Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/unreleased/repl-usage-error-lines.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **The terminal prompt prints every line of a usage error.** A repository or notebook command given wrong arguments — `%load --id x`, `%load --id=a --id=b`, `%load --tags=a a.ipynb` — printed only the usage line at the prompt, leaving out the line saying what was wrong (`--id is not an option of %load`), which the Jupyter kernel's `UsageError` traceback showed. The prompt now prints the usage and the problem, as the kernel does.
12 changes: 11 additions & 1 deletion internal/frontend/repl/loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func Loop(r LineReader, out io.Writer, s *Session) error {
printLines(w, metaOut)
_ = w.Flush()
if merr != nil {
printLines(w, []string{"error: " + merr.Error()})
printLines(w, metaErrorLines(merr))
_ = w.Flush()
}
if quit {
Expand Down Expand Up @@ -124,6 +124,16 @@ func bareExpression(src string) (string, bool) {
return trimmed, true
}

// metaErrorLines prints a meta command's error: every line of a usage error,
// the first under the error prefix as the kernel's value; other errors as before.
func metaErrorLines(err error) []string {
var usage *UsageError
if errors.As(err, &usage) && len(usage.Lines) > 0 {
return append([]string{errPrefix + usage.Error()}, usage.Lines[1:]...)
}
return []string{errPrefix + err.Error()}
}

func printLines(w io.Writer, lines []string) {
for _, l := range lines {
_, _ = io.WriteString(w, l+"\n")
Expand Down
19 changes: 19 additions & 0 deletions internal/frontend/repl/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ func wantUsage(t *testing.T, err error, line string) {

func joined(lines []string) string { return strings.Join(lines, "\n") }

// TestLoopPrintsEveryLineOfAUsageError drives repository usage errors through the
// terminal loop: the usage line under the error prefix, then what was wrong.
func TestLoopPrintsEveryLineOfAUsageError(t *testing.T) {
repoSession(t)
var out strings.Builder
if err := Loop(&scriptReader{lines: []string{"%load --id x", "%load --id=a --id=b", "%projects now"}}, &out, NewSession()); err != nil {
t.Fatalf("Loop error: %v", err)
}
got := strings.Split(strings.TrimSuffix(out.String(), "\n"), "\n")
want := []string{
"error: " + usageLoadRepo, "--id is not an option of %load",
"error: " + usageLoadRepo, "--id was given twice",
"error: " + usageProjects,
}
if strings.Join(got, "\n") != strings.Join(want, "\n") {
t.Errorf("the loop printed:\n%s\nwant:\n%s", strings.Join(got, "\n"), strings.Join(want, "\n"))
}
}

func TestRepoShowsAndSetsTheBaseURL(t *testing.T) {
s, api := repoSession(t)
if got := joined(runMeta(t, s, "%repo")); got != "API base path: "+api.URL() {
Expand Down
Loading