Skip to content

Commit

Permalink
more
Browse files Browse the repository at this point in the history
  • Loading branch information
mvdan committed Jul 31, 2024
1 parent 4ccfb30 commit ea8c67d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
76 changes: 76 additions & 0 deletions example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"bytes"
"fmt"
"io"
"os"

"mvdan.cc/sh/v3/syntax"
)

func main() {
src, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
p := syntax.NewParser(syntax.RecoverErrors(5))
f, err := p.Parse(bytes.NewReader(src), "")
if err != nil {
panic(err)
}

last := lastStmt(f)
compl := extractCompletion(last, string(src))
fmt.Printf("%#v\n", compl)
}

func lastStmt(node syntax.Node) *syntax.Stmt {
var last *syntax.Stmt
// TODO: keep the first incomplete statement, too
syntax.Walk(node, func(node syntax.Node) bool {
if stmt, _ := node.(*syntax.Stmt); stmt != nil {
last = stmt
}
return true
})
return last
}

func extractCompletion(stmt *syntax.Stmt, src string) compResult {
syntax.DebugPrint(os.Stderr, stmt)
if len(stmt.Redirs) > 0 {
lastRedir := stmt.Redirs[len(stmt.Redirs)-1]
// fmt.Println(lastRedir.Word.Pos())
// fmt.Fprintln(os.Stderr, lastRedir.Word.Pos())
if lastRedir.Word.Pos().IsRecovered() {
return compResult{"redirect", nil}
}
}
if call, _ := stmt.Cmd.(*syntax.CallExpr); call != nil {
flat := flatWords(call.Args, src)
if stmt.End().Offset() < uint(len(src)) {
// Starting a new word.
flat = append(flat, "")
}
return compResult{"args", flat}
}

// other commands, e.g. "if foo; then bar; fi"
return compResult{}
}

func flatWords(words []*syntax.Word, src string) []string {
var flat []string
for _, word := range words {
start := word.Pos().Offset()
end := word.End().Offset()
flat = append(flat, src[start:end])
}
return flat
}

type compResult struct {
Type string
Tokens []string
}
4 changes: 4 additions & 0 deletions syntax/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2565,6 +2565,10 @@ func TestParseRecoverErrors(t *testing.T) {
// src: "incomp >",
// wantRecoveredPos: 1,
// },
{
src: "${incomp",
wantRecoveredPos: 1,
},
{
src: "badsyntax)",
wantErr: true,
Expand Down
4 changes: 4 additions & 0 deletions syntax/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ func (p *debugPrinter) print(x reflect.Value) {

case reflect.Struct:
if v, ok := x.Interface().(Pos); ok {
if v.IsRecovered() {
p.printf("<recovered>")
return
}
p.printf("%v:%v", v.Line(), v.Col())
return
}
Expand Down

0 comments on commit ea8c67d

Please sign in to comment.