Separate tree-sitter and non-tree-sitter variant of sh-mode

Now there are three modes, sh-base-mode, sh-mode, bash-ts-mode.

The change I made: change sh-mode to sh-base-mode, remove docstring.
Below the new sh-base-mode, create a new definition for sh-mode, paste
the dostring, add setup for font-lock-defaults.  Below sh-mode, add
bash-ts-mode.

* lisp/progmodes/sh-script.el (sh-mode): Moves all setup into
sh-base-mode, except for the setup for font-lock-defaults and the
docstring.
(sh-base-mode): New mode.
(bash-ts-mode): New mode.
This commit is contained in:
Yuan Fu 2022-11-22 00:49:04 -08:00
parent e494ca4f4d
commit 1161c96cc9
No known key found for this signature in database
GPG key ID: 56E19BC57664A442

View file

@ -1469,57 +1469,12 @@ When the region is active, send the region instead."
(defvar sh-mode--treesit-settings)
;;;###autoload
(define-derived-mode sh-mode prog-mode "Shell-script"
"Major mode for editing shell scripts.
This mode works for many shells, since they all have roughly the same syntax,
as far as commands, arguments, variables, pipes, comments etc. are concerned.
Unless the file's magic number indicates the shell, your usual shell is
assumed. Since filenames rarely give a clue, they are not further analyzed.
(define-derived-mode sh-base-mode prog-mode "Shell-script"
"Generic major mode for editing shell scripts.
This mode adapts to the variations between shells (see `sh-set-shell') by
means of an inheritance based feature lookup (see `sh-feature'). This
mechanism applies to all variables (including skeletons) that pertain to
shell-specific features. Shell script files can use the `sh-shell' local
variable to indicate the shell variant to be used for the file.
The default style of this mode is that of Rosenblatt's Korn shell book.
The syntax of the statements varies with the shell being used. The
following commands are available, based on the current shell's syntax:
\\<sh-mode-map>
\\[sh-case] case statement
\\[sh-for] for loop
\\[sh-function] function definition
\\[sh-if] if statement
\\[sh-indexed-loop] indexed loop from 1 to n
\\[sh-while-getopts] while getopts loop
\\[sh-repeat] repeat loop
\\[sh-select] select loop
\\[sh-until] until loop
\\[sh-while] while loop
For sh and rc shells indentation commands are:
\\[smie-config-show-indent] Show the rules controlling this line's indentation.
\\[smie-config-set-indent] Change the rules controlling this line's indentation.
\\[smie-config-guess] Try to tweak the indentation rules so the
buffer indents as it currently is indented.
\\[backward-delete-char-untabify] Delete backward one position, even if it was a tab.
\\[sh-end-of-command] Go to end of successive commands.
\\[sh-beginning-of-command] Go to beginning of successive commands.
\\[sh-set-shell] Set this buffer's shell, and maybe its magic number.
\\[sh-execute-region] Have optional header and region be executed in a subshell.
`sh-electric-here-document-mode' controls whether insertion of two
unquoted < insert a here document. You can control this behavior by
modifying `sh-mode-hook'.
If you generally program a shell different from your login shell you can
set `sh-shell-file' accordingly. If your shell's file name doesn't correctly
indicate what shell it is use `sh-alias-alist' to translate.
If your shell gives error messages with line numbers, you can use \\[executable-interpret]
with your script for an edit-interpret-debug cycle."
This is a generic major mode intended to be inherited by concrete
implementations. Currently there are two: `sh-mode' and
`bash-ts-mode'."
(make-local-variable 'sh-shell-file)
(make-local-variable 'sh-shell)
@ -1583,31 +1538,82 @@ with your script for an edit-interpret-debug cycle."
nil nil)
(add-hook 'flymake-diagnostic-functions #'sh-shellcheck-flymake nil t)
(add-hook 'hack-local-variables-hook
#'sh-after-hack-local-variables nil t)
#'sh-after-hack-local-variables nil t))
(cond
;; Tree-sitter. If the shell is bash, we can enable tree-sitter.
((treesit-ready-p sh-shell)
;;;###autoload
(define-derived-mode sh-mode sh-base-mode "Shell-script"
"Major mode for editing shell scripts.
This mode works for many shells, since they all have roughly the same syntax,
as far as commands, arguments, variables, pipes, comments etc. are concerned.
Unless the file's magic number indicates the shell, your usual shell is
assumed. Since filenames rarely give a clue, they are not further analyzed.
This mode adapts to the variations between shells (see `sh-set-shell') by
means of an inheritance based feature lookup (see `sh-feature'). This
mechanism applies to all variables (including skeletons) that pertain to
shell-specific features. Shell script files can use the `sh-shell' local
variable to indicate the shell variant to be used for the file.
The default style of this mode is that of Rosenblatt's Korn shell book.
The syntax of the statements varies with the shell being used. The
following commands are available, based on the current shell's syntax:
\\<sh-mode-map>
\\[sh-case] case statement
\\[sh-for] for loop
\\[sh-function] function definition
\\[sh-if] if statement
\\[sh-indexed-loop] indexed loop from 1 to n
\\[sh-while-getopts] while getopts loop
\\[sh-repeat] repeat loop
\\[sh-select] select loop
\\[sh-until] until loop
\\[sh-while] while loop
For sh and rc shells indentation commands are:
\\[smie-config-show-indent] Show the rules controlling this line's indentation.
\\[smie-config-set-indent] Change the rules controlling this line's indentation.
\\[smie-config-guess] Try to tweak the indentation rules so the
buffer indents as it currently is indented.
\\[backward-delete-char-untabify] Delete backward one position, even if it was a tab.
\\[sh-end-of-command] Go to end of successive commands.
\\[sh-beginning-of-command] Go to beginning of successive commands.
\\[sh-set-shell] Set this buffer's shell, and maybe its magic number.
\\[sh-execute-region] Have optional header and region be executed in a subshell.
`sh-electric-here-document-mode' controls whether insertion of two
unquoted < insert a here document. You can control this behavior by
modifying `sh-mode-hook'.
If you generally program a shell different from your login shell you can
set `sh-shell-file' accordingly. If your shell's file name doesn't correctly
indicate what shell it is use `sh-alias-alist' to translate.
If your shell gives error messages with line numbers, you can use \\[executable-interpret]
with your script for an edit-interpret-debug cycle."
(setq font-lock-defaults
`((sh-font-lock-keywords
sh-font-lock-keywords-1 sh-font-lock-keywords-2)
nil nil
((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
(font-lock-syntactic-face-function
. ,#'sh-font-lock-syntactic-face-function))))
;;;###autoload
(defalias 'shell-script-mode 'sh-mode)
;;;###autoload
(define-derived-mode bash-ts-mode sh-base-mode "Bash"
"Major mode for editing Bash shell scripts."
(when (treesit-ready-p 'bash)
(setq-local treesit-font-lock-feature-list
'((comment function string heredoc)
(variable keyword command declaration-command)
(constant operator builtin-variable)))
(setq-local treesit-font-lock-settings
sh-mode--treesit-settings)
(treesit-major-mode-setup))
;; Elisp.
(t
(setq font-lock-defaults
`((sh-font-lock-keywords
sh-font-lock-keywords-1 sh-font-lock-keywords-2)
nil nil
((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
(font-lock-syntactic-face-function
. ,#'sh-font-lock-syntactic-face-function))))))
;;;###autoload
(defalias 'shell-script-mode 'sh-mode)
(treesit-major-mode-setup)))
(defun sh-font-lock-keywords (&optional keywords)
"Function to get simple fontification based on `sh-font-lock-keywords'.