358 |
;; I turned off this feature because it doesn't permit typing commands |
;; I turned off this feature because it doesn't permit typing commands |
359 |
;; in the usual way without help. |
;; in the usual way without help. |
360 |
;;(defvar sh-abbrevs |
;;(defvar sh-abbrevs |
361 |
;; '((csh eval sh-abbrevs shell |
;; '((csh sh-abbrevs shell |
362 |
;; "switch" 'sh-case |
;; "switch" 'sh-case |
363 |
;; "getopts" 'sh-while-getopts) |
;; "getopts" 'sh-while-getopts) |
364 |
|
|
365 |
;; (es eval sh-abbrevs shell |
;; (es sh-abbrevs shell |
366 |
;; "function" 'sh-function) |
;; "function" 'sh-function) |
367 |
|
|
368 |
;; (ksh88 eval sh-abbrevs sh |
;; (ksh88 sh-abbrevs sh |
369 |
;; "select" 'sh-select) |
;; "select" 'sh-select) |
370 |
|
|
371 |
;; (rc eval sh-abbrevs shell |
;; (rc sh-abbrevs shell |
372 |
;; "case" 'sh-case |
;; "case" 'sh-case |
373 |
;; "function" 'sh-function) |
;; "function" 'sh-function) |
374 |
|
|
375 |
;; (sh eval sh-abbrevs shell |
;; (sh sh-abbrevs shell |
376 |
;; "case" 'sh-case |
;; "case" 'sh-case |
377 |
;; "function" 'sh-function |
;; "function" 'sh-function |
378 |
;; "until" 'sh-until |
;; "until" 'sh-until |
385 |
;; "tmpfile" sh-tmp-file |
;; "tmpfile" sh-tmp-file |
386 |
;; "while" sh-while) |
;; "while" sh-while) |
387 |
|
|
388 |
;; (zsh eval sh-abbrevs ksh88 |
;; (zsh sh-abbrevs ksh88 |
389 |
;; "repeat" 'sh-repeat)) |
;; "repeat" 'sh-repeat)) |
390 |
;; "Abbrev-table used in Shell-Script mode. See `sh-feature'. |
;; "Abbrev-table used in Shell-Script mode. See `sh-feature'. |
391 |
;;;Due to the internal workings of abbrev tables, the shell name symbol is |
;;;Due to the internal workings of abbrev tables, the shell name symbol is |
393 |
|
|
394 |
|
|
395 |
|
|
396 |
(defvar sh-mode-syntax-table |
(defun sh-mode-syntax-table (table &rest list) |
397 |
'((sh eval sh-mode-syntax-table () |
"Copy TABLE and set syntax for successive CHARs according to strings S." |
398 |
|
(setq table (copy-syntax-table table)) |
399 |
|
(while list |
400 |
|
(modify-syntax-entry (pop list) (pop list) table)) |
401 |
|
table) |
402 |
|
|
403 |
|
(defvar sh-mode-syntax-table nil |
404 |
|
"The syntax table to use for Shell-Script mode. |
405 |
|
This is buffer-local in every such buffer.") |
406 |
|
|
407 |
|
(defvar sh-mode-default-syntax-table |
408 |
|
(sh-mode-syntax-table () |
409 |
?\# "<" |
?\# "<" |
410 |
?\n ">#" |
?\n ">#" |
411 |
?\" "\"\"" |
?\" "\"\"" |
417 |
?. "_" |
?. "_" |
418 |
?^ "_" |
?^ "_" |
419 |
?~ "_" |
?~ "_" |
420 |
|
?, "_" |
421 |
?< "." |
?< "." |
422 |
?> ".") |
?> ".") |
423 |
(csh eval identity sh) |
"Default syntax table for shell mode.") |
|
(rc eval identity sh)) |
|
424 |
|
|
425 |
|
(defvar sh-mode-syntax-table-input |
426 |
|
'((sh . nil)) |
427 |
"Syntax-table used in Shell-Script mode. See `sh-feature'.") |
"Syntax-table used in Shell-Script mode. See `sh-feature'.") |
428 |
|
|
429 |
(defvar sh-mode-map |
(defvar sh-mode-map |
492 |
(defcustom sh-require-final-newline |
(defcustom sh-require-final-newline |
493 |
'((csh . t) |
'((csh . t) |
494 |
(pdksh . t) |
(pdksh . t) |
495 |
(rc eval . require-final-newline) |
(rc . require-final-newline) |
496 |
(sh eval . require-final-newline)) |
(sh . require-final-newline)) |
497 |
"*Value of `require-final-newline' in Shell-Script mode buffers. |
"*Value of `require-final-newline' in Shell-Script mode buffers. |
498 |
See `sh-feature'." |
See `sh-feature'." |
499 |
:type '(repeat (cons (symbol :tag "Shell") |
:type '(repeat (cons (symbol :tag "Shell") |
556 |
|
|
557 |
|
|
558 |
(defvar sh-here-document-word "EOF" |
(defvar sh-here-document-word "EOF" |
559 |
"Word to delimit here documents.") |
"Word to delimit here documents. |
560 |
|
If the first character of this string is \"-\", this character will |
561 |
|
be removed from the string when it is used to close the here document. |
562 |
|
This convention is used by the Bash shell, for example, to indicate |
563 |
|
that leading tabs inside the here document should be ignored. |
564 |
|
Note that Emacs currently has no support for indenting inside here |
565 |
|
documents - you must insert literal tabs by hand.") |
566 |
|
|
567 |
(defvar sh-test |
(defvar sh-test |
568 |
'((sh "[ ]" . 3) |
'((sh "[ ]" . 3) |
573 |
;; customized this out of sheer bravado. not for the faint of heart. |
;; customized this out of sheer bravado. not for the faint of heart. |
574 |
;; but it *did* have an asterisk in the docstring! |
;; but it *did* have an asterisk in the docstring! |
575 |
(defcustom sh-builtins |
(defcustom sh-builtins |
576 |
'((bash eval sh-append posix |
'((bash sh-append posix |
577 |
"alias" "bg" "bind" "builtin" "declare" "dirs" "enable" "fc" "fg" |
"." "alias" "bg" "bind" "builtin" "compgen" "complete" |
578 |
"help" "history" "jobs" "kill" "let" "local" "popd" "pushd" "source" |
"declare" "dirs" "disown" "enable" "fc" "fg" "help" "history" |
579 |
"suspend" "typeset" "unalias") |
"jobs" "kill" "let" "local" "popd" "printf" "pushd" "shopt" |
580 |
|
"source" "suspend" "typeset" "unalias") |
581 |
|
|
582 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
583 |
(bourne eval sh-append shell |
(bourne sh-append shell |
584 |
"eval" "export" "getopts" "newgrp" "pwd" "read" "readonly" |
"eval" "export" "getopts" "newgrp" "pwd" "read" "readonly" |
585 |
"times" "ulimit") |
"times" "ulimit") |
586 |
|
|
587 |
(csh eval sh-append shell |
(csh sh-append shell |
588 |
"alias" "chdir" "glob" "history" "limit" "nice" "nohup" "rehash" |
"alias" "chdir" "glob" "history" "limit" "nice" "nohup" "rehash" |
589 |
"setenv" "source" "time" "unalias" "unhash") |
"setenv" "source" "time" "unalias" "unhash") |
590 |
|
|
591 |
(dtksh eval identity wksh) |
(dtksh sh-append wksh) |
592 |
|
|
593 |
(es "access" "apids" "cd" "echo" "eval" "false" "let" "limit" "local" |
(es "access" "apids" "cd" "echo" "eval" "false" "let" "limit" "local" |
594 |
"newpgrp" "result" "time" "umask" "var" "vars" "wait" "whatis") |
"newpgrp" "result" "time" "umask" "var" "vars" "wait" "whatis") |
595 |
|
|
596 |
(jsh eval sh-append sh |
(jsh sh-append sh |
597 |
"bg" "fg" "jobs" "kill" "stop" "suspend") |
"bg" "fg" "jobs" "kill" "stop" "suspend") |
598 |
|
|
599 |
(jcsh eval sh-append csh |
(jcsh sh-append csh |
600 |
"bg" "fg" "jobs" "kill" "notify" "stop" "suspend") |
"bg" "fg" "jobs" "kill" "notify" "stop" "suspend") |
601 |
|
|
602 |
(ksh88 eval sh-append bourne |
(ksh88 sh-append bourne |
603 |
"alias" "bg" "false" "fc" "fg" "jobs" "kill" "let" "print" "time" |
"alias" "bg" "false" "fc" "fg" "jobs" "kill" "let" "print" "time" |
604 |
"typeset" "unalias" "whence") |
"typeset" "unalias" "whence") |
605 |
|
|
606 |
(oash eval sh-append sh |
(oash sh-append sh |
607 |
"checkwin" "dateline" "error" "form" "menu" "newwin" "oadeinit" |
"checkwin" "dateline" "error" "form" "menu" "newwin" "oadeinit" |
608 |
"oaed" "oahelp" "oainit" "pp" "ppfile" "scan" "scrollok" "wattr" |
"oaed" "oahelp" "oainit" "pp" "ppfile" "scan" "scrollok" "wattr" |
609 |
"wclear" "werase" "win" "wmclose" "wmmessage" "wmopen" "wmove" |
"wclear" "werase" "win" "wmclose" "wmmessage" "wmopen" "wmove" |
610 |
"wmtitle" "wrefresh") |
"wmtitle" "wrefresh") |
611 |
|
|
612 |
(pdksh eval sh-append ksh88 |
(pdksh sh-append ksh88 |
613 |
"bind") |
"bind") |
614 |
|
|
615 |
(posix eval sh-append sh |
(posix sh-append sh |
616 |
"command") |
"command") |
617 |
|
|
618 |
(rc "builtin" "cd" "echo" "eval" "limit" "newpgrp" "shift" "umask" "wait" |
(rc "builtin" "cd" "echo" "eval" "limit" "newpgrp" "shift" "umask" "wait" |
619 |
"whatis") |
"whatis") |
620 |
|
|
621 |
(sh eval sh-append bourne |
(sh sh-append bourne |
622 |
"hash" "test" "type") |
"hash" "test" "type") |
623 |
|
|
624 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
625 |
(shell "cd" "echo" "eval" "set" "shift" "umask" "unset" "wait") |
(shell "cd" "echo" "eval" "set" "shift" "umask" "unset" "wait") |
626 |
|
|
627 |
(wksh eval sh-append ksh88 |
(wksh sh-append ksh88 |
628 |
"Xt[A-Z][A-Za-z]*") |
"Xt[A-Z][A-Za-z]*") |
629 |
|
|
630 |
(zsh eval sh-append ksh88 |
(zsh sh-append ksh88 |
631 |
"autoload" "bindkey" "builtin" "chdir" "compctl" "declare" "dirs" |
"autoload" "bindkey" "builtin" "chdir" "compctl" "declare" "dirs" |
632 |
"disable" "disown" "echotc" "enable" "functions" "getln" "hash" |
"disable" "disown" "echotc" "enable" "functions" "getln" "hash" |
633 |
"history" "integer" "limit" "local" "log" "popd" "pushd" "r" |
"history" "integer" "limit" "local" "log" "popd" "pushd" "r" |
647 |
|
|
648 |
|
|
649 |
(defcustom sh-leading-keywords |
(defcustom sh-leading-keywords |
650 |
'((csh "else") |
'((bash sh-append sh |
651 |
|
"time") |
652 |
|
|
653 |
|
(csh "else") |
654 |
|
|
655 |
(es "true" "unwind-protect" "whatis") |
(es "true" "unwind-protect" "whatis") |
656 |
|
|
670 |
|
|
671 |
|
|
672 |
(defcustom sh-other-keywords |
(defcustom sh-other-keywords |
673 |
'((bash eval sh-append bourne |
'((bash sh-append bourne |
674 |
"bye" "logout") |
"bye" "logout" "select") |
675 |
|
|
676 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
677 |
(bourne eval sh-append sh |
(bourne sh-append sh |
678 |
"function") |
"function") |
679 |
|
|
680 |
(csh eval sh-append shell |
(csh sh-append shell |
681 |
"breaksw" "default" "end" "endif" "endsw" "foreach" "goto" |
"breaksw" "default" "end" "endif" "endsw" "foreach" "goto" |
682 |
"if" "logout" "onintr" "repeat" "switch" "then" "while") |
"if" "logout" "onintr" "repeat" "switch" "then" "while") |
683 |
|
|
684 |
(es "break" "catch" "exec" "exit" "fn" "for" "forever" "fork" "if" |
(es "break" "catch" "exec" "exit" "fn" "for" "forever" "fork" "if" |
685 |
"return" "throw" "while") |
"return" "throw" "while") |
686 |
|
|
687 |
(ksh88 eval sh-append bourne |
(ksh88 sh-append bourne |
688 |
"select") |
"select") |
689 |
|
|
690 |
(rc "break" "case" "exec" "exit" "fn" "for" "if" "in" "return" "switch" |
(rc "break" "case" "exec" "exit" "fn" "for" "if" "in" "return" "switch" |
691 |
"while") |
"while") |
692 |
|
|
693 |
(sh eval sh-append shell |
(sh sh-append shell |
694 |
"done" "esac" "fi" "for" "in" "return") |
"done" "esac" "fi" "for" "in" "return") |
695 |
|
|
696 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
697 |
(shell "break" "case" "continue" "exec" "exit") |
(shell "break" "case" "continue" "exec" "exit") |
698 |
|
|
699 |
(zsh eval sh-append bash |
(zsh sh-append bash |
700 |
"select")) |
"select")) |
701 |
"*List of keywords not in `sh-leading-keywords'. |
"*List of keywords not in `sh-leading-keywords'. |
702 |
See `sh-feature'." |
See `sh-feature'." |
710 |
|
|
711 |
|
|
712 |
(defvar sh-variables |
(defvar sh-variables |
713 |
'((bash eval sh-append sh |
'((bash sh-append sh |
714 |
"allow_null_glob_expansion" "auto_resume" "BASH" "BASH_VERSION" |
"allow_null_glob_expansion" "auto_resume" "BASH" "BASH_ENV" |
715 |
"cdable_vars" "ENV" "EUID" "FCEDIT" "FIGNORE" "glob_dot_filenames" |
"BASH_VERSINFO" "BASH_VERSION" "cdable_vars" "COMP_CWORD" |
716 |
"histchars" "HISTFILE" "HISTFILESIZE" "history_control" "HISTSIZE" |
"COMP_LINE" "COMP_POINT" "COMP_WORDS" "COMPREPLY" "DIRSTACK" |
717 |
"hostname_completion_file" "HOSTTYPE" "IGNOREEOF" "ignoreeof" |
"ENV" "EUID" "FCEDIT" "FIGNORE" "FUNCNAME" |
718 |
"LINENO" "MAIL_WARNING" "noclobber" "nolinks" "notify" |
"glob_dot_filenames" "GLOBIGNORE" "GROUPS" "histchars" |
719 |
"no_exit_on_failed_exec" "NO_PROMPT_VARS" "OLDPWD" "OPTERR" "PPID" |
"HISTCMD" "HISTCONTROL" "HISTFILE" "HISTFILESIZE" |
720 |
"PROMPT_COMMAND" "PS4" "pushd_silent" "PWD" "RANDOM" "REPLY" |
"HISTIGNORE" "history_control" "HISTSIZE" |
721 |
"SECONDS" "SHLVL" "TMOUT" "UID") |
"hostname_completion_file" "HOSTFILE" "HOSTTYPE" "IGNOREEOF" |
722 |
|
"ignoreeof" "INPUTRC" "LINENO" "MACHTYPE" "MAIL_WARNING" |
723 |
|
"noclobber" "nolinks" "notify" "no_exit_on_failed_exec" |
724 |
|
"NO_PROMPT_VARS" "OLDPWD" "OPTERR" "OSTYPE" "PIPESTATUS" |
725 |
|
"PPID" "POSIXLY_CORRECT" "PROMPT_COMMAND" "PS3" "PS4" |
726 |
|
"pushd_silent" "PWD" "RANDOM" "REPLY" "SECONDS" "SHELLOPTS" |
727 |
|
"SHLVL" "TIMEFORMAT" "TMOUT" "UID") |
728 |
|
|
729 |
(csh eval sh-append shell |
(csh sh-append shell |
730 |
"argv" "cdpath" "child" "echo" "histchars" "history" "home" |
"argv" "cdpath" "child" "echo" "histchars" "history" "home" |
731 |
"ignoreeof" "mail" "noclobber" "noglob" "nonomatch" "path" "prompt" |
"ignoreeof" "mail" "noclobber" "noglob" "nonomatch" "path" "prompt" |
732 |
"shell" "status" "time" "verbose") |
"shell" "status" "time" "verbose") |
733 |
|
|
734 |
(es eval sh-append shell |
(es sh-append shell |
735 |
"apid" "cdpath" "CDPATH" "history" "home" "ifs" "noexport" "path" |
"apid" "cdpath" "CDPATH" "history" "home" "ifs" "noexport" "path" |
736 |
"pid" "prompt" "signals") |
"pid" "prompt" "signals") |
737 |
|
|
738 |
(jcsh eval sh-append csh |
(jcsh sh-append csh |
739 |
"notify") |
"notify") |
740 |
|
|
741 |
(ksh88 eval sh-append sh |
(ksh88 sh-append sh |
742 |
"ENV" "ERRNO" "FCEDIT" "FPATH" "HISTFILE" "HISTSIZE" "LINENO" |
"ENV" "ERRNO" "FCEDIT" "FPATH" "HISTFILE" "HISTSIZE" "LINENO" |
743 |
"OLDPWD" "PPID" "PS3" "PS4" "PWD" "RANDOM" "REPLY" "SECONDS" |
"OLDPWD" "PPID" "PS3" "PS4" "PWD" "RANDOM" "REPLY" "SECONDS" |
744 |
"TMOUT") |
"TMOUT") |
745 |
|
|
746 |
(oash eval sh-append sh |
(oash sh-append sh |
747 |
"FIELD" "FIELD_MAX" "LAST_KEY" "OALIB" "PP_ITEM" "PP_NUM") |
"FIELD" "FIELD_MAX" "LAST_KEY" "OALIB" "PP_ITEM" "PP_NUM") |
748 |
|
|
749 |
(rc eval sh-append shell |
(rc sh-append shell |
750 |
"apid" "apids" "cdpath" "CDPATH" "history" "home" "ifs" "path" "pid" |
"apid" "apids" "cdpath" "CDPATH" "history" "home" "ifs" "path" "pid" |
751 |
"prompt" "status") |
"prompt" "status") |
752 |
|
|
753 |
(sh eval sh-append shell |
(sh sh-append shell |
754 |
"CDPATH" "IFS" "OPTARG" "OPTIND" "PS1" "PS2") |
"CDPATH" "IFS" "OPTARG" "OPTIND" "PS1" "PS2") |
755 |
|
|
756 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
759 |
"LINES" "LOGNAME" "MAIL" "MAILCHECK" "MAILPATH" "PAGER" "PATH" |
"LINES" "LOGNAME" "MAIL" "MAILCHECK" "MAILPATH" "PAGER" "PATH" |
760 |
"SHELL" "TERM" "TERMCAP" "TERMINFO" "VISUAL") |
"SHELL" "TERM" "TERMCAP" "TERMINFO" "VISUAL") |
761 |
|
|
762 |
(tcsh eval sh-append csh |
(tcsh sh-append csh |
763 |
"addsuffix" "ampm" "autocorrect" "autoexpand" "autolist" |
"addsuffix" "ampm" "autocorrect" "autoexpand" "autolist" |
764 |
"autologout" "chase_symlinks" "correct" "dextract" "edit" "el" |
"autologout" "chase_symlinks" "correct" "dextract" "edit" "el" |
765 |
"fignore" "gid" "histlit" "HOST" "HOSTTYPE" "HPATH" |
"fignore" "gid" "histlit" "HOST" "HOSTTYPE" "HPATH" |
770 |
"tperiod" "tty" "uid" "version" "visiblebell" "watch" "who" |
"tperiod" "tty" "uid" "version" "visiblebell" "watch" "who" |
771 |
"wordchars") |
"wordchars") |
772 |
|
|
773 |
(zsh eval sh-append ksh88 |
(zsh sh-append ksh88 |
774 |
"BAUD" "bindcmds" "cdpath" "DIRSTACKSIZE" "fignore" "FIGNORE" "fpath" |
"BAUD" "bindcmds" "cdpath" "DIRSTACKSIZE" "fignore" "FIGNORE" "fpath" |
775 |
"HISTCHARS" "hostcmds" "hosts" "HOSTS" "LISTMAX" "LITHISTSIZE" |
"HISTCHARS" "hostcmds" "hosts" "HOSTS" "LISTMAX" "LITHISTSIZE" |
776 |
"LOGCHECK" "mailpath" "manpath" "NULLCMD" "optcmds" "path" "POSTEDIT" |
"LOGCHECK" "mailpath" "manpath" "NULLCMD" "optcmds" "path" "POSTEDIT" |
799 |
|
|
800 |
|
|
801 |
(defvar sh-font-lock-keywords |
(defvar sh-font-lock-keywords |
802 |
'((csh eval sh-append shell |
'((csh sh-append shell |
803 |
'("\\${?[#?]?\\([A-Za-z_][A-Za-z0-9_]*\\|0\\)" 1 |
("\\${?[#?]?\\([A-Za-z_][A-Za-z0-9_]*\\|0\\)" 1 |
804 |
font-lock-variable-name-face)) |
font-lock-variable-name-face)) |
805 |
|
|
806 |
(es eval sh-append executable-font-lock-keywords |
(es sh-append executable-font-lock-keywords |
807 |
'("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1 |
("\\$#?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\)" 1 |
808 |
font-lock-variable-name-face)) |
font-lock-variable-name-face)) |
809 |
|
|
810 |
(rc eval identity es) |
(rc sh-append es) |
811 |
|
|
812 |
(sh eval sh-append shell |
(sh sh-append shell |
813 |
;; Variable names. |
;; Variable names. |
814 |
'("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2 |
("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2 |
815 |
font-lock-variable-name-face) |
font-lock-variable-name-face) |
816 |
;; Function names. |
;; Function names. |
817 |
'("^\\(\\sw+\\)[ \t]*(" 1 font-lock-function-name-face) |
("^\\(\\sw+\\)[ \t]*(" 1 font-lock-function-name-face) |
818 |
'("\\<\\(function\\)\\>[ \t]*\\(\\sw+\\)?" |
("\\<\\(function\\)\\>[ \t]*\\(\\sw+\\)?" |
819 |
(1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))) |
(1 font-lock-keyword-face) (2 font-lock-function-name-face nil t))) |
820 |
|
|
821 |
;; The next entry is only used for defining the others |
;; The next entry is only used for defining the others |
822 |
(shell eval sh-append executable-font-lock-keywords |
(shell sh-append executable-font-lock-keywords |
823 |
'("\\\\[^A-Za-z0-9]" 0 font-lock-string-face) |
;; Using font-lock-string-face here confuses sh-get-indent-info. |
824 |
'("\\${?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\|[$*_]\\)" 1 |
("\\\\$" 0 font-lock-warning-face) |
825 |
|
("\\\\[^A-Za-z0-9]" 0 font-lock-string-face) |
826 |
|
("\\${?\\([A-Za-z_][A-Za-z0-9_]*\\|[0-9]+\\|[$*_]\\)" 1 |
827 |
font-lock-variable-name-face)) |
font-lock-variable-name-face)) |
828 |
(rpm eval sh-append rpm2 |
(rpm sh-append rpm2 |
829 |
'("%{?\\(\\sw+\\)" 1 font-lock-keyword-face)) |
("%{?\\(\\sw+\\)" 1 font-lock-keyword-face)) |
830 |
(rpm2 eval sh-append shell |
(rpm2 sh-append shell |
831 |
'("^\\(\\sw+\\):" 1 font-lock-variable-name-face))) |
("^\\(\\sw+\\):" 1 font-lock-variable-name-face))) |
832 |
"Default expressions to highlight in Shell Script modes. See `sh-feature'.") |
"Default expressions to highlight in Shell Script modes. See `sh-feature'.") |
833 |
|
|
834 |
(defvar sh-font-lock-keywords-1 |
(defvar sh-font-lock-keywords-1 |
915 |
;; This looks silly, but it's because `sh-here-doc-re' keeps changing. |
;; This looks silly, but it's because `sh-here-doc-re' keeps changing. |
916 |
(re-search-forward sh-here-doc-re limit t)) |
(re-search-forward sh-here-doc-re limit t)) |
917 |
|
|
918 |
|
(defun sh-is-quoted-p (pos) |
919 |
|
(and (eq (char-before pos) ?\\) |
920 |
|
(not (sh-is-quoted-p (1- pos))))) |
921 |
|
|
922 |
(defun sh-font-lock-paren (start) |
(defun sh-font-lock-paren (start) |
923 |
(save-excursion |
(save-excursion |
924 |
(goto-char start) |
(goto-char start) |
929 |
;; Skip through one pattern |
;; Skip through one pattern |
930 |
(while |
(while |
931 |
(or (/= 0 (skip-syntax-backward "w_")) |
(or (/= 0 (skip-syntax-backward "w_")) |
932 |
(/= 0 (skip-chars-backward "?*/")) |
(/= 0 (skip-chars-backward "?[]*/\\")) |
933 |
|
(and (sh-is-quoted-p (1- (point))) |
934 |
|
(goto-char (- (point) 2))) |
935 |
(when (memq (char-before) '(?\" ?\')) |
(when (memq (char-before) '(?\" ?\')) |
936 |
(condition-case nil (progn (backward-sexp 1) t) |
(condition-case nil (progn (backward-sexp 1) t) |
937 |
(error nil))))) |
(error nil))))) |
1252 |
;; mode-command and utility functions |
;; mode-command and utility functions |
1253 |
|
|
1254 |
;;;###autoload |
;;;###autoload |
|
(put 'sh-mode 'mode-class 'special) |
|
|
|
|
|
;;;###autoload |
|
1255 |
(defun sh-mode () |
(defun sh-mode () |
1256 |
"Major mode for editing shell scripts. |
"Major mode for editing shell scripts. |
1257 |
This mode works for many shells, since they all have roughly the same syntax, |
This mode works for many shells, since they all have roughly the same syntax, |
1490 |
(setq sh-shell-file |
(setq sh-shell-file |
1491 |
(executable-set-magic shell (sh-feature sh-shell-arg) |
(executable-set-magic shell (sh-feature sh-shell-arg) |
1492 |
no-query-flag insert-flag))) |
no-query-flag insert-flag))) |
1493 |
(setq require-final-newline (sh-feature sh-require-final-newline) |
(let ((tem (sh-feature sh-require-final-newline))) |
1494 |
;;; local-abbrev-table (sh-feature sh-abbrevs) |
(unless (eq tem 'require-final-newline) |
1495 |
|
(setq require-final-newline tem))) |
1496 |
|
(setq |
1497 |
comment-start-skip "#+[\t ]*" |
comment-start-skip "#+[\t ]*" |
1498 |
|
;;; local-abbrev-table (sh-feature sh-abbrevs) |
1499 |
mode-line-process (format "[%s]" sh-shell) |
mode-line-process (format "[%s]" sh-shell) |
1500 |
sh-shell-variables nil |
sh-shell-variables nil |
1501 |
sh-shell-variables-initialized nil |
sh-shell-variables-initialized nil |
1502 |
imenu-generic-expression (sh-feature sh-imenu-generic-expression) |
imenu-generic-expression (sh-feature sh-imenu-generic-expression) |
1503 |
imenu-case-fold-search nil) |
imenu-case-fold-search nil) |
1504 |
(set-syntax-table (or (sh-feature sh-mode-syntax-table) |
(make-local-variable 'sh-mode-syntax-table) |
1505 |
(standard-syntax-table))) |
(let ((tem (sh-feature sh-mode-syntax-table-input))) |
1506 |
|
(setq sh-mode-syntax-table |
1507 |
|
(if tem (apply 'sh-mode-syntax-table tem) |
1508 |
|
sh-mode-default-syntax-table))) |
1509 |
|
(set-syntax-table sh-mode-syntax-table) |
1510 |
(dolist (var (sh-feature sh-variables)) |
(dolist (var (sh-feature sh-variables)) |
1511 |
(sh-remember-variable var)) |
(sh-remember-variable var)) |
1512 |
(make-local-variable 'indent-line-function) |
(make-local-variable 'indent-line-function) |
1532 |
|
|
1533 |
|
|
1534 |
|
|
1535 |
(defun sh-feature (list &optional function) |
(defun sh-feature (alist &optional function) |
1536 |
"Index ALIST by the current shell. |
"Index ALIST by the current shell. |
1537 |
If ALIST isn't a list where every element is a cons, it is returned as is. |
If ALIST isn't a list where every element is a cons, it is returned as is. |
1538 |
Else indexing follows an inheritance logic which works in two ways: |
Else indexing follows an inheritance logic which works in two ways: |
1541 |
the alist contains no value for the current shell. |
the alist contains no value for the current shell. |
1542 |
The ultimate default is always `sh'. |
The ultimate default is always `sh'. |
1543 |
|
|
1544 |
- If the value thus looked up is a list starting with `eval' its `cdr' is |
- If the value thus looked up is a list starting with `sh-append', |
1545 |
first evaluated. If that is also a list and the first argument is a |
we call the function `sh-append' with the rest of the list as |
1546 |
symbol in ALIST it is not evaluated, but rather recursively looked up in |
arguments, and use the value. However, the next element of the |
1547 |
ALIST to allow the function called to define the value for one shell to be |
list is not used as-is; instead, we look it up recursively |
1548 |
derived from another shell. While calling the function, is the car of the |
in ALIST to allow the function called to define the value for |
1549 |
alist element is the current shell. |
one shell to be derived from another shell. |
1550 |
The value thus determined is physically replaced into the alist. |
The value thus determined is physically replaced into the alist. |
1551 |
|
|
1552 |
Optional FUNCTION is applied to the determined value and the result is cached |
Optional FUNCTION is applied to the determined value and the result is cached |
1553 |
in ALIST." |
in ALIST." |
1554 |
(or (if (consp list) |
(or (if (consp alist) |
1555 |
(let ((l list)) |
(let ((l alist)) |
1556 |
(while (and l (consp (car l))) |
(while (and l (consp (car l))) |
1557 |
(setq l (cdr l))) |
(setq l (cdr l))) |
1558 |
(if l list))) |
(if l alist))) |
1559 |
(if function |
(if function |
1560 |
(cdr (assoc (setq function (cons sh-shell function)) list))) |
(cdr (assoc (setq function (cons sh-shell function)) alist))) |
1561 |
(let ((sh-shell sh-shell) |
(let ((sh-shell sh-shell) |
1562 |
elt val) |
elt val) |
1563 |
(while (and sh-shell |
(while (and sh-shell |
1564 |
(not (setq elt (assq sh-shell list)))) |
(not (setq elt (assq sh-shell alist)))) |
1565 |
(setq sh-shell (cdr (assq sh-shell sh-ancestor-alist)))) |
(setq sh-shell (cdr (assq sh-shell sh-ancestor-alist)))) |
1566 |
;; If the shell is not known, treat it as sh. |
;; If the shell is not known, treat it as sh. |
1567 |
(unless elt |
(unless elt |
1568 |
(setq elt (assq 'sh list))) |
(setq elt (assq 'sh alist))) |
1569 |
(if (and (consp (setq val (cdr elt))) |
(if (and (consp (setq val (cdr elt))) |
1570 |
(eq (car val) 'eval)) |
(memq (car val) '(sh-append sh-modify))) |
1571 |
(setcdr elt |
(setcdr elt |
1572 |
(setq val |
(setq val |
1573 |
(eval (if (consp (setq val (cdr val))) |
(apply (car val) |
1574 |
(let ((sh-shell (car (cdr val))) |
(let ((sh-shell (car (cdr val)))) |
1575 |
function) |
(if (assq sh-shell alist) |
1576 |
(if (assq sh-shell list) |
(sh-feature alist) |
1577 |
(setcar (cdr val) |
(eval sh-shell))) |
1578 |
(list 'quote |
(cddr val))))) |
|
(sh-feature list)))) |
|
|
val) |
|
|
val))))) |
|
1579 |
(if function |
(if function |
1580 |
(nconc list |
(nconc alist |
1581 |
(list (cons function |
(list (cons function |
1582 |
(setq sh-shell (car function) |
(setq sh-shell (car function) |
1583 |
val (funcall (cdr function) val)))))) |
val (funcall (cdr function) val)))))) |
1618 |
;; (symbol-value sh-shell))) |
;; (symbol-value sh-shell))) |
1619 |
|
|
1620 |
|
|
|
(defun sh-mode-syntax-table (table &rest list) |
|
|
"Copy TABLE and set syntax for successive CHARs according to strings S." |
|
|
(setq table (copy-syntax-table table)) |
|
|
(while list |
|
|
(modify-syntax-entry (pop list) (pop list) table)) |
|
|
table) |
|
|
|
|
1621 |
(defun sh-append (ancestor &rest list) |
(defun sh-append (ancestor &rest list) |
1622 |
"Return list composed of first argument (a list) physically appended to rest." |
"Return list composed of first argument (a list) physically appended to rest." |
1623 |
(nconc list ancestor)) |
(nconc list ancestor)) |
1972 |
what the indentation is based on." |
what the indentation is based on." |
1973 |
;; See comments before `sh-kw'. |
;; See comments before `sh-kw'. |
1974 |
(save-excursion |
(save-excursion |
1975 |
(let ((prev-kw nil) |
(let ((have-result nil) |
|
(prev-stmt nil) |
|
|
(have-result nil) |
|
|
depth-bol depth-eol |
|
1976 |
this-kw |
this-kw |
|
(state nil) |
|
|
state-bol |
|
|
(depth-prev-bol nil) |
|
1977 |
start |
start |
1978 |
func val |
val |
1979 |
(result nil) |
(result nil) |
|
prev-lines-indent |
|
|
(prev-list nil) |
|
|
(this-list nil) |
|
1980 |
(align-point nil) |
(align-point nil) |
1981 |
prev-line-end x) |
prev-line-end x) |
1982 |
(beginning-of-line) |
(beginning-of-line) |
1983 |
;; Note: setting result to t means we are done and will return nil. |
;; Note: setting result to t means we are done and will return nil. |
1984 |
;;(This function never returns just t.) |
;;(This function never returns just t.) |
1985 |
(cond |
(cond |
1986 |
((or (and (boundp 'font-lock-string-face) |
((or (and (boundp 'font-lock-string-face) (not (bobp)) |
1987 |
(eq (get-text-property (point) 'face) font-lock-string-face)) |
(eq (get-text-property (1- (point)) 'face) |
1988 |
|
font-lock-string-face)) |
1989 |
(eq (get-text-property (point) 'face) sh-heredoc-face)) |
(eq (get-text-property (point) 'face) sh-heredoc-face)) |
1990 |
(setq result t) |
(setq result t) |
1991 |
(setq have-result t)) |
(setq have-result t)) |
2282 |
;; |
;; |
2283 |
(if (bolp) |
(if (bolp) |
2284 |
nil |
nil |
2285 |
(let ((going t) |
(let (c min-point |
2286 |
c n |
(start (point))) |
|
min-point |
|
|
(start (point)) |
|
|
(found nil)) |
|
2287 |
(save-restriction |
(save-restriction |
2288 |
(narrow-to-region |
(narrow-to-region |
2289 |
(if (sh-this-is-a-continuation) |
(if (sh-this-is-a-continuation) |
2572 |
(sh-must-support-indent) |
(sh-must-support-indent) |
2573 |
(let* ((info (sh-get-indent-info)) |
(let* ((info (sh-get-indent-info)) |
2574 |
(var (sh-get-indent-var-for-line info)) |
(var (sh-get-indent-var-for-line info)) |
2575 |
val val0 new-val old-val indent-val) |
val old-val indent-val) |
2576 |
(if (stringp var) |
(if (stringp var) |
2577 |
(message (format "Cannot set indent - %s" var)) |
(message (format "Cannot set indent - %s" var)) |
2578 |
(setq old-val (symbol-value var)) |
(setq old-val (symbol-value var)) |
2767 |
(let ((learned-var-list nil) |
(let ((learned-var-list nil) |
2768 |
(out-buffer "*indent*") |
(out-buffer "*indent*") |
2769 |
(num-diffs 0) |
(num-diffs 0) |
|
last-pos |
|
2770 |
previous-set-info |
previous-set-info |
2771 |
(max 17) |
(max 17) |
2772 |
vec |
vec |
2927 |
(append (list (list 'sh-indent-comment comment-col (point-max))) |
(append (list (list 'sh-indent-comment comment-col (point-max))) |
2928 |
learned-var-list)) |
learned-var-list)) |
2929 |
(setq sh-indent-comment comment-col) |
(setq sh-indent-comment comment-col) |
2930 |
(let ((name (buffer-name)) |
(let ((name (buffer-name))) |
|
(lines (if (and (eq (point-min) 1) |
|
|
(eq (point-max) (1+ (buffer-size)))) |
|
|
"" |
|
|
(format "lines %d to %d of " |
|
|
(1+ (count-lines 1 (point-min))) |
|
|
(1+ (count-lines 1 (point-max)))))) |
|
|
) |
|
2931 |
(sh-mark-line "\nLearned variable settings:" nil out-buffer) |
(sh-mark-line "\nLearned variable settings:" nil out-buffer) |
2932 |
(if arg |
(if arg |
2933 |
;; Set learned variables to symbolic rather than numeric |
;; Set learned variables to symbolic rather than numeric |
2972 |
nil - we couldn't find a reasonable one." |
nil - we couldn't find a reasonable one." |
2973 |
(let* ((max (1- (length vec))) |
(let* ((max (1- (length vec))) |
2974 |
(i 1) |
(i 1) |
2975 |
(totals (make-vector max 0)) |
(totals (make-vector max 0))) |
|
(return nil) |
|
|
j) |
|
2976 |
(while (< i max) |
(while (< i max) |
2977 |
(aset totals i (+ (aref totals i) (* 4 (aref vec i)))) |
(aset totals i (+ (aref totals i) (* 4 (aref vec i)))) |
|
(setq j (/ i 2)) |
|
2978 |
(if (zerop (% i 2)) |
(if (zerop (% i 2)) |
2979 |
(aset totals i (+ (aref totals i) (aref vec (/ i 2))))) |
(aset totals i (+ (aref totals i) (aref vec (/ i 2))))) |
2980 |
(if (< (* i 2) max) |
(if (< (* i 2) max) |
3128 |
|
|
3129 |
(define-skeleton sh-for |
(define-skeleton sh-for |
3130 |
"Insert a for loop. See `sh-feature'." |
"Insert a for loop. See `sh-feature'." |
3131 |
(csh eval sh-modify sh |
(csh sh-modify sh |
3132 |
1 "" |
1 "" |
3133 |
2 "foreach " |
2 "foreach " |
3134 |
4 " ( " |
4 " ( " |
3135 |
6 " )" |
6 " )" |
3136 |
15 '< |
15 '< |
3137 |
16 "end") |
16 "end") |
3138 |
(es eval sh-modify rc |
(es sh-modify rc |
3139 |
4 " = ") |
4 " = ") |
3140 |
(rc eval sh-modify sh |
(rc sh-modify sh |
3141 |
2 "for( " |
2 "for( " |
3142 |
6 " ) {" |
6 " ) {" |
3143 |
15 ?\} ) |
15 ?\} ) |
3150 |
|
|
3151 |
(define-skeleton sh-indexed-loop |
(define-skeleton sh-indexed-loop |
3152 |
"Insert an indexed loop from 1 to n. See `sh-feature'." |
"Insert an indexed loop from 1 to n. See `sh-feature'." |
3153 |
(bash eval identity posix) |
(bash sh-modify posix) |
3154 |
(csh "Index variable: " |
(csh "Index variable: " |
3155 |
"@ " str " = 1" \n |
"@ " str " = 1" \n |
3156 |
"while( $" str " <= " (read-string "upper limit: ") " )" \n |
"while( $" str " <= " (read-string "upper limit: ") " )" \n |
3157 |
> _ ?$ str \n |
> _ ?$ str \n |
3158 |
"@ " str "++" \n |
"@ " str "++" \n |
3159 |
< "end" \n) |
< "end" \n) |
3160 |
(es eval sh-modify rc |
(es sh-modify rc |
3161 |
4 " =") |
4 " =") |
3162 |
(ksh88 "Index variable: " |
(ksh88 "Index variable: " |
3163 |
> "integer " str "=0" \n |
> "integer " str "=0" \n |
3225 |
process-environment) |
process-environment) |
3226 |
sh-shell-variables)))) |
sh-shell-variables)))) |
3227 |
(case code |
(case code |
3228 |
(nil (try-completion string sh-shell-variables predicate)) |
((nil) (try-completion string sh-shell-variables predicate)) |
3229 |
(lambda (test-completion string sh-shell-variables predicate)) |
(lambda (test-completion string sh-shell-variables predicate)) |
3230 |
(t (all-completions string sh-shell-variables predicate))))) |
(t (all-completions string sh-shell-variables predicate))))) |
3231 |
|
|
3255 |
|
|
3256 |
(define-skeleton sh-function |
(define-skeleton sh-function |
3257 |
"Insert a function definition. See `sh-feature'." |
"Insert a function definition. See `sh-feature'." |
3258 |
(bash eval sh-modify ksh88 |
(bash sh-modify ksh88 |
3259 |
3 "() {") |
3 "() {") |
3260 |
(ksh88 "name: " |
(ksh88 "name: " |
3261 |
"function " str " {" \n |
"function " str " {" \n |
3262 |
> _ \n |
> _ \n |
3263 |
< "}" \n) |
< "}" \n) |
3264 |
(rc eval sh-modify ksh88 |
(rc sh-modify ksh88 |
3265 |
1 "fn ") |
1 "fn ") |
3266 |
(sh () |
(sh () |
3267 |
"() {" \n |
"() {" \n |
3337 |
> "select " str " in " _ "; do" \n |
> "select " str " in " _ "; do" \n |
3338 |
> ?$ str \n |
> ?$ str \n |
3339 |
"done" > \n) |
"done" > \n) |
3340 |
(bash eval sh-append ksh88)) |
(bash sh-append ksh88)) |
3341 |
;;;(put 'sh-select 'menu-enable '(sh-feature sh-select)) |
;;;(put 'sh-select 'menu-enable '(sh-feature sh-select)) |
3342 |
|
|
3343 |
|
|
3344 |
|
|
3345 |
(define-skeleton sh-tmp-file |
(define-skeleton sh-tmp-file |
3346 |
"Insert code to setup temporary file handling. See `sh-feature'." |
"Insert code to setup temporary file handling. See `sh-feature'." |
3347 |
(bash eval identity ksh88) |
(bash sh-append ksh88) |
3348 |
(csh (file-name-nondirectory (buffer-file-name)) |
(csh (file-name-nondirectory (buffer-file-name)) |
3349 |
"set tmp = /tmp/" str ".$$" \n |
"set tmp = /tmp/" str ".$$" \n |
3350 |
"onintr exit" \n _ |
"onintr exit" \n _ |
3363 |
_ \n |
_ \n |
3364 |
?\} > \n |
?\} > \n |
3365 |
?\} > \n) |
?\} > \n) |
3366 |
(ksh88 eval sh-modify sh |
(ksh88 sh-modify sh |
3367 |
7 "EXIT") |
7 "EXIT") |
3368 |
(rc (file-name-nondirectory (buffer-file-name)) |
(rc (file-name-nondirectory (buffer-file-name)) |
3369 |
> "tmp = /tmp/" str ".$pid" \n |
> "tmp = /tmp/" str ".$pid" \n |
3387 |
|
|
3388 |
(define-skeleton sh-while |
(define-skeleton sh-while |
3389 |
"Insert a while loop. See `sh-feature'." |
"Insert a while loop. See `sh-feature'." |
3390 |
(csh eval sh-modify sh |
(csh sh-modify sh |
3391 |
2 "" |
2 "" |
3392 |
3 "while( " |
3 "while( " |
3393 |
5 " )" |
5 " )" |
3394 |
10 '< |
10 '< |
3395 |
11 "end") |
11 "end") |
3396 |
(es eval sh-modify sh |
(es sh-modify sh |
3397 |
3 "while { " |
3 "while { " |
3398 |
5 " } {" |
5 " } {" |
3399 |
10 ?\} ) |
10 ?\} ) |
3400 |
(rc eval sh-modify sh |
(rc sh-modify sh |
3401 |
3 "while( " |
3 "while( " |
3402 |
5 " ) {" |
5 " ) {" |
3403 |
10 ?\} ) |
10 ?\} ) |
3413 |
"Insert a while getopts loop. See `sh-feature'. |
"Insert a while getopts loop. See `sh-feature'. |
3414 |
Prompts for an options string which consists of letters for each recognized |
Prompts for an options string which consists of letters for each recognized |
3415 |
option followed by a colon `:' if the option accepts an argument." |
option followed by a colon `:' if the option accepts an argument." |
3416 |
(bash eval sh-modify sh |
(bash sh-modify sh |
3417 |
18 "${0##*/}") |
18 "${0##*/}") |
3418 |
(csh nil |
(csh nil |
3419 |
"while( 1 )" \n |
"while( 1 )" \n |
3438 |
< < "endsw" \n |
< < "endsw" \n |
3439 |
"shift" \n |
"shift" \n |
3440 |
< "end" \n) |
< "end" \n) |
3441 |
(ksh88 eval sh-modify sh |
(ksh88 sh-modify sh |
3442 |
16 "print" |
16 "print" |
3443 |
18 "${0##*/}" |
18 "${0##*/}" |
3444 |
36 "OPTIND-1") |
37 "OPTIND-1") |
3445 |
(posix eval sh-modify sh |
(posix sh-modify sh |
3446 |
18 "$(basename $0)") |
18 "$(basename $0)") |
3447 |
(sh "optstring: " |
(sh "optstring: " |
3448 |
> "while getopts :" str " OPT; do" \n |
> "while getopts :" str " OPT; do" \n |
3507 |
(sh-quoted-p) |
(sh-quoted-p) |
3508 |
(end-of-line 2)) |
(end-of-line 2)) |
3509 |
(newline) |
(newline) |
3510 |
(save-excursion (insert ?\n sh-here-document-word))))) |
(save-excursion |
3511 |
|
(insert ?\n (substring |
3512 |
|
sh-here-document-word |
3513 |
|
(if (string-match "^-" sh-here-document-word) 1 0))))))) |
3514 |
|
|
3515 |
|
|
3516 |
;; various other commands |
;; various other commands |
3555 |
|
|
3556 |
(provide 'sh-script) |
(provide 'sh-script) |
3557 |
|
|
3558 |
|
;;; arch-tag: eccd8b72-f337-4fc2-ae86-18155a69d937 |
3559 |
;;; sh-script.el ends here |
;;; sh-script.el ends here |