Commit 84bfbb44 authored by Karl Heuer's avatar Karl Heuer
Browse files

(sh-shells): Eliminated variable redundant with

`interpreter-mode-alist'.
(sh-beginning-of-command): Take into account \quoted newline.
(sh-builtins, sh-leading-keywords, sh-other-keywords): Now three
distinct sets for font-locking.
(sh-font-lock-keywords-1, sh-font-lock-keywords-2): New variables
and functions to give the user finer control over how much to fontify,
including new distinction between keywords and builtins.
(sh-mode): Use new features of `font-lock-defaults' and adaptation
to skeleton changes.
(sh-while): Fix csh, es & rc skeletons.
parent da6a884f
......@@ -138,12 +138,6 @@ Use this where the name of the executable doesn't correspond to the type of
shell it really is.")
(defvar sh-shells
'(("ash") ("bash") ("csh") ("dtksh") ("es") ("itcsh") ("jsh") ("ksh")
("oash") ("pdksh") ("rc") ("sh") ("tcsh") ("wksh") ("wsh") ("zsh"))
"*Alist of shells available for completing read in `sh-set-shell'.")
(defvar sh-shell-path (or (getenv "SHELL") "/bin/sh")
"*The executable of the shell being programmed.")
......@@ -347,13 +341,13 @@ That command is also used for setting this variable.")
(defvar sh-beginning-of-command
"\\([;({`|&]\\|^\\)[ \t]*\\([/~:a-zA-Z0-9]\\)"
"\\([;({`|&]\\|\\`\\|[^\\]\n\\)[ \t]*\\([/~a-zA-Z0-9:]\\)"
"*Regexp to determine the beginning of a shell command.
The actual command starts at the beginning of the second \\(grouping\\).")
(defvar sh-end-of-command
"\\([/~:a-zA-Z0-9]\\)[ \t]*\\([;#)}`|&]\\|$\\)"
"\\([/~a-zA-Z0-9:]\\)[ \t]*\\([;#)}`|&]\\|$\\)"
"*Regexp to determine the end of a shell command.
The actual command ends at the end of the first \\(grouping\\).")
......@@ -369,28 +363,24 @@ The actual command ends at the end of the first \\(grouping\\).")
(defvar sh-builtins
'((bash eval sh-append sh
"alias" "bg" "bind" "builtin" "bye" "command" "declare" "dirs"
"enable" "fc" "fg" "function" "help" "history" "jobs" "kill" "let"
"local" "logout" "popd" "pushd" "source" "suspend" "typeset"
"unalias")
'((bash eval sh-append posix
"alias" "bg" "bind" "builtin" "declare" "dirs" "enable" "fc" "fg"
"help" "history" "jobs" "kill" "let" "local" "popd" "pushd" "source"
"suspend" "typeset" "unalias")
;; The next entry is only used for defining the others
(bourne eval sh-append shell
"do" "done" "elif" "esac" "export" "fi" "for" "getopts" "in"
"newgrp" "pwd" "read" "readonly" "return" "times" "trap" "ulimit"
"until")
"eval" "export" "getopts" "newgrp" "pwd" "read" "readonly"
"times" "ulimit")
(csh eval sh-append shell
"alias" "breaksw" "chdir" "default:" "end" "endif" "endsw" "foreach"
"glob" "goto" "history" "limit" "logout" "nice" "nohup" "onintr"
"rehash" "repeat" "setenv" "source" "switch" "time" "unalias"
"unhash")
"alias" "chdir" "glob" "history" "limit" "nice" "nohup" "rehash"
"setenv" "source" "time" "unalias" "unhash")
(dtksh eval identity wksh)
(es "access" "apids" "break" "catch" "cd" "echo" "eval" "exec" "exit"
"false" "fn" "for" "forever" "fork" "if" "let" "limit" "local"
"newpgrp" "result" "return" "throw" "time" "true" "umask"
"unwind-protect" "var" "vars" "wait" "whatis" "while")
(es "access" "apids" "cd" "echo" "eval" "false" "let" "limit" "local"
"newpgrp" "result" "time" "umask" "var" "vars" "wait" "whatis")
(jsh eval sh-append sh
"bg" "fg" "jobs" "kill" "stop" "suspend")
......@@ -399,8 +389,8 @@ The actual command ends at the end of the first \\(grouping\\).")
"bg" "fg" "jobs" "kill" "notify" "stop" "suspend")
(ksh88 eval sh-append bourne
"alias" "bg" "false" "fc" "fg" "function" "jobs" "kill" "let"
"print" "select" "time" "typeset" "unalias" "whence")
"alias" "bg" "false" "fc" "fg" "jobs" "kill" "let" "print" "time"
"typeset" "unalias" "whence")
(oash eval sh-append sh
"checkwin" "dateline" "error" "form" "menu" "newwin" "oadeinit"
......@@ -414,55 +404,72 @@ The actual command ends at the end of the first \\(grouping\\).")
(posix eval sh-append sh
"command")
(rc "break" "builtin" "case" "cd" "echo" "else" "eval" "exec" "exit" "fn"
"for" "if" "in" "limit" "newpgrp" "return" "shift" "switch" "umask"
"wait" "whatis" "while")
(rc "builtin" "cd" "echo" "eval" "limit" "newpgrp" "shift" "umask" "wait"
"whatis")
(sh eval sh-append bourne
"hash" "test" "type")
;; The next entry is only used for defining the others
(shell "break" "case" "cd" "continue" "echo" "else" "eval" "exec" "exit"
"if" "set" "shift" "then" "umask" "unset" "wait" "while")
(shell "cd" "echo" "eval" "set" "shift" "umask" "unset" "wait")
(wksh eval sh-append ksh88
"Xt[A-Z][A-Za-z]*")
(zsh eval sh-append ksh88
"autoload" "bindkey" "builtin" "bye" "chdir" "compctl" "declare"
"dirs" "disable" "disown" "echotc" "enable" "functions" "getln"
"hash" "history" "integer" "limit" "local" "log" "logout" "popd"
"pushd" "r" "readonly" "rehash" "sched" "setopt" "source" "suspend"
"true" "ttyctl" "type" "unfunction" "unhash" "unlimit" "unsetopt"
"vared" "which"))
"autoload" "bindkey" "builtin" "chdir" "compctl" "declare" "dirs"
"disable" "disown" "echotc" "enable" "functions" "getln" "hash"
"history" "integer" "limit" "local" "log" "popd" "pushd" "r"
"readonly" "rehash" "sched" "setopt" "source" "suspend" "true"
"ttyctl" "type" "unfunction" "unhash" "unlimit" "unsetopt" "vared"
"which"))
"*List of all shell builtins for completing read and fontification.
Note that on some systems not all builtins are available or some are
implemented as aliases. See `sh-feature'.")
(defvar sh-leading-keywords
'((bash eval sh-append sh
"builtin" "command" "enable")
'((csh "else")
(es "true" "unwind-protect" "whatis")
(rc "else")
(sh "do" "elif" "else" "if" "then" "trap" "type" "until" "while"))
"*List of keywords that may be immediately followed by a builtin or keyword.
Given some confusion between keywords and builtins depending on shell and
system, the distinction here has been based on whether they influence the
flow of control or syntax. See `sh-feature'.")
(defvar sh-other-keywords
'((bash eval sh-append bourne
"bye" "logout")
;; The next entry is only used for defining the others
(bourne "do" "elif" "else" "eval" "if" "then" "trap" "until" "while")
(bourne eval sh-append shell
"done" "esac" "fi" "for" "function" "in" "return")
(csh "else")
(csh eval sh-append shell
"breaksw" "default" "end" "endif" "endsw" "foreach" "goto"
"if" "logout" "onintr" "repeat" "switch" "then" "while")
(es "eval" "time" "true" "umask"
"unwind-protect" "whatis")
(es "break" "catch" "exec" "exit" "fn" "for" "forever" "fork" "if"
"return" "throw" "while")
(ksh88 eval sh-append bourne
"time" "whence")
"select")
(posix eval sh-append sh
"command")
(rc "builtin" "else" "eval" "whatis")
(rc "break" "case" "exec" "exit" "fn" "for" "if" "in" "return" "switch"
"while")
(sh eval sh-append bourne
"type")
;; The next entry is only used for defining the others
(shell "break" "case" "continue" "exec" "exit")
(zsh eval sh-append ksh88
"builtin" "disable" "enable" "type" "unhash" "which"))
"*List of keywords that may be immediately followed by a command(-name).
(zsh eval sh-append bash
"select"))
"*List of keywords not in `sh-leading-keywords'.
See `sh-feature'.")
......@@ -540,31 +547,30 @@ See `sh-feature'.")
'("\\${?[#?]?\\([A-Za-z_][A-Za-z0-9_]*\\|0\\)" 1
font-lock-variable-name-face))
(dtksh eval identity wksh)
(es eval sh-append executable-font-lock-keywords
'("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1
font-lock-variable-name-face))
(rc eval sh-append es
'("\\(^\\|[ \t]\\)\\(else\\( if\\)?\\)\\>" 2
font-lock-keyword-face t))
(rc eval identity es)
(sh eval sh-append shell
'("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2
font-lock-variable-name-face)
" in\\([ \t]\\|$\\)")
font-lock-variable-name-face))
;; The next entry is only used for defining the others
(shell eval sh-append executable-font-lock-keywords
'("\\\\." 0 font-lock-string-face)
'("\\${?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\|[$*_]\\)" 1
font-lock-variable-name-face))
(wksh eval sh-append ksh88
'("\\(^\\|[^-._A-Za-z0-9]\\)\\(Xt[A-Z][A-Za-z]*\\)\\($\\|[^-._A-Za-z0-9]\\)" 2 font-lock-keyword-face)))
font-lock-variable-name-face)))
"*Rules for highlighting shell scripts. See `sh-feature'.")
(defvar sh-font-lock-keywords-1
'((sh "[ \t]in[ \t]"))
"*Additional rules for highlighting shell scripts. See `sh-feature'.")
(defvar sh-font-lock-keywords-2 ()
"*Yet more rules for highlighting shell scripts. See `sh-feature'.")
;; mode-command and utility functions
......@@ -618,6 +624,7 @@ with your script for an edit-interpret-debug cycle."
(use-local-map sh-mode-map)
(make-local-variable 'indent-line-function)
(make-local-variable 'indent-region-function)
(make-local-variable 'skeleton-end-hook)
(make-local-variable 'paragraph-start)
(make-local-variable 'paragraph-separate)
(make-local-variable 'comment-start)
......@@ -628,10 +635,10 @@ with your script for an edit-interpret-debug cycle."
(make-local-variable 'sh-shell)
(make-local-variable 'skeleton-pair-alist)
(make-local-variable 'skeleton-pair-filter)
(make-local-variable 'font-lock-keywords)
(make-local-variable 'comint-dynamic-complete-functions)
(make-local-variable 'comint-prompt-regexp)
(make-local-variable 'font-lock-keywords-case-fold-search)
(make-local-variable 'font-lock-keywords)
(make-local-variable 'font-lock-defaults)
(make-local-variable 'skeleton-filter)
(make-local-variable 'skeleton-newline-indent-rigidly)
(make-local-variable 'process-environment)
......@@ -640,14 +647,27 @@ with your script for an edit-interpret-debug cycle."
indent-line-function 'sh-indent-line
;; not very clever, but enables wrapping skeletons around regions
indent-region-function (lambda (b e)
(indent-rigidly b e sh-indentation))
(save-excursion
(goto-char b)
(skip-syntax-backward "-")
(setq b (point))
(goto-char e)
(skip-syntax-backward "-")
(indent-rigidly b (point) sh-indentation)))
skeleton-end-hook (lambda ()
(or (eolp) (newline) (indent-relative)))
paragraph-start "^$\\|^ "
paragraph-separate paragraph-start
comment-start "# "
font-lock-keywords-case-fold-search nil
comint-dynamic-complete-functions sh-dynamic-complete-functions
;; we can't look if previous line ended with `\'
comint-prompt-regexp "^[ \t]*"
font-lock-defaults
'((sh-font-lock-keywords
sh-font-lock-keywords-1
sh-font-lock-keywords-2)
nil nil
((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")))
skeleton-pair-alist '((?` _ ?`))
skeleton-pair-filter 'sh-quoted-p
skeleton-further-elements '((< '(- (min sh-indentation
......@@ -659,19 +679,61 @@ with your script for an edit-interpret-debug cycle."
(goto-char (point-min))
(sh-set-shell
(if (looking-at "#![\t ]*\\([^\t\n ]+\\)")
(buffer-substring (match-beginning 1) (match-end 1))
(match-string 1)
sh-shell-path))
(run-hooks 'sh-mode-hook))
;;;###autoload
(defalias 'shell-script-mode 'sh-mode)
(defun sh-font-lock-keywords (&optional keywords)
"Function to get simple fontification based on `sh-font-lock-keywords'.
This adds rules for comments and assignments."
(sh-feature sh-font-lock-keywords
(lambda (list)
`((,(concat (sh-feature sh-comment-prefix) "\\(#.*\\)")
2 font-lock-comment-face t)
(,(sh-feature sh-assignment-regexp)
1 font-lock-variable-name-face)
,@keywords
,@list))))
(defun sh-font-lock-keywords-1 (&optional builtins)
"Function to get better fontification including keywords."
(let ((keywords (concat "\\([;(){}`|&]\\|^\\)[ \t]*\\(\\(\\("
(mapconcat 'identity
(sh-feature sh-leading-keywords)
"\\|")
"\\)[ \t]+\\)?\\("
(mapconcat 'identity
(append (sh-feature sh-leading-keywords)
(sh-feature sh-other-keywords))
"\\|")
"\\)")))
(sh-font-lock-keywords
`(,@(if builtins
`((,(concat keywords "[ \t]+\\)?\\("
(mapconcat 'identity (sh-feature sh-builtins) "\\|")
"\\)\\>")
(2 font-lock-keyword-face nil t)
(6 font-lock-function-name-face))
,@(sh-feature sh-font-lock-keywords-2)))
(,(concat keywords "\\)\\>")
2 font-lock-keyword-face)
,@(sh-feature sh-font-lock-keywords-1)))))
(defun sh-font-lock-keywords-2 ()
"Function to get better fontification including keywords and builtins."
(sh-font-lock-keywords-1 t))
(defun sh-set-shell (shell)
"Set this buffer's shell to SHELL (a string).
Makes this script executable via `executable-set-magic'.
Calls the value of `sh-set-shell-hook' if set."
(interactive (list (completing-read "Name or path of shell: " sh-shells)))
(interactive (list (completing-read "Name or path of shell: "
interpreter-mode-alist
(lambda (x) (eq (cdr x) 'sh-mode)))))
(if (eq this-command 'sh-set-shell)
;; prevent querying
(setq this-command 'executable-set-magic))
......@@ -681,32 +743,13 @@ Calls the value of `sh-set-shell-hook' if set."
sh-shell-path (executable-set-magic shell (sh-feature sh-shell-arg))
local-abbrev-table (sh-feature sh-abbrevs)
require-final-newline (sh-feature sh-require-final-newline)
font-lock-keywords
(sh-feature
sh-font-lock-keywords
(lambda (list)
`((,(concat (sh-feature sh-comment-prefix) "\\(#.*\\)")
2 font-lock-comment-face t)
(,(sh-feature sh-assignment-regexp)
1 font-lock-variable-name-face)
,@(if font-lock-maximum-decoration
`((,(concat "\\(^\\|[|&;()`!]\\)[ \t]*\\(\\(\\("
(mapconcat 'identity
(sh-feature sh-leading-keywords)
"\\|")
"\\)[ \t]+\\)?\\("
(mapconcat 'identity
(sh-feature sh-builtins)
"\\|")
"\\)\\)\\($\\|[ \t|&;()]\\)")
2 font-lock-keyword-face 'keep)
,@list)
list))))
font-lock-keywords nil ; force resetting
comment-start-skip (concat (sh-feature sh-comment-prefix) "#+[\t ]*")
mode-line-process (format "[%s]" sh-shell)
process-environment (default-value 'process-environment)
shell (sh-feature sh-variables))
(set-syntax-table (sh-feature sh-mode-syntax-table))
(setq font-lock-syntax-table)
(save-excursion
(while (search-forward "=" nil t)
(sh-assignment 0)))
......@@ -941,6 +984,7 @@ region, clear header."
> _ \n
resume:
< < "esac"))
(put 'sh-case 'menu-enable '(sh-feature sh-case))
......@@ -1159,15 +1203,15 @@ region, clear header."
(define-skeleton sh-while
"Insert a while loop. See `sh-feature'."
(csh eval sh-modify sh
1 "while( "
3 " )"
9 "end")
2 "while( "
4 " )"
10 "end")
(es eval sh-modify rc
1 "while { "
3 " } {")
2 "while { "
4 " } {")
(rc eval sh-modify csh
3 " ) {"
9 ?})
4 " ) {"
10 ?})
(sh "condition: "
'(setq input (sh-feature sh-test))
"while " str "; do" \n
......@@ -1252,7 +1296,7 @@ option followed by a colon `:' if the option accepts an argument."
(prog1 (point)
(beginning-of-line 1))
t)
(buffer-substring (match-beginning 1) (match-end 1)))))))
(match-string 1))))))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment