bash.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package cli
  3. import (
  4. "fmt"
  5. "strings"
  6. "kitty/tools/utils"
  7. )
  8. var _ = fmt.Print
  9. func bash_completion_script(commands []string) (string, error) {
  10. return `_ksi_completions() {
  11. builtin local src
  12. builtin local limit
  13. # Send all words up to the word the cursor is currently on
  14. builtin let limit=1+$COMP_CWORD
  15. src=$(builtin printf "%s\n" "${COMP_WORDS[@]:0:$limit}" | builtin command kitten __complete__ bash)
  16. if [[ $? == 0 ]]; then
  17. builtin eval "${src}"
  18. fi
  19. }
  20. builtin complete -F _ksi_completions kitty
  21. builtin complete -F _ksi_completions edit-in-kitty
  22. builtin complete -F _ksi_completions clone-in-kitty
  23. builtin complete -F _ksi_completions kitten
  24. `, nil
  25. }
  26. func bash_output_serializer(completions []*Completions, shell_state map[string]string) ([]byte, error) {
  27. output := strings.Builder{}
  28. f := func(format string, args ...any) { fmt.Fprintf(&output, format+"\n", args...) }
  29. n := completions[0].Delegate.NumToRemove
  30. if n > 0 {
  31. f("if builtin declare -F _command_offset >/dev/null; then")
  32. f(" compopt +o nospace")
  33. f(" COMP_WORDS[%d]=%s", n, utils.QuoteStringForSH(completions[0].Delegate.Command))
  34. f(" _command_offset %d", n)
  35. f("fi")
  36. } else {
  37. for _, mg := range completions[0].Groups {
  38. mg.remove_common_prefix()
  39. if mg.NoTrailingSpace {
  40. f("compopt -o nospace")
  41. } else {
  42. f("compopt +o nospace")
  43. }
  44. if mg.IsFiles {
  45. f("compopt -o filenames")
  46. for _, m := range mg.Matches {
  47. if strings.HasSuffix(m.Word, utils.Sep) {
  48. m.Word = m.Word[:len(m.Word)-1]
  49. }
  50. }
  51. } else {
  52. f("compopt +o filenames")
  53. }
  54. for _, m := range mg.Matches {
  55. f("COMPREPLY+=(%s)", utils.QuoteStringForSH(m.Word))
  56. }
  57. }
  58. }
  59. // debugf("%#v", output.String())
  60. return []byte(output.String()), nil
  61. }
  62. func bash_init_completions(completions *Completions) {
  63. completions.split_on_equals = true
  64. }
  65. func init() {
  66. completion_scripts["bash"] = bash_completion_script
  67. input_parsers["bash"] = shell_input_parser
  68. output_serializers["bash"] = bash_output_serializer
  69. init_completions["bash"] = bash_init_completions
  70. }