diff --git a/internal/complete/complete.go b/internal/complete/complete.go index 8003987..9af8ed9 100644 --- a/internal/complete/complete.go +++ b/internal/complete/complete.go @@ -37,6 +37,7 @@ var globals = []string{ "Object.fromEntries", "Array.isArray", "Array.from", + "console.log", "len", "uniq", "sort", @@ -49,12 +50,13 @@ var globals = []string{ "reverse", "keys", "values", + "skip", } func Complete() bool { compLine, ok := os.LookupEnv("COMP_LINE") - if ok && len(os.Args) == 3 { + if ok && len(os.Args) >= 3 { doComplete(compLine, os.Args[2]) return true } @@ -65,6 +67,12 @@ func Complete() bool { return true } + compFish, ok := os.LookupEnv("COMP_FISH") + if ok { + doComplete(compFish, lastWord(compFish)) + return true + } + return false } @@ -108,11 +116,11 @@ func doComplete(compLine string, compWord string) { isSecondArgIsFile = isFile(args[1]) } - if isSecondArgIsFile { - if globalsComplete(compWord) { - return - } + if globalsComplete(compWord) { + return + } + if isSecondArgIsFile { file := args[1] hasYamlExt, _ := regexp.MatchString(`(?i)\.ya?ml$`, file) @@ -190,12 +198,25 @@ func codeComplete(input string, args []string, compWord string) { prefix := dropTail(compWord) var reply []string for _, key := range array { - reply = append(reply, prefix+key.(string)) + reply = append(reply, join(prefix, key.(string))) } compReply(filterReply(reply, compWord)) } } +var alphaRe = regexp.MustCompile(`^\w+$`) + +func join(prefix, key string) string { + if alphaRe.MatchString(key) { + return prefix + "." + key + } else { + if prefix == "" { + return fmt.Sprintf(".[%q]", key) + } + return fmt.Sprintf("%s[%q]", prefix, key) + } +} + func filterArgs(args []string) []string { filtered := make([]string, 0, len(args)) for _, arg := range args { diff --git a/internal/complete/fish.go b/internal/complete/fish.go new file mode 100644 index 0000000..a25a4b3 --- /dev/null +++ b/internal/complete/fish.go @@ -0,0 +1,6 @@ +package complete + +func Fish() string { + return `complete --command fx --arguments '(COMP_FISH=(commandline -cp) fx)' +` +} diff --git a/internal/complete/prelude.go b/internal/complete/prelude.go index a6960ef..a51adac 100644 --- a/internal/complete/prelude.go +++ b/internal/complete/prelude.go @@ -8,11 +8,7 @@ Object.prototype.__keys = function () { if (typeof this === 'string') return if (this instanceof String) return if (typeof this === 'object' && this !== null) - Object.keys(this) - .forEach(x => /^\w+$/.test(x) ? - __keys.add('.' + x) : - __keys.add('.[' + JSON.stringify(x) + ']') - ) + Object.keys(this).forEach(x => __keys.add(x)) } function apply(fn, ...args) { diff --git a/internal/complete/utils.go b/internal/complete/utils.go index 277ca0e..d27c38c 100644 --- a/internal/complete/utils.go +++ b/internal/complete/utils.go @@ -3,14 +3,11 @@ package complete import ( "fmt" "os" - "regexp" "strings" ) func compReply(reply []string) { - for _, word := range reply { - fmt.Println(word) - } + fmt.Print(strings.Join(reply, "\n")) } func filterReply(reply []string, compWord string) []string { @@ -31,10 +28,9 @@ func isFile(path string) bool { return !info.IsDir() } -var tailRe = regexp.MustCompile(`\.?\w*$`) - func dropTail(s string) string { - return tailRe.ReplaceAllString(s, "") + parts := strings.Split(s, ".") + return strings.Join(parts[:len(parts)-1], ".") } func balanceBrackets(code string) string { diff --git a/main.go b/main.go index 437bcd4..b1b57d2 100644 --- a/main.go +++ b/main.go @@ -89,6 +89,8 @@ func main() { fmt.Print(complete.Bash()) case "zsh": fmt.Print(complete.Zsh()) + case "fish": + fmt.Print(complete.Fish()) default: fmt.Println("unknown shell type") } @@ -176,9 +178,14 @@ func main() { lipgloss.SetColorProfile(termOutput.ColorProfile()) + withMouse := tea.WithMouseCellMotion() + if _, ok := os.LookupEnv("FX_NO_MOUSE"); ok { + withMouse = tea.WithAltScreen() + } + p := tea.NewProgram(m, tea.WithAltScreen(), - tea.WithMouseCellMotion(), + withMouse, tea.WithOutput(os.Stderr), ) _, err = p.Run() @@ -422,7 +429,7 @@ func (m *model) handleYankKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { _ = clipboard.WriteAll(m.cursorPath()) case key.Matches(msg, yankKey): _ = clipboard.WriteAll(m.cursorKey()) - case key.Matches(msg, yankValue): + case key.Matches(msg, yankValueY, yankValueV): _ = clipboard.WriteAll(m.cursorValue()) } m.yank = false