bash.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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("compopt +o nospace")
  32. f("COMP_WORDS[%d]=%s", n, utils.QuoteStringForSH(completions[0].Delegate.Command))
  33. f("_command_offset %d", n)
  34. } else {
  35. for _, mg := range completions[0].Groups {
  36. mg.remove_common_prefix()
  37. if mg.NoTrailingSpace {
  38. f("compopt -o nospace")
  39. } else {
  40. f("compopt +o nospace")
  41. }
  42. if mg.IsFiles {
  43. f("compopt -o filenames")
  44. for _, m := range mg.Matches {
  45. if strings.HasSuffix(m.Word, utils.Sep) {
  46. m.Word = m.Word[:len(m.Word)-1]
  47. }
  48. }
  49. } else {
  50. f("compopt +o filenames")
  51. }
  52. for _, m := range mg.Matches {
  53. f("COMPREPLY+=(%s)", utils.QuoteStringForSH(m.Word))
  54. }
  55. }
  56. }
  57. // debugf("%#v", output.String())
  58. return []byte(output.String()), nil
  59. }
  60. func bash_init_completions(completions *Completions) {
  61. completions.split_on_equals = true
  62. }
  63. func init() {
  64. completion_scripts["bash"] = bash_completion_script
  65. input_parsers["bash"] = shell_input_parser
  66. output_serializers["bash"] = bash_output_serializer
  67. init_completions["bash"] = bash_init_completions
  68. }