Skip to content

Commit 061915e

Browse files
committed
refactor(uninterpreted): pass delimiter to IsComplete and DRY readUninterpreted
Change UninterpretedConfig.IsComplete to func(accumulated, delimiter string) bool so the callback receives the delimiter currently in effect without the consumer having to capture the shell. Collapse the duplicated terminator logic in readUninterpreted into a single predicate plus a lineIsComplete helper, and make readMultiLinesFunc delegate to readMultiLinesAccumFunc to remove the duplicated accumulation loop. Refs: dolthub/dolt#10866
1 parent 9a5c1e6 commit 061915e

1 file changed

Lines changed: 47 additions & 101 deletions

File tree

ishell.go

Lines changed: 47 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ type Shell struct {
6565
specialTerminators []string
6666
backSlashCmds []string
6767
quitKeywords []string
68-
isComplete func(accumulated string) bool
68+
isComplete func(accumulated, delimiter string) bool
6969
contextValues
7070
Actions
7171
}
@@ -81,14 +81,10 @@ type UninterpretedConfig struct {
8181
BackSlashCmds []string
8282
// Quit keywords to exit the shell if discovered
8383
QuitKeywords []string
84-
// IsComplete, when non-nil, replaces the per-line LineTerminator suffix
85-
// check in readUninterpreted. It is called after each physical line is
86-
// read with the cumulative buffer (lines joined by "\n", matching the
87-
// final delivered string). Returning true ends accumulation. Special
88-
// terminators, backslash commands, and quit keywords still apply on top
89-
// of IsComplete; first-line DELIMITER detection and the leading "--"
90-
// short-circuit also still apply.
91-
IsComplete func(accumulated string) bool
84+
// IsComplete, when set, replaces the LineTerminator suffix check: it is
85+
// called with the cumulative buffer and current delimiter and returns true
86+
// when accumulation should stop.
87+
IsComplete func(accumulated, delimiter string) bool
9288
}
9389

9490
// New creates a new shell with default settings. Uses standard output and default prompt ">> ".
@@ -376,72 +372,24 @@ func (s *Shell) readUninterpreted() (string, error) {
376372

377373
if s.lineTerminator != "" {
378374
firstLine := true
379-
if s.isComplete != nil {
380-
lines, err = s.readMultiLinesAccumFunc(func(line, accumulated string) (keepReading bool) {
381-
if firstLine {
382-
firstLine = false
383-
if matches := delimiterRegex.FindStringSubmatch(line); len(matches) == 2 {
384-
s.lineTerminator = matches[1]
385-
return false
386-
}
387-
if strings.HasPrefix(line, "--") {
388-
return false
389-
}
390-
for _, keyword := range s.quitKeywords {
391-
if strings.TrimSpace(line) == keyword {
392-
return false
393-
}
394-
}
395-
}
396-
397-
for _, sc := range s.specialTerminators {
398-
if strings.HasSuffix(strings.TrimSpace(line), sc) {
399-
return false
400-
}
401-
}
402-
for _, sc := range s.backSlashCmds {
403-
if strings.HasPrefix(strings.TrimSpace(line), sc) {
404-
return false
405-
}
406-
}
407-
408-
return !s.isComplete(accumulated)
409-
})
410-
} else {
411-
lines, err = s.readMultiLinesFunc(func(line string) (keepReading bool) {
412-
if firstLine {
413-
firstLine = false
414-
if matches := delimiterRegex.FindStringSubmatch(line); len(matches) == 2 {
415-
s.lineTerminator = matches[1]
416-
return false
417-
}
418-
if strings.HasPrefix(line, "--") {
419-
return false
420-
}
421-
for _, keyword := range s.quitKeywords {
422-
if strings.TrimSpace(line) == keyword {
423-
return false
424-
}
425-
}
426-
}
427-
428-
if strings.HasSuffix(strings.TrimSpace(line), s.lineTerminator) {
375+
lines, err = s.readMultiLinesAccumFunc(func(line, accumulated string) (keepReading bool) {
376+
if firstLine {
377+
firstLine = false
378+
if matches := delimiterRegex.FindStringSubmatch(line); len(matches) == 2 {
379+
s.lineTerminator = matches[1]
429380
return false
430381
}
431-
for _, sc := range s.specialTerminators {
432-
if strings.HasSuffix(strings.TrimSpace(line), sc) {
433-
return false
434-
}
382+
if strings.HasPrefix(line, "--") {
383+
return false
435384
}
436-
for _, sc := range s.backSlashCmds {
437-
if strings.HasPrefix(strings.TrimSpace(line), sc) {
385+
for _, keyword := range s.quitKeywords {
386+
if strings.TrimSpace(line) == keyword {
438387
return false
439388
}
440389
}
441-
442-
return true
443-
})
444-
}
390+
}
391+
return !s.lineIsComplete(line, accumulated)
392+
})
445393

446394
if err != nil {
447395
return "", err
@@ -480,6 +428,27 @@ func (s *Shell) readUninterpreted() (string, error) {
480428
return lines, nil
481429
}
482430

431+
// lineIsComplete reports whether reading should stop: special terminators and
432+
// backslash commands always end input, otherwise it defers to IsComplete or the
433+
// line-terminator suffix check.
434+
func (s *Shell) lineIsComplete(line, accumulated string) bool {
435+
trimmed := strings.TrimSpace(line)
436+
for _, sc := range s.specialTerminators {
437+
if strings.HasSuffix(trimmed, sc) {
438+
return true
439+
}
440+
}
441+
for _, sc := range s.backSlashCmds {
442+
if strings.HasPrefix(trimmed, sc) {
443+
return true
444+
}
445+
}
446+
if s.isComplete != nil {
447+
return s.isComplete(accumulated, s.lineTerminator)
448+
}
449+
return strings.HasSuffix(trimmed, s.lineTerminator)
450+
}
451+
483452
func (s *Shell) read() ([]string, error) {
484453
s.rawArgs = nil
485454
eof := ""
@@ -526,44 +495,21 @@ func (s *Shell) read() ([]string, error) {
526495
}
527496

528497
func (s *Shell) readMultiLinesFunc(f func(string) (keepReading bool)) (string, error) {
529-
var lines bytes.Buffer
530-
currentLine := 0
531-
var err error
532-
for {
533-
if currentLine == 1 {
534-
// from second line, enable next line prompt.
535-
s.reader.setMultiMode(true)
536-
}
537-
var line string
538-
line, err = s.readLine()
539-
fmt.Fprint(&lines, line)
540-
if !f(line) || err != nil {
541-
break
542-
}
543-
fmt.Fprintln(&lines)
544-
currentLine++
545-
}
546-
if currentLine > 0 {
547-
// if more than one line is read
548-
// revert to standard prompt.
549-
s.reader.setMultiMode(false)
550-
}
551-
return lines.String(), err
498+
return s.readMultiLinesAccumFunc(func(line, _ string) bool {
499+
return f(line)
500+
})
552501
}
553502

554-
// readMultiLinesAccumFunc is a sibling of readMultiLinesFunc that passes
555-
// both the most recent physical line and the cumulative buffer to the
556-
// predicate. The cumulative buffer matches what readMultiLinesFunc would
557-
// produce: physical lines joined by "\n" with no trailing newline on the
558-
// terminating line.
503+
// readMultiLinesAccumFunc accumulates physical lines until the predicate
504+
// returns false. The predicate receives the latest line and the cumulative
505+
// buffer (lines joined by "\n").
559506
func (s *Shell) readMultiLinesAccumFunc(f func(line, accumulated string) (keepReading bool)) (string, error) {
560507
return readMultiLinesAccumFromReader(s.readLine, s.reader.setMultiMode, f)
561508
}
562509

563-
// readMultiLinesAccumFromReader is the inner accumulation loop used by
564-
// readMultiLinesAccumFunc. It is parameterized on the line reader and the
565-
// multi-mode toggle so unit tests can drive it without a real readline
566-
// instance.
510+
// readMultiLinesAccumFromReader is the inner accumulation loop, parameterized
511+
// on the line reader and multi-mode toggle so tests can drive it without a real
512+
// readline instance.
567513
func readMultiLinesAccumFromReader(
568514
readLine func() (string, error),
569515
setMulti func(bool),

0 commit comments

Comments
 (0)