1c80476e4SDavid E. O'Brien;; csh-mode.el --- csh (and tcsh) script editing mode for Emacs. 2c80476e4SDavid E. O'Brien;; 3c80476e4SDavid E. O'Brien;; Version: 1.2 4c80476e4SDavid E. O'Brien;; Date: April 2, 1999 5*b2d5d167SMark Peek;; Maintainer: Dan Harkless <software@harkless.org> 6c80476e4SDavid E. O'Brien;; 7c80476e4SDavid E. O'Brien;; Description: 8c80476e4SDavid E. O'Brien;; csh and tcsh script editing mode for Emacs. 9c80476e4SDavid E. O'Brien;; 10c80476e4SDavid E. O'Brien;; Installation: 11c80476e4SDavid E. O'Brien;; Put csh-mode.el in some directory in your load-path and load it. 12c80476e4SDavid E. O'Brien;; 13c80476e4SDavid E. O'Brien;; Usage: 14c80476e4SDavid E. O'Brien;; This major mode assists shell script writers with indentation 15c80476e4SDavid E. O'Brien;; control and control structure construct matching in much the same 16c80476e4SDavid E. O'Brien;; fashion as other programming language modes. Invoke describe-mode 17c80476e4SDavid E. O'Brien;; for more information. 18c80476e4SDavid E. O'Brien;; 19c80476e4SDavid E. O'Brien;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 20c80476e4SDavid E. O'Brien;; 21c80476e4SDavid E. O'Brien;; Author key: 22*b2d5d167SMark Peek;; DH - Dan Harkless <software@harkless.org> 23c80476e4SDavid E. O'Brien;; CM - Carlo Migliorini <migliorini@sodalia.it> 24c80476e4SDavid E. O'Brien;; JR - Jack Repenning <jackr@sgi.com> 25c80476e4SDavid E. O'Brien;; GE - Gary Ellison <Gary.F.Ellison@att.com> 26c80476e4SDavid E. O'Brien;; 27c80476e4SDavid E. O'Brien;; *** REVISION HISTORY *** 28c80476e4SDavid E. O'Brien;; 29c80476e4SDavid E. O'Brien;; DATE MOD. BY REASON FOR MODIFICATION 30c80476e4SDavid E. O'Brien;; --------- -- -------------------------------------------------------------- 31c80476e4SDavid E. O'Brien;; 2 Apr 99 DH 1.2: Noticed an out-of-date comment referencing .bashrc etc. 32c80476e4SDavid E. O'Brien;; 11 Dec 96 DH 1.1: ksh-mode just indented continuation lines by 1 space. 33c80476e4SDavid E. O'Brien;; csh-mode looks at the first line and indents properly to line 34c80476e4SDavid E. O'Brien;; up under the open-paren, quote, or command. 35c80476e4SDavid E. O'Brien;; 11 Dec 96 DH Added fontification for history substitutions. 36c80476e4SDavid E. O'Brien;; 10 Dec 96 DH Added indentation and fontification for labels. Added 37c80476e4SDavid E. O'Brien;; fontification for variables and backquoted strings. 38c80476e4SDavid E. O'Brien;; 9 Dec 96 DH 1.0: Brought csh-mode up to the level of functionality of 39c80476e4SDavid E. O'Brien;; the original ksh-mode. 40c80476e4SDavid E. O'Brien;; 7 Oct 96 CM 0.1: Hacked ksh-mode.el into minimally functional csh-mode.el 41c80476e4SDavid E. O'Brien;; by doing search-and-replace and some keyword changes. 42c80476e4SDavid E. O'Brien;; 8 Aug 96 JR (Last modification to ksh-mode 2.6.) 43c80476e4SDavid E. O'Brien;; [...] 44c80476e4SDavid E. O'Brien;; 19 Jun 92 GE (Conception of ksh-mode.) 45c80476e4SDavid E. O'Brien;; 46c80476e4SDavid E. O'Brien;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 47c80476e4SDavid E. O'Brien 48c80476e4SDavid E. O'Brien 49c80476e4SDavid E. O'Brien(defconst csh-mode-version "1.2" 50c80476e4SDavid E. O'Brien "*Version number of this version of csh-mode") 51c80476e4SDavid E. O'Brien 52c80476e4SDavid E. O'Brien(defvar csh-mode-hook 53c80476e4SDavid E. O'Brien '(lambda () 54c80476e4SDavid E. O'Brien (auto-fill-mode 1)) 55c80476e4SDavid E. O'Brien "Hook to run each time csh-mode is entered.") 56c80476e4SDavid E. O'Brien 57c80476e4SDavid E. O'Brien 58c80476e4SDavid E. O'Brien;; 59c80476e4SDavid E. O'Brien;; -------------------------------------------> Variables controlling completion 60c80476e4SDavid E. O'Brien;; 61c80476e4SDavid E. O'Brien(defvar csh-completion-list '()) 62c80476e4SDavid E. O'Brien(make-variable-buffer-local 'csh-completion-list) 63c80476e4SDavid E. O'Brien(set-default 'csh-completion-list '()) 64c80476e4SDavid E. O'Brien;; 65c80476e4SDavid E. O'Brien;; -type- : type number, 0:misc, 1:variable, 2:function 66c80476e4SDavid E. O'Brien;; -regexp-: regexp used to parse the script 67c80476e4SDavid E. O'Brien;; -match- : used by match-beginning/end to pickup target 68c80476e4SDavid E. O'Brien;; 69c80476e4SDavid E. O'Brien(defvar csh-completion-type-misc 0) 70c80476e4SDavid E. O'Brien(defvar csh-completion-regexp-var "\\([A-Za-z_0-9]+\\)=") 71c80476e4SDavid E. O'Brien(defvar csh-completion-type-var 1) 72c80476e4SDavid E. O'Brien(defvar csh-completion-match-var 1) 73c80476e4SDavid E. O'Brien(defvar csh-completion-regexp-var2 "\\$\\({\\|{#\\)?\\([A-Za-z_0-9]+\\)[#%:}]?") 74c80476e4SDavid E. O'Brien(defvar csh-completion-match-var2 2) 75c80476e4SDavid E. O'Brien(defvar csh-completion-regexp-function 76c80476e4SDavid E. O'Brien "\\(function\\)?[ \t]*\\([A-Za-z_0-9]+\\)[ \t]*([ \t]*)") 77c80476e4SDavid E. O'Brien(defvar csh-completion-type-function 2) 78c80476e4SDavid E. O'Brien(defvar csh-completion-match-function 2) 79c80476e4SDavid E. O'Brien 80c80476e4SDavid E. O'Brien 81c80476e4SDavid E. O'Brien;; 82c80476e4SDavid E. O'Brien;; ------------------------------------> Variables controlling indentation style 83c80476e4SDavid E. O'Brien;; 84c80476e4SDavid E. O'Brien(defvar csh-indent 4 85c80476e4SDavid E. O'Brien "*Indentation of csh statements with respect to containing block. A value 86c80476e4SDavid E. O'Brienof nil indicates compound list keyword \(\"do\" and \"then\"\) alignment.") 87c80476e4SDavid E. O'Brien 88c80476e4SDavid E. O'Brien(defvar csh-case-item-offset csh-indent 89c80476e4SDavid E. O'Brien "*Additional indentation for case items within a case statement.") 90c80476e4SDavid E. O'Brien(defvar csh-case-indent nil 91c80476e4SDavid E. O'Brien "*Additional indentation for statements under case items.") 92c80476e4SDavid E. O'Brien(defvar csh-comment-regexp "^\\s *#" 93c80476e4SDavid E. O'Brien "*Regular expression used to recognize comments. Customize to support 94c80476e4SDavid E. O'Briencsh-like languages.") 95c80476e4SDavid E. O'Brien(defvar csh-match-and-tell t 96c80476e4SDavid E. O'Brien "*If non-nil echo in the minibuffer the matching compound command 97c80476e4SDavid E. O'Brienfor the \"breaksw\", \"end\", or \"endif\".") 98c80476e4SDavid E. O'Brien(defvar csh-tab-always-indent t 99c80476e4SDavid E. O'Brien "*Controls the operation of the TAB key. If t (the default), always 100c80476e4SDavid E. O'Brienreindent the current line. If nil, indent the current line only if 101c80476e4SDavid E. O'Brienpoint is at the left margin or in the line's indentation; otherwise 102c80476e4SDavid E. O'Brieninsert a tab.") 103c80476e4SDavid E. O'Brien 104c80476e4SDavid E. O'Brien 105c80476e4SDavid E. O'Brien;; 106c80476e4SDavid E. O'Brien;; ----------------------------------------> Constants containing syntax regexps 107c80476e4SDavid E. O'Brien;; 108c80476e4SDavid E. O'Brien(defconst csh-case-default-re 109c80476e4SDavid E. O'Brien "^\\s *\\(case\\|default\\)\\b" 110c80476e4SDavid E. O'Brien "Regexp used to locate grouping keywords case and default" ) 111c80476e4SDavid E. O'Brien 112c80476e4SDavid E. O'Brien(defconst csh-case-item-re "^\\s *\\(case .*\\|default\\):" 113c80476e4SDavid E. O'Brien "Regexp used to match case-items") 114c80476e4SDavid E. O'Brien 115c80476e4SDavid E. O'Brien(defconst csh-end-re "^\\s *end\\b" 116c80476e4SDavid E. O'Brien "Regexp used to match keyword: end") 117c80476e4SDavid E. O'Brien 118c80476e4SDavid E. O'Brien(defconst csh-endif-re "^\\s *endif\\b" 119c80476e4SDavid E. O'Brien "Regexp used to match keyword: endif") 120c80476e4SDavid E. O'Brien 121c80476e4SDavid E. O'Brien(defconst csh-endsw-re "^\\s *endsw\\b" 122c80476e4SDavid E. O'Brien "Regexp used to match keyword: endsw") 123c80476e4SDavid E. O'Brien 124c80476e4SDavid E. O'Brien(defconst csh-else-re "^\\s *\\belse\\(\\b\\|$\\)" 125c80476e4SDavid E. O'Brien "Regexp used to match keyword: else") 126c80476e4SDavid E. O'Brien 127c80476e4SDavid E. O'Brien(defconst csh-else-if-re "^\\s *\\belse if\\(\\b\\|$\\)" 128c80476e4SDavid E. O'Brien "Regexp used to match keyword pair: else if") 129c80476e4SDavid E. O'Brien 130c80476e4SDavid E. O'Brien(defconst csh-if-re "^\\s *if\\b.+\\(\\\\\\|\\bthen\\b\\)" 131c80476e4SDavid E. O'Brien "Regexp used to match non-one-line if statements") 132c80476e4SDavid E. O'Brien 133c80476e4SDavid E. O'Brien(defconst csh-iteration-keywords-re "^[^#\n]*\\s\"*\\b\\(while\\|foreach\\)\\b" 134c80476e4SDavid E. O'Brien "Match one of the keywords: while, foreach") 135c80476e4SDavid E. O'Brien 136c80476e4SDavid E. O'Brien(defconst csh-keywords-re 137c80476e4SDavid E. O'Brien "^\\s *\\(else\\b\\|foreach\\b\\|if\\b.+\\(\\\\\\|\\bthen\\b\\)\\|switch\\b\\|while\\b\\)" 138c80476e4SDavid E. O'Brien "Regexp used to detect compound command keywords: else, if, foreach, while") 139c80476e4SDavid E. O'Brien 140c80476e4SDavid E. O'Brien(defconst csh-label-re "^\\s *[^!#$\n ]+:" 141c80476e4SDavid E. O'Brien "Regexp used to match flow-control labels") 142c80476e4SDavid E. O'Brien 143c80476e4SDavid E. O'Brien(defconst csh-multiline-re "^.*\\\\$" 144c80476e4SDavid E. O'Brien "Regexp used to match a line with a statement using more lines.") 145c80476e4SDavid E. O'Brien 146c80476e4SDavid E. O'Brien(defconst csh-switch-re "^\\s *switch\\b" 147c80476e4SDavid E. O'Brien "Regexp used to match keyword: switch") 148c80476e4SDavid E. O'Brien 149c80476e4SDavid E. O'Brien 150c80476e4SDavid E. O'Brien;; 151c80476e4SDavid E. O'Brien;; ----------------------------------------> Variables controlling fontification 152c80476e4SDavid E. O'Brien;; 153c80476e4SDavid E. O'Brien(defvar csh-keywords '("@" "alias" "bg" "break" "breaksw" "case" "cd" "chdir" 154c80476e4SDavid E. O'Brien "continue" "default" "dirs" "echo" "else" "end" "endif" 155c80476e4SDavid E. O'Brien "endsw" "eval" "exec" "exit" "fg" "foreach" "glob" "goto" 156c80476e4SDavid E. O'Brien "hashstat" "history" "if" "jobs" "kill" "limit" "login" 157c80476e4SDavid E. O'Brien "logout" "limit" "notify" "onintr" "popd" "printenv" 158c80476e4SDavid E. O'Brien "pushd" "rehash" "repeat" "set" "setenv" "shift" "source" 159c80476e4SDavid E. O'Brien "stop" "suspend" "switch" "then" "time" "umask" "unalias" 160c80476e4SDavid E. O'Brien "unhash" "unlimit" "unset" "unsetenv" "wait" "while" 161c80476e4SDavid E. O'Brien ;; tcsh-keywords 162c80476e4SDavid E. O'Brien "alloc" "bindkey" "builtins" "complete" "echotc" 163c80476e4SDavid E. O'Brien "filetest" "hup" "log" "ls-F" "nice" "nohup" "sched" 164c80476e4SDavid E. O'Brien "settc" "setty" "telltc" "uncomplete" "where" "which")) 165c80476e4SDavid E. O'Brien 166c80476e4SDavid E. O'Brien(require 'font-lock) ; need to do this before referring to font-lock-* below 167c80476e4SDavid E. O'Brien 168c80476e4SDavid E. O'Brien(defconst csh-font-lock-keywords 169c80476e4SDavid E. O'Brien ;; NOTE: The order of some of the items in this list is significant. Do not 170c80476e4SDavid E. O'Brien ;; alphabetize or otherwise blindly rearrange. 171c80476e4SDavid E. O'Brien (list 172c80476e4SDavid E. O'Brien ;; Comments on line 1, which are missed by syntactic fontification. 173c80476e4SDavid E. O'Brien '("^#.*" 0 font-lock-comment-face) 174c80476e4SDavid E. O'Brien 175c80476e4SDavid E. O'Brien ;; Label definitions (1 means first parenthesized exp in regexp). 176c80476e4SDavid E. O'Brien '("^\\s *\\([^!#$\n ]+\\):" 1 font-lock-function-name-face) 177c80476e4SDavid E. O'Brien 178c80476e4SDavid E. O'Brien ;; Label references. 179c80476e4SDavid E. O'Brien '("\\b\\(goto\\|onintr\\)\\b\\s +\\([^!#$ \n\t]+\\)" 180c80476e4SDavid E. O'Brien 2 font-lock-function-name-face) 181c80476e4SDavid E. O'Brien 182c80476e4SDavid E. O'Brien ;; Variable settings. 183c80476e4SDavid E. O'Brien '("\\(@\\|set\\|setenv\\)\\s +\\([0-9A-Za-z_]+\\b\\)" 184c80476e4SDavid E. O'Brien 2 font-lock-variable-name-face) 185c80476e4SDavid E. O'Brien 186c80476e4SDavid E. O'Brien ;; Variable references not inside of strings. 187c80476e4SDavid E. O'Brien '("\\$[][0-9A-Za-z_#:?]+" 0 font-lock-variable-name-face) 188c80476e4SDavid E. O'Brien 189c80476e4SDavid E. O'Brien ;; Backquoted strings. 'keep' means to just fontify non-fontified text. 190c80476e4SDavid E. O'Brien '("`\\(.*\\)`" 1 font-lock-reference-face keep) 191c80476e4SDavid E. O'Brien 192c80476e4SDavid E. O'Brien ;; NOTE: The following variables need to be anchored to the beginning of 193c80476e4SDavid E. O'Brien ;; line to prevent re-fontifying text in comments. Due to this, we 194c80476e4SDavid E. O'Brien ;; can only catch a finite number of occurrences. More can be added. 195c80476e4SDavid E. O'Brien ;; The 't' means to override previous fontification. 196c80476e4SDavid E. O'Brien ;; 197c80476e4SDavid E. O'Brien ;; Variable references inside of " strings. 198c80476e4SDavid E. O'Brien '("^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*\"" 199c80476e4SDavid E. O'Brien 1 font-lock-variable-name-face t) ; 1 200c80476e4SDavid E. O'Brien '("^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*\\$[][0-9A-Za-z_#:?]+.*\"" 201c80476e4SDavid E. O'Brien 1 font-lock-variable-name-face t) ; 2 202c80476e4SDavid E. O'Brien (cons (concat "^[^#\n]*\".*\\(\\$[][0-9A-Za-z_#:?]+\\).*" 203c80476e4SDavid E. O'Brien "\\$[][0-9A-Za-z_#:?]+.*\\$[][0-9A-Za-z_#:?]+.*\"") 204c80476e4SDavid E. O'Brien (list 1 font-lock-variable-name-face t)) ; 3 205c80476e4SDavid E. O'Brien ;; 206c80476e4SDavid E. O'Brien ;; History substitutions. 207c80476e4SDavid E. O'Brien '("^![^~= \n\t]+" 0 font-lock-reference-face t) ; BOL 208c80476e4SDavid E. O'Brien '("^[^#\n]*[^#\\\n]\\(![^~= \n\t]+\\)" 1 font-lock-reference-face t) ; 1 209c80476e4SDavid E. O'Brien '("^[^#\n]*[^#\\\n]\\(![^~= \n\t]+\\).*![^~= \n\t]+" 210c80476e4SDavid E. O'Brien 1 font-lock-reference-face t) ; 2 211c80476e4SDavid E. O'Brien 212c80476e4SDavid E. O'Brien ;; Keywords. 213c80476e4SDavid E. O'Brien (cons (concat 214c80476e4SDavid E. O'Brien "\\(\\<" 215c80476e4SDavid E. O'Brien (mapconcat 'identity csh-keywords "\\>\\|\\<") 216c80476e4SDavid E. O'Brien "\\>\\)") 217c80476e4SDavid E. O'Brien 1) 218c80476e4SDavid E. O'Brien )) 219c80476e4SDavid E. O'Brien 220c80476e4SDavid E. O'Brien(put 'csh-mode 'font-lock-keywords 'csh-font-lock-keywords) 221c80476e4SDavid E. O'Brien 222c80476e4SDavid E. O'Brien 223c80476e4SDavid E. O'Brien;; 224c80476e4SDavid E. O'Brien;; -------------------------------------------------------> Mode-specific tables 225c80476e4SDavid E. O'Brien;; 226c80476e4SDavid E. O'Brien(defvar csh-mode-abbrev-table nil 227c80476e4SDavid E. O'Brien "Abbrev table used while in csh mode.") 228c80476e4SDavid E. O'Brien(define-abbrev-table 'csh-mode-abbrev-table ()) 229c80476e4SDavid E. O'Brien 230c80476e4SDavid E. O'Brien(defvar csh-mode-map nil 231c80476e4SDavid E. O'Brien "Keymap used in csh mode") 232c80476e4SDavid E. O'Brien(if csh-mode-map 233c80476e4SDavid E. O'Brien () 234c80476e4SDavid E. O'Brien (setq csh-mode-map (make-sparse-keymap)) 235c80476e4SDavid E. O'Brien;;(define-key csh-mode-map "\177" 'backward-delete-char-untabify) 236c80476e4SDavid E. O'Brien (define-key csh-mode-map "\C-c\t" 'csh-completion-init-and-pickup) 237c80476e4SDavid E. O'Brien (define-key csh-mode-map "\C-j" 'reindent-then-newline-and-indent) 238c80476e4SDavid E. O'Brien (define-key csh-mode-map "\e\t" 'csh-complete-symbol) 239c80476e4SDavid E. O'Brien (define-key csh-mode-map "\n" 'reindent-then-newline-and-indent) 240c80476e4SDavid E. O'Brien (define-key csh-mode-map '[return] 'reindent-then-newline-and-indent) 241c80476e4SDavid E. O'Brien (define-key csh-mode-map "\t" 'csh-indent-command) 242c80476e4SDavid E. O'Brien;;(define-key csh-mode-map "\t" 'csh-indent-line) 243c80476e4SDavid E. O'Brien ) 244c80476e4SDavid E. O'Brien 245c80476e4SDavid E. O'Brien(defvar csh-mode-syntax-table nil 246c80476e4SDavid E. O'Brien "Syntax table used while in csh mode.") 247c80476e4SDavid E. O'Brien(if csh-mode-syntax-table 248c80476e4SDavid E. O'Brien ;; If it's already set up, don't change it. 249c80476e4SDavid E. O'Brien () 250c80476e4SDavid E. O'Brien ;; Else, create it from the standard table and modify entries that need to be. 251c80476e4SDavid E. O'Brien (setq csh-mode-syntax-table (make-syntax-table)) 252c80476e4SDavid E. O'Brien (modify-syntax-entry ?& "." csh-mode-syntax-table) ; & -punctuation 253c80476e4SDavid E. O'Brien (modify-syntax-entry ?* "." csh-mode-syntax-table) ; * -punctuation 254c80476e4SDavid E. O'Brien (modify-syntax-entry ?- "." csh-mode-syntax-table) ; - -punctuation 255c80476e4SDavid E. O'Brien (modify-syntax-entry ?= "." csh-mode-syntax-table) ; = -punctuation 256c80476e4SDavid E. O'Brien (modify-syntax-entry ?+ "." csh-mode-syntax-table) ; + -punctuation 257c80476e4SDavid E. O'Brien (modify-syntax-entry ?| "." csh-mode-syntax-table) ; | -punctuation 258c80476e4SDavid E. O'Brien (modify-syntax-entry ?< "." csh-mode-syntax-table) ; < -punctuation 259c80476e4SDavid E. O'Brien (modify-syntax-entry ?> "." csh-mode-syntax-table) ; > -punctuation 260c80476e4SDavid E. O'Brien (modify-syntax-entry ?/ "." csh-mode-syntax-table) ; / -punctuation 261c80476e4SDavid E. O'Brien (modify-syntax-entry ?\' "\"" csh-mode-syntax-table) ; ' -string quote 262c80476e4SDavid E. O'Brien (modify-syntax-entry ?. "w" csh-mode-syntax-table) ; . -word constituent 263c80476e4SDavid E. O'Brien (modify-syntax-entry ?? "w" csh-mode-syntax-table) ; ? -word constituent 264c80476e4SDavid E. O'Brien 265c80476e4SDavid E. O'Brien ;; \n - comment ender, first character of 2-char comment sequence 266c80476e4SDavid E. O'Brien (modify-syntax-entry ?\n "> 1" csh-mode-syntax-table) ; # -word constituent 267c80476e4SDavid E. O'Brien 268c80476e4SDavid E. O'Brien ;; - whitespace, first character of 2-char comment sequence 269c80476e4SDavid E. O'Brien (modify-syntax-entry ? " 1" csh-mode-syntax-table) ; 270c80476e4SDavid E. O'Brien 271c80476e4SDavid E. O'Brien ;; \t - whitespace, first character of 2-char comment sequence 272c80476e4SDavid E. O'Brien (modify-syntax-entry ?\t " 1" csh-mode-syntax-table) ; # -word constituent 273c80476e4SDavid E. O'Brien 274c80476e4SDavid E. O'Brien ;; # - word constituent, second character of 2-char comment sequence 275c80476e4SDavid E. O'Brien (modify-syntax-entry ?# "w 2" csh-mode-syntax-table) ; # -word constituent 276c80476e4SDavid E. O'Brien ) 277c80476e4SDavid E. O'Brien 278c80476e4SDavid E. O'Brien 279c80476e4SDavid E. O'Brien;; 280c80476e4SDavid E. O'Brien;; ------------------------------------------------------------------> Functions 281c80476e4SDavid E. O'Brien;; 282c80476e4SDavid E. O'Brien(defun csh-current-line () 283c80476e4SDavid E. O'Brien "Return the vertical position of point in the buffer. 284c80476e4SDavid E. O'BrienTop line is 1." 285c80476e4SDavid E. O'Brien (+ (count-lines (point-min) (point)) 286c80476e4SDavid E. O'Brien (if (= (current-column) 0) 1 0)) 287c80476e4SDavid E. O'Brien ) 288c80476e4SDavid E. O'Brien 289c80476e4SDavid E. O'Brien(defun csh-get-compound-level 290c80476e4SDavid E. O'Brien (begin-re end-re anchor-point &optional balance-list) 291c80476e4SDavid E. O'Brien "Determine how much to indent this structure. Return a list (level line) 292c80476e4SDavid E. O'Brienof the matching compound command or nil if no match found." 293c80476e4SDavid E. O'Brien (let* 294c80476e4SDavid E. O'Brien (;; Locate the next compound begin keyword bounded by point-min 295c80476e4SDavid E. O'Brien (match-point (if (re-search-backward begin-re (point-min) t) 296c80476e4SDavid E. O'Brien (match-beginning 0) 0)) 297c80476e4SDavid E. O'Brien (nest-column (if (zerop match-point) 298c80476e4SDavid E. O'Brien 1 299c80476e4SDavid E. O'Brien (progn 300c80476e4SDavid E. O'Brien (goto-char match-point) 301c80476e4SDavid E. O'Brien (current-indentation)))) 302c80476e4SDavid E. O'Brien (nest-list (cons 0 0)) ;; sentinel cons since cdr is >= 1 303c80476e4SDavid E. O'Brien ) 304c80476e4SDavid E. O'Brien (if (zerop match-point) 305c80476e4SDavid E. O'Brien nil ;; graceful exit from recursion 306c80476e4SDavid E. O'Brien (progn 307c80476e4SDavid E. O'Brien (if (nlistp balance-list) 308c80476e4SDavid E. O'Brien (setq balance-list (list))) 309c80476e4SDavid E. O'Brien ;; Now search forward from matching start keyword for end keyword 310c80476e4SDavid E. O'Brien (while (and (consp nest-list) (zerop (cdr nest-list)) 311c80476e4SDavid E. O'Brien (re-search-forward end-re anchor-point t)) 312c80476e4SDavid E. O'Brien (if (not (memq (point) balance-list)) 313c80476e4SDavid E. O'Brien (progn 314c80476e4SDavid E. O'Brien (setq balance-list (cons (point) balance-list)) 315c80476e4SDavid E. O'Brien (goto-char match-point) ;; beginning of compound cmd 316c80476e4SDavid E. O'Brien (setq nest-list 317c80476e4SDavid E. O'Brien (csh-get-compound-level begin-re end-re 318c80476e4SDavid E. O'Brien anchor-point balance-list)) 319c80476e4SDavid E. O'Brien ))) 320c80476e4SDavid E. O'Brien 321c80476e4SDavid E. O'Brien (cond ((consp nest-list) 322c80476e4SDavid E. O'Brien (if (zerop (cdr nest-list)) 323c80476e4SDavid E. O'Brien (progn 324c80476e4SDavid E. O'Brien (goto-char match-point) 325c80476e4SDavid E. O'Brien (cons nest-column (csh-current-line))) 326c80476e4SDavid E. O'Brien nest-list)) 327c80476e4SDavid E. O'Brien (t nil) 328c80476e4SDavid E. O'Brien ) 329c80476e4SDavid E. O'Brien ) 330c80476e4SDavid E. O'Brien ) 331c80476e4SDavid E. O'Brien ) 332c80476e4SDavid E. O'Brien ) 333c80476e4SDavid E. O'Brien 334c80476e4SDavid E. O'Brien(defun csh-get-nest-level () 335c80476e4SDavid E. O'Brien "Return a 2 element list (nest-level nest-line) describing where the 336c80476e4SDavid E. O'Briencurrent line should nest." 337c80476e4SDavid E. O'Brien (let ((case-fold-search) 338c80476e4SDavid E. O'Brien (level)) 339c80476e4SDavid E. O'Brien (save-excursion 340c80476e4SDavid E. O'Brien (forward-line -1) 341c80476e4SDavid E. O'Brien (while (and (not (bobp)) 342c80476e4SDavid E. O'Brien (null level)) 343c80476e4SDavid E. O'Brien (if (and (not (looking-at "^\\s *$")) 344c80476e4SDavid E. O'Brien (not (save-excursion 345c80476e4SDavid E. O'Brien (forward-line -1) 346c80476e4SDavid E. O'Brien (beginning-of-line) 347c80476e4SDavid E. O'Brien (looking-at csh-multiline-re))) 348c80476e4SDavid E. O'Brien (not (looking-at csh-comment-regexp))) 349c80476e4SDavid E. O'Brien (setq level (cons (current-indentation) 350c80476e4SDavid E. O'Brien (csh-current-line))) 351c80476e4SDavid E. O'Brien (forward-line -1) 352c80476e4SDavid E. O'Brien );; if 353c80476e4SDavid E. O'Brien );; while 354c80476e4SDavid E. O'Brien (if (null level) 355c80476e4SDavid E. O'Brien (cons (current-indentation) (csh-current-line)) 356c80476e4SDavid E. O'Brien level) 357c80476e4SDavid E. O'Brien ) 358c80476e4SDavid E. O'Brien ) 359c80476e4SDavid E. O'Brien ) 360c80476e4SDavid E. O'Brien 361c80476e4SDavid E. O'Brien(defun csh-get-nester-column (nest-line) 362c80476e4SDavid E. O'Brien "Return the column to indent to with respect to nest-line taking 363c80476e4SDavid E. O'Brieninto consideration keywords and other nesting constructs." 364c80476e4SDavid E. O'Brien (save-excursion 365c80476e4SDavid E. O'Brien (let ((fence-post) 366c80476e4SDavid E. O'Brien (case-fold-search) 367c80476e4SDavid E. O'Brien (start-line (csh-current-line))) 368c80476e4SDavid E. O'Brien ;; 369c80476e4SDavid E. O'Brien ;; Handle case item indentation constructs for this line 370c80476e4SDavid E. O'Brien (cond ((looking-at csh-case-item-re) 371c80476e4SDavid E. O'Brien ;; This line is a case item... 372c80476e4SDavid E. O'Brien (save-excursion 373c80476e4SDavid E. O'Brien (goto-line nest-line) 374c80476e4SDavid E. O'Brien (let ((fence-post (save-excursion (end-of-line) (point)))) 375c80476e4SDavid E. O'Brien (cond ((re-search-forward csh-switch-re fence-post t) 376c80476e4SDavid E. O'Brien ;; If this is the first case under the switch, indent. 377c80476e4SDavid E. O'Brien (goto-char (match-beginning 0)) 378c80476e4SDavid E. O'Brien (+ (current-indentation) csh-case-item-offset)) 379c80476e4SDavid E. O'Brien 380c80476e4SDavid E. O'Brien ((re-search-forward csh-case-item-re fence-post t) 381c80476e4SDavid E. O'Brien ;; If this is another case right under a previous case 382c80476e4SDavid E. O'Brien ;; without intervening code, stay at the same 383c80476e4SDavid E. O'Brien ;; indentation. 384c80476e4SDavid E. O'Brien (goto-char (match-beginning 0)) 385c80476e4SDavid E. O'Brien (current-indentation)) 386c80476e4SDavid E. O'Brien 387c80476e4SDavid E. O'Brien (t 388c80476e4SDavid E. O'Brien ;; Else, this is a new case. Outdent. 389c80476e4SDavid E. O'Brien (- (current-indentation) csh-case-item-offset)) 390c80476e4SDavid E. O'Brien ) 391c80476e4SDavid E. O'Brien ))) 392c80476e4SDavid E. O'Brien (t;; Not a case-item. What to do relative to the nest-line? 393c80476e4SDavid E. O'Brien (save-excursion 394c80476e4SDavid E. O'Brien (goto-line nest-line) 395c80476e4SDavid E. O'Brien (setq fence-post (save-excursion (end-of-line) (point))) 396c80476e4SDavid E. O'Brien (save-excursion 397c80476e4SDavid E. O'Brien (cond 398c80476e4SDavid E. O'Brien ;; 399c80476e4SDavid E. O'Brien ;; Check if we are in a continued statement 400c80476e4SDavid E. O'Brien ((and (looking-at csh-multiline-re) 401c80476e4SDavid E. O'Brien (save-excursion 402c80476e4SDavid E. O'Brien (goto-line (1- start-line)) 403c80476e4SDavid E. O'Brien (looking-at csh-multiline-re))) 404c80476e4SDavid E. O'Brien (if (looking-at ".*[\'\"]\\\\") 405c80476e4SDavid E. O'Brien ;; If this is a continued string, indent under 406c80476e4SDavid E. O'Brien ;; opening quote. 407c80476e4SDavid E. O'Brien (progn 408c80476e4SDavid E. O'Brien (re-search-forward "[\'\"]") 409c80476e4SDavid E. O'Brien (forward-char -1)) 410c80476e4SDavid E. O'Brien (if (looking-at ".*([^\)\n]*\\\\") 411c80476e4SDavid E. O'Brien ;; Else if this is a continued parenthesized 412c80476e4SDavid E. O'Brien ;; list, indent after paren. 413c80476e4SDavid E. O'Brien (re-search-forward "(" fence-post t) 414c80476e4SDavid E. O'Brien ;; Else, indent after whitespace after first word. 415c80476e4SDavid E. O'Brien (re-search-forward "[^ \t]+[ \t]+" fence-post t))) 416c80476e4SDavid E. O'Brien (current-column)) 417c80476e4SDavid E. O'Brien 418c80476e4SDavid E. O'Brien ;; In order to locate the column of the keyword, 419c80476e4SDavid E. O'Brien ;; which might be embedded within a case-item, 420c80476e4SDavid E. O'Brien ;; it is necessary to use re-search-forward. 421c80476e4SDavid E. O'Brien ;; Search by literal case, since shell is 422c80476e4SDavid E. O'Brien ;; case-sensitive. 423c80476e4SDavid E. O'Brien ((re-search-forward csh-keywords-re fence-post t) 424c80476e4SDavid E. O'Brien (goto-char (match-beginning 1)) 425c80476e4SDavid E. O'Brien (if (looking-at csh-switch-re) 426c80476e4SDavid E. O'Brien (+ (current-indentation) csh-case-item-offset) 427c80476e4SDavid E. O'Brien (+ (current-indentation) 428c80476e4SDavid E. O'Brien (if (null csh-indent) 429c80476e4SDavid E. O'Brien 2 csh-indent) 430c80476e4SDavid E. O'Brien ))) 431c80476e4SDavid E. O'Brien 432c80476e4SDavid E. O'Brien ((re-search-forward csh-case-default-re fence-post t) 433c80476e4SDavid E. O'Brien (if (null csh-indent) 434c80476e4SDavid E. O'Brien (progn 435c80476e4SDavid E. O'Brien (goto-char (match-end 1)) 436c80476e4SDavid E. O'Brien (+ (current-indentation) 1)) 437c80476e4SDavid E. O'Brien (progn 438c80476e4SDavid E. O'Brien (goto-char (match-beginning 1)) 439c80476e4SDavid E. O'Brien (+ (current-indentation) csh-indent)) 440c80476e4SDavid E. O'Brien )) 441c80476e4SDavid E. O'Brien 442c80476e4SDavid E. O'Brien ;; 443c80476e4SDavid E. O'Brien ;; Now detect first statement under a case item 444c80476e4SDavid E. O'Brien ((looking-at csh-case-item-re) 445c80476e4SDavid E. O'Brien (if (null csh-case-indent) 446c80476e4SDavid E. O'Brien (progn 447c80476e4SDavid E. O'Brien (re-search-forward csh-case-item-re fence-post t) 448c80476e4SDavid E. O'Brien (goto-char (match-end 1)) 449c80476e4SDavid E. O'Brien (+ (current-column) 1)) 450c80476e4SDavid E. O'Brien (+ (current-indentation) csh-case-indent))) 451c80476e4SDavid E. O'Brien 452c80476e4SDavid E. O'Brien ;; 453c80476e4SDavid E. O'Brien ;; If this is the first statement under a control-flow 454c80476e4SDavid E. O'Brien ;; label, indent one level. 455c80476e4SDavid E. O'Brien ((csh-looking-at-label) 456c80476e4SDavid E. O'Brien (+ (current-indentation) csh-indent)) 457c80476e4SDavid E. O'Brien 458c80476e4SDavid E. O'Brien ;; This is hosed when using current-column 459c80476e4SDavid E. O'Brien ;; and there is a multi-command expression as the 460c80476e4SDavid E. O'Brien ;; nester. 461c80476e4SDavid E. O'Brien (t (current-indentation))) 462c80476e4SDavid E. O'Brien ) 463c80476e4SDavid E. O'Brien ));; excursion over 464c80476e4SDavid E. O'Brien );; Not a case-item 465c80476e4SDavid E. O'Brien );;let 466c80476e4SDavid E. O'Brien );; excursion 467c80476e4SDavid E. O'Brien );; defun 468c80476e4SDavid E. O'Brien 469c80476e4SDavid E. O'Brien(defun csh-indent-command () 470c80476e4SDavid E. O'Brien "Indent current line relative to containing block and allow for 471c80476e4SDavid E. O'Briencsh-tab-always-indent customization" 472c80476e4SDavid E. O'Brien (interactive) 473c80476e4SDavid E. O'Brien (let (case-fold-search) 474c80476e4SDavid E. O'Brien (cond ((save-excursion 475c80476e4SDavid E. O'Brien (skip-chars-backward " \t") 476c80476e4SDavid E. O'Brien (bolp)) 477c80476e4SDavid E. O'Brien (csh-indent-line)) 478c80476e4SDavid E. O'Brien (csh-tab-always-indent 479c80476e4SDavid E. O'Brien (save-excursion 480c80476e4SDavid E. O'Brien (csh-indent-line))) 481c80476e4SDavid E. O'Brien (t (insert-tab)) 482c80476e4SDavid E. O'Brien )) 483c80476e4SDavid E. O'Brien ) 484c80476e4SDavid E. O'Brien 485c80476e4SDavid E. O'Brien(defun csh-indent-line () 486c80476e4SDavid E. O'Brien "Indent current line as far as it should go according 487c80476e4SDavid E. O'Briento the syntax/context" 488c80476e4SDavid E. O'Brien (interactive) 489c80476e4SDavid E. O'Brien (let (case-fold-search) 490c80476e4SDavid E. O'Brien (save-excursion 491c80476e4SDavid E. O'Brien (beginning-of-line) 492c80476e4SDavid E. O'Brien (if (bobp) 493c80476e4SDavid E. O'Brien nil 494c80476e4SDavid E. O'Brien ;; 495c80476e4SDavid E. O'Brien ;; Align this line to current nesting level 496c80476e4SDavid E. O'Brien (let* 497c80476e4SDavid E. O'Brien ( 498c80476e4SDavid E. O'Brien (level-list (csh-get-nest-level)) ; Where to nest against 499c80476e4SDavid E. O'Brien ;; (last-line-level (car level-list)) 500c80476e4SDavid E. O'Brien (this-line-level (current-indentation)) 501c80476e4SDavid E. O'Brien (nester-column (csh-get-nester-column (cdr level-list))) 502c80476e4SDavid E. O'Brien (struct-match (csh-match-structure-and-reindent)) 503c80476e4SDavid E. O'Brien ) 504c80476e4SDavid E. O'Brien (if struct-match 505c80476e4SDavid E. O'Brien (setq nester-column struct-match)) 506c80476e4SDavid E. O'Brien (if (eq nester-column this-line-level) 507c80476e4SDavid E. O'Brien nil 508c80476e4SDavid E. O'Brien (beginning-of-line) 509c80476e4SDavid E. O'Brien (let ((beg (point))) 510c80476e4SDavid E. O'Brien (back-to-indentation) 511c80476e4SDavid E. O'Brien (delete-region beg (point))) 512c80476e4SDavid E. O'Brien (indent-to nester-column)) 513c80476e4SDavid E. O'Brien );; let* 514c80476e4SDavid E. O'Brien );; if 515c80476e4SDavid E. O'Brien );; excursion 516c80476e4SDavid E. O'Brien ;; 517c80476e4SDavid E. O'Brien ;; Position point on this line 518c80476e4SDavid E. O'Brien (let* 519c80476e4SDavid E. O'Brien ( 520c80476e4SDavid E. O'Brien (this-line-level (current-indentation)) 521c80476e4SDavid E. O'Brien (this-bol (save-excursion 522c80476e4SDavid E. O'Brien (beginning-of-line) 523c80476e4SDavid E. O'Brien (point))) 524c80476e4SDavid E. O'Brien (this-point (- (point) this-bol)) 525c80476e4SDavid E. O'Brien ) 526c80476e4SDavid E. O'Brien (cond ((> this-line-level this-point);; point in initial white space 527c80476e4SDavid E. O'Brien (back-to-indentation)) 528c80476e4SDavid E. O'Brien (t nil) 529c80476e4SDavid E. O'Brien );; cond 530c80476e4SDavid E. O'Brien );; let* 531c80476e4SDavid E. O'Brien );; let 532c80476e4SDavid E. O'Brien );; defun 533c80476e4SDavid E. O'Brien 534c80476e4SDavid E. O'Brien(defun csh-indent-region (start end) 535c80476e4SDavid E. O'Brien "From start to end, indent each line." 536c80476e4SDavid E. O'Brien ;; The algorithm is just moving through the region line by line with 537c80476e4SDavid E. O'Brien ;; the match noise turned off. Only modifies nonempty lines. 538c80476e4SDavid E. O'Brien (save-excursion 539c80476e4SDavid E. O'Brien (let (csh-match-and-tell 540c80476e4SDavid E. O'Brien (endmark (copy-marker end))) 541c80476e4SDavid E. O'Brien 542c80476e4SDavid E. O'Brien (goto-char start) 543c80476e4SDavid E. O'Brien (beginning-of-line) 544c80476e4SDavid E. O'Brien (setq start (point)) 545c80476e4SDavid E. O'Brien (while (> (marker-position endmark) start) 546c80476e4SDavid E. O'Brien (if (not (and (bolp) (eolp))) 547c80476e4SDavid E. O'Brien (csh-indent-line)) 548c80476e4SDavid E. O'Brien (forward-line 1) 549c80476e4SDavid E. O'Brien (setq start (point))) 550c80476e4SDavid E. O'Brien 551c80476e4SDavid E. O'Brien (set-marker endmark nil) 552c80476e4SDavid E. O'Brien ) 553c80476e4SDavid E. O'Brien ) 554c80476e4SDavid E. O'Brien ) 555c80476e4SDavid E. O'Brien 556c80476e4SDavid E. O'Brien(defun csh-line-to-string () 557c80476e4SDavid E. O'Brien "From point, construct a string from all characters on 558c80476e4SDavid E. O'Briencurrent line" 559c80476e4SDavid E. O'Brien (skip-chars-forward " \t") ;; skip tabs as well as spaces 560c80476e4SDavid E. O'Brien (buffer-substring (point) 561c80476e4SDavid E. O'Brien (progn 562c80476e4SDavid E. O'Brien (end-of-line 1) 563c80476e4SDavid E. O'Brien (point)))) 564c80476e4SDavid E. O'Brien 565c80476e4SDavid E. O'Brien(defun csh-looking-at-label () 566c80476e4SDavid E. O'Brien "Return true if current line is a label (not the default: case label)." 567c80476e4SDavid E. O'Brien (and 568c80476e4SDavid E. O'Brien (looking-at csh-label-re) 569c80476e4SDavid E. O'Brien (not (looking-at "^\\s *default:")))) 570c80476e4SDavid E. O'Brien 571c80476e4SDavid E. O'Brien(defun csh-match-indent-level (begin-re end-re) 572c80476e4SDavid E. O'Brien "Match the compound command and indent. Return nil on no match, 573c80476e4SDavid E. O'Brienindentation to use for this line otherwise." 574c80476e4SDavid E. O'Brien (interactive) 575c80476e4SDavid E. O'Brien (let* ((case-fold-search) 576c80476e4SDavid E. O'Brien (nest-list 577c80476e4SDavid E. O'Brien (save-excursion 578c80476e4SDavid E. O'Brien (csh-get-compound-level begin-re end-re (point)) 579c80476e4SDavid E. O'Brien )) 580c80476e4SDavid E. O'Brien ) ;; bindings 581c80476e4SDavid E. O'Brien (if (null nest-list) 582c80476e4SDavid E. O'Brien (progn 583c80476e4SDavid E. O'Brien (if csh-match-and-tell 584c80476e4SDavid E. O'Brien (message "No matching compound command")) 585c80476e4SDavid E. O'Brien nil) ;; Propagate a miss. 586c80476e4SDavid E. O'Brien (let* ( 587c80476e4SDavid E. O'Brien (nest-level (car nest-list)) 588c80476e4SDavid E. O'Brien (match-line (cdr nest-list)) 589c80476e4SDavid E. O'Brien ) ;; bindings 590c80476e4SDavid E. O'Brien (if csh-match-and-tell 591c80476e4SDavid E. O'Brien (save-excursion 592c80476e4SDavid E. O'Brien (goto-line match-line) 593c80476e4SDavid E. O'Brien (message "Matched ... %s" (csh-line-to-string)) 594c80476e4SDavid E. O'Brien ) ;; excursion 595c80476e4SDavid E. O'Brien ) ;; if csh-match-and-tell 596c80476e4SDavid E. O'Brien nest-level ;;Propagate a hit. 597c80476e4SDavid E. O'Brien ) ;; let* 598c80476e4SDavid E. O'Brien ) ;; if 599c80476e4SDavid E. O'Brien ) ;; let* 600c80476e4SDavid E. O'Brien ) ;; defun csh-match-indent-level 601c80476e4SDavid E. O'Brien 602c80476e4SDavid E. O'Brien(defun csh-match-structure-and-reindent () 603c80476e4SDavid E. O'Brien "If the current line matches one of the indenting keywords 604c80476e4SDavid E. O'Brienor one of the control structure ending keywords then reindent. Also 605c80476e4SDavid E. O'Brienif csh-match-and-tell is non-nil the matching structure will echo in 606c80476e4SDavid E. O'Brienthe minibuffer" 607c80476e4SDavid E. O'Brien (interactive) 608c80476e4SDavid E. O'Brien (let (case-fold-search) 609c80476e4SDavid E. O'Brien (save-excursion 610c80476e4SDavid E. O'Brien (beginning-of-line) 611c80476e4SDavid E. O'Brien (cond ((looking-at csh-else-re) 612c80476e4SDavid E. O'Brien (csh-match-indent-level csh-if-re csh-endif-re)) 613c80476e4SDavid E. O'Brien ((looking-at csh-else-if-re) 614c80476e4SDavid E. O'Brien (csh-match-indent-level csh-if-re csh-endif-re)) 615c80476e4SDavid E. O'Brien ((looking-at csh-endif-re) 616c80476e4SDavid E. O'Brien (csh-match-indent-level csh-if-re csh-endif-re)) 617c80476e4SDavid E. O'Brien ((looking-at csh-end-re) 618c80476e4SDavid E. O'Brien (csh-match-indent-level csh-iteration-keywords-re csh-end-re)) 619c80476e4SDavid E. O'Brien ((looking-at csh-endsw-re) 620c80476e4SDavid E. O'Brien (csh-match-indent-level csh-switch-re csh-endsw-re)) 621c80476e4SDavid E. O'Brien ((csh-looking-at-label) 622c80476e4SDavid E. O'Brien ;; Flush control-flow labels left since they don't nest. 623c80476e4SDavid E. O'Brien 0) 624c80476e4SDavid E. O'Brien ;; 625c80476e4SDavid E. O'Brien (t nil) 626c80476e4SDavid E. O'Brien );; cond 627c80476e4SDavid E. O'Brien ) 628c80476e4SDavid E. O'Brien )) 629c80476e4SDavid E. O'Brien 630c80476e4SDavid E. O'Brien;;;###autoload 631c80476e4SDavid E. O'Brien(defun csh-mode () 632c80476e4SDavid E. O'Brien "csh-mode 2.0 - Major mode for editing csh and tcsh scripts. 633c80476e4SDavid E. O'BrienSpecial key bindings and commands: 634c80476e4SDavid E. O'Brien\\{csh-mode-map} 635c80476e4SDavid E. O'BrienVariables controlling indentation style: 636c80476e4SDavid E. O'Briencsh-indent 637c80476e4SDavid E. O'Brien Indentation of csh statements with respect to containing block. 638c80476e4SDavid E. O'Brien Default value is 4. 639c80476e4SDavid E. O'Briencsh-case-indent 640c80476e4SDavid E. O'Brien Additional indentation for statements under case items. 641c80476e4SDavid E. O'Brien Default value is nil which will align the statements one position 642c80476e4SDavid E. O'Brien past the \")\" of the pattern. 643c80476e4SDavid E. O'Briencsh-case-item-offset 644c80476e4SDavid E. O'Brien Additional indentation for case items within a case statement. 645c80476e4SDavid E. O'Brien Default value is 2. 646c80476e4SDavid E. O'Briencsh-tab-always-indent 647c80476e4SDavid E. O'Brien Controls the operation of the TAB key. If t (the default), always 648c80476e4SDavid E. O'Brien reindent the current line. If nil, indent the current line only if 649c80476e4SDavid E. O'Brien point is at the left margin or in the line's indentation; otherwise 650c80476e4SDavid E. O'Brien insert a tab. 651c80476e4SDavid E. O'Briencsh-match-and-tell 652c80476e4SDavid E. O'Brien If non-nil echo in the minibuffer the matching compound command 653c80476e4SDavid E. O'Brien for the \"done\", \"}\", \"fi\", or \"endsw\". Default value is t. 654c80476e4SDavid E. O'Brien 655c80476e4SDavid E. O'Briencsh-comment-regexp 656c80476e4SDavid E. O'Brien Regular expression used to recognize comments. Customize to support 657c80476e4SDavid E. O'Brien csh-like languages. Default value is \"\^\\\\s *#\". 658c80476e4SDavid E. O'Brien 659c80476e4SDavid E. O'BrienStyle Guide. 660c80476e4SDavid E. O'Brien By setting 661c80476e4SDavid E. O'Brien (setq csh-indent default-tab-width) 662c80476e4SDavid E. O'Brien 663c80476e4SDavid E. O'Brien The following style is obtained: 664c80476e4SDavid E. O'Brien 665c80476e4SDavid E. O'Brien if [ -z $foo ] 666c80476e4SDavid E. O'Brien then 667c80476e4SDavid E. O'Brien bar # <-- csh-group-offset is additive to csh-indent 668c80476e4SDavid E. O'Brien foo 669c80476e4SDavid E. O'Brien fi 670c80476e4SDavid E. O'Brien 671c80476e4SDavid E. O'Brien By setting 672c80476e4SDavid E. O'Brien (setq csh-indent default-tab-width) 673c80476e4SDavid E. O'Brien (setq csh-group-offset (- 0 csh-indent)) 674c80476e4SDavid E. O'Brien 675c80476e4SDavid E. O'Brien The following style is obtained: 676c80476e4SDavid E. O'Brien 677c80476e4SDavid E. O'Brien if [ -z $foo ] 678c80476e4SDavid E. O'Brien then 679c80476e4SDavid E. O'Brien bar 680c80476e4SDavid E. O'Brien foo 681c80476e4SDavid E. O'Brien fi 682c80476e4SDavid E. O'Brien 683c80476e4SDavid E. O'Brien By setting 684c80476e4SDavid E. O'Brien (setq csh-case-item-offset 1) 685c80476e4SDavid E. O'Brien (setq csh-case-indent nil) 686c80476e4SDavid E. O'Brien 687c80476e4SDavid E. O'Brien The following style is obtained: 688c80476e4SDavid E. O'Brien 689c80476e4SDavid E. O'Brien case x in * 690c80476e4SDavid E. O'Brien foo) bar # <-- csh-case-item-offset 691c80476e4SDavid E. O'Brien baz;; # <-- csh-case-indent aligns with \")\" 692c80476e4SDavid E. O'Brien foobar) foo 693c80476e4SDavid E. O'Brien bar;; 694c80476e4SDavid E. O'Brien endsw 695c80476e4SDavid E. O'Brien 696c80476e4SDavid E. O'Brien By setting 697c80476e4SDavid E. O'Brien (setq csh-case-item-offset 1) 698c80476e4SDavid E. O'Brien (setq csh-case-indent 6) 699c80476e4SDavid E. O'Brien 700c80476e4SDavid E. O'Brien The following style is obtained: 701c80476e4SDavid E. O'Brien 702c80476e4SDavid E. O'Brien case x in * 703c80476e4SDavid E. O'Brien foo) bar # <-- csh-case-item-offset 704c80476e4SDavid E. O'Brien baz;; # <-- csh-case-indent 705c80476e4SDavid E. O'Brien foobar) foo 706c80476e4SDavid E. O'Brien bar;; 707c80476e4SDavid E. O'Brien endsw 708c80476e4SDavid E. O'Brien 709c80476e4SDavid E. O'Brien 710c80476e4SDavid E. O'BrienInstallation: 711c80476e4SDavid E. O'Brien Put csh-mode.el in some directory in your load-path. 712c80476e4SDavid E. O'Brien Put the following forms in your .emacs file. 713c80476e4SDavid E. O'Brien 714c80476e4SDavid E. O'Brien (setq auto-mode-alist 715c80476e4SDavid E. O'Brien (append auto-mode-alist 716c80476e4SDavid E. O'Brien (list 717c80476e4SDavid E. O'Brien '(\"\\\\.csh$\" . csh-mode) 718c80476e4SDavid E. O'Brien '(\"\\\\.login\" . csh-mode)))) 719c80476e4SDavid E. O'Brien 720c80476e4SDavid E. O'Brien (setq csh-mode-hook 721c80476e4SDavid E. O'Brien (function (lambda () 722c80476e4SDavid E. O'Brien (font-lock-mode 1) ;; font-lock the buffer 723c80476e4SDavid E. O'Brien (setq csh-indent 8) 724c80476e4SDavid E. O'Brien (setq csh-tab-always-indent t) 725c80476e4SDavid E. O'Brien (setq csh-match-and-tell t) 726c80476e4SDavid E. O'Brien (setq csh-align-to-keyword t) ;; Turn on keyword alignment 727c80476e4SDavid E. O'Brien )))" 728c80476e4SDavid E. O'Brien (interactive) 729c80476e4SDavid E. O'Brien (kill-all-local-variables) 730c80476e4SDavid E. O'Brien (use-local-map csh-mode-map) 731c80476e4SDavid E. O'Brien (setq major-mode 'csh-mode) 732c80476e4SDavid E. O'Brien (setq mode-name "Csh") 733c80476e4SDavid E. O'Brien (setq local-abbrev-table csh-mode-abbrev-table) 734c80476e4SDavid E. O'Brien (set-syntax-table csh-mode-syntax-table) 735c80476e4SDavid E. O'Brien (make-local-variable 'indent-line-function) 736c80476e4SDavid E. O'Brien (setq indent-line-function 'csh-indent-line) 737c80476e4SDavid E. O'Brien (make-local-variable 'indent-region-function) 738c80476e4SDavid E. O'Brien (setq indent-region-function 'csh-indent-region) 739c80476e4SDavid E. O'Brien (make-local-variable 'comment-start) 740c80476e4SDavid E. O'Brien (setq comment-start "# ") 741c80476e4SDavid E. O'Brien (make-local-variable 'comment-end) 742c80476e4SDavid E. O'Brien (setq comment-end "") 743c80476e4SDavid E. O'Brien (make-local-variable 'comment-column) 744c80476e4SDavid E. O'Brien (setq comment-column 32) 745c80476e4SDavid E. O'Brien (make-local-variable 'comment-start-skip) 746c80476e4SDavid E. O'Brien (setq comment-start-skip "#+ *") 747c80476e4SDavid E. O'Brien ;; 748c80476e4SDavid E. O'Brien ;; config font-lock mode 749c80476e4SDavid E. O'Brien (make-local-variable 'font-lock-keywords) 750c80476e4SDavid E. O'Brien (setq font-lock-keywords csh-font-lock-keywords) 751c80476e4SDavid E. O'Brien ;; 752c80476e4SDavid E. O'Brien ;; Let the user customize 753c80476e4SDavid E. O'Brien (run-hooks 'csh-mode-hook) 754c80476e4SDavid E. O'Brien ) ;; defun 755c80476e4SDavid E. O'Brien 756c80476e4SDavid E. O'Brien;; 757c80476e4SDavid E. O'Brien;; Completion code supplied by Haavard Rue <hrue@imf.unit.no>. 758c80476e4SDavid E. O'Brien;; 759c80476e4SDavid E. O'Brien;; 760c80476e4SDavid E. O'Brien;; add a completion with a given type to the list 761c80476e4SDavid E. O'Brien;; 762c80476e4SDavid E. O'Brien(defun csh-addto-alist (completion type) 763c80476e4SDavid E. O'Brien (setq csh-completion-list 764c80476e4SDavid E. O'Brien (append csh-completion-list 765c80476e4SDavid E. O'Brien (list (cons completion type))))) 766c80476e4SDavid E. O'Brien 767c80476e4SDavid E. O'Brien(defun csh-bol-point () 768c80476e4SDavid E. O'Brien (save-excursion 769c80476e4SDavid E. O'Brien (beginning-of-line) 770c80476e4SDavid E. O'Brien (point))) 771c80476e4SDavid E. O'Brien 772c80476e4SDavid E. O'Brien(defun csh-complete-symbol () 773c80476e4SDavid E. O'Brien "Perform completion." 774c80476e4SDavid E. O'Brien (interactive) 775c80476e4SDavid E. O'Brien (let* ((case-fold-search) 776c80476e4SDavid E. O'Brien (end (point)) 777c80476e4SDavid E. O'Brien (beg (unwind-protect 778c80476e4SDavid E. O'Brien (save-excursion 779c80476e4SDavid E. O'Brien (backward-sexp 1) 780c80476e4SDavid E. O'Brien (while (= (char-syntax (following-char)) ?\') 781c80476e4SDavid E. O'Brien (forward-char 1)) 782c80476e4SDavid E. O'Brien (point)))) 783c80476e4SDavid E. O'Brien (pattern (buffer-substring beg end)) 784c80476e4SDavid E. O'Brien (predicate 785c80476e4SDavid E. O'Brien ;; 786c80476e4SDavid E. O'Brien ;; ` or $( mark a function 787c80476e4SDavid E. O'Brien ;; 788c80476e4SDavid E. O'Brien (save-excursion 789c80476e4SDavid E. O'Brien (goto-char beg) 790c80476e4SDavid E. O'Brien (if (or 791c80476e4SDavid E. O'Brien (save-excursion 792c80476e4SDavid E. O'Brien (backward-char 1) 793c80476e4SDavid E. O'Brien (looking-at "`")) 794c80476e4SDavid E. O'Brien (save-excursion 795c80476e4SDavid E. O'Brien (backward-char 2) 796c80476e4SDavid E. O'Brien (looking-at "\\$("))) 797c80476e4SDavid E. O'Brien (function (lambda (sym) 798c80476e4SDavid E. O'Brien (equal (cdr sym) csh-completion-type-function))) 799c80476e4SDavid E. O'Brien ;; 800c80476e4SDavid E. O'Brien ;; a $, ${ or ${# mark a variable 801c80476e4SDavid E. O'Brien ;; 802c80476e4SDavid E. O'Brien (if (or 803c80476e4SDavid E. O'Brien (save-excursion 804c80476e4SDavid E. O'Brien (backward-char 1) 805c80476e4SDavid E. O'Brien (looking-at "\\$")) 806c80476e4SDavid E. O'Brien (save-excursion 807c80476e4SDavid E. O'Brien (backward-char 2) 808c80476e4SDavid E. O'Brien (looking-at "\\${")) 809c80476e4SDavid E. O'Brien (save-excursion 810c80476e4SDavid E. O'Brien (backward-char 3) 811c80476e4SDavid E. O'Brien (looking-at "\\${#"))) 812c80476e4SDavid E. O'Brien (function (lambda (sym) 813c80476e4SDavid E. O'Brien (equal (cdr sym) 814c80476e4SDavid E. O'Brien csh-completion-type-var))) 815c80476e4SDavid E. O'Brien ;; 816c80476e4SDavid E. O'Brien ;; don't know. use 'em all 817c80476e4SDavid E. O'Brien ;; 818c80476e4SDavid E. O'Brien (function (lambda (sym) t)))))) 819c80476e4SDavid E. O'Brien ;; 820c80476e4SDavid E. O'Brien (completion (try-completion pattern csh-completion-list predicate))) 821c80476e4SDavid E. O'Brien ;; 822c80476e4SDavid E. O'Brien (cond ((eq completion t)) 823c80476e4SDavid E. O'Brien ;; 824c80476e4SDavid E. O'Brien ;; oops, what is this ? 825c80476e4SDavid E. O'Brien ;; 826c80476e4SDavid E. O'Brien ((null completion) 827c80476e4SDavid E. O'Brien (message "Can't find completion for \"%s\"" pattern)) 828c80476e4SDavid E. O'Brien ;; 829c80476e4SDavid E. O'Brien ;; insert 830c80476e4SDavid E. O'Brien ;; 831c80476e4SDavid E. O'Brien ((not (string= pattern completion)) 832c80476e4SDavid E. O'Brien (delete-region beg end) 833c80476e4SDavid E. O'Brien (insert completion)) 834c80476e4SDavid E. O'Brien ;; 835c80476e4SDavid E. O'Brien ;; write possible completion in the minibuffer, 836c80476e4SDavid E. O'Brien ;; use this instead of a seperate buffer (usual) 837c80476e4SDavid E. O'Brien ;; 838c80476e4SDavid E. O'Brien (t 839c80476e4SDavid E. O'Brien (let ((list (all-completions pattern csh-completion-list predicate)) 840c80476e4SDavid E. O'Brien (string "")) 841c80476e4SDavid E. O'Brien (while list 842c80476e4SDavid E. O'Brien (progn 843c80476e4SDavid E. O'Brien (setq string (concat string (format "%s " (car list)))) 844c80476e4SDavid E. O'Brien (setq list (cdr list)))) 845c80476e4SDavid E. O'Brien (message string)))))) 846c80476e4SDavid E. O'Brien 847c80476e4SDavid E. O'Brien;; 848c80476e4SDavid E. O'Brien;; init the list and pickup all 849c80476e4SDavid E. O'Brien;; 850c80476e4SDavid E. O'Brien(defun csh-completion-init-and-pickup () 851c80476e4SDavid E. O'Brien (interactive) 852c80476e4SDavid E. O'Brien (let (case-fold-search) 853c80476e4SDavid E. O'Brien (csh-completion-list-init) 854c80476e4SDavid E. O'Brien (csh-pickup-all))) 855c80476e4SDavid E. O'Brien 856c80476e4SDavid E. O'Brien;; 857c80476e4SDavid E. O'Brien;; init the list 858c80476e4SDavid E. O'Brien;; 859c80476e4SDavid E. O'Brien(defun csh-completion-list-init () 860c80476e4SDavid E. O'Brien (interactive) 861c80476e4SDavid E. O'Brien (setq csh-completion-list 862c80476e4SDavid E. O'Brien (list 863c80476e4SDavid E. O'Brien (cons "break" csh-completion-type-misc) 864c80476e4SDavid E. O'Brien (cons "breaksw" csh-completion-type-misc) 865c80476e4SDavid E. O'Brien (cons "case" csh-completion-type-misc) 866c80476e4SDavid E. O'Brien (cons "continue" csh-completion-type-misc) 867c80476e4SDavid E. O'Brien (cons "endif" csh-completion-type-misc) 868c80476e4SDavid E. O'Brien (cons "exit" csh-completion-type-misc) 869c80476e4SDavid E. O'Brien (cons "foreach" csh-completion-type-misc) 870c80476e4SDavid E. O'Brien (cons "if" csh-completion-type-misc) 871c80476e4SDavid E. O'Brien (cons "while" csh-completion-type-misc)))) 872c80476e4SDavid E. O'Brien 873c80476e4SDavid E. O'Brien(defun csh-eol-point () 874c80476e4SDavid E. O'Brien (save-excursion 875c80476e4SDavid E. O'Brien (end-of-line) 876c80476e4SDavid E. O'Brien (point))) 877c80476e4SDavid E. O'Brien 878c80476e4SDavid E. O'Brien(defun csh-pickup-all () 879c80476e4SDavid E. O'Brien "Pickup all completions in buffer." 880c80476e4SDavid E. O'Brien (interactive) 881c80476e4SDavid E. O'Brien (csh-pickup-completion-driver (point-min) (point-max) t)) 882c80476e4SDavid E. O'Brien 883c80476e4SDavid E. O'Brien(defun csh-pickup-completion (regexp type match pmin pmax) 884c80476e4SDavid E. O'Brien "Pickup completion in region and addit to the list, if not already 885c80476e4SDavid E. O'Brienthere." 886c80476e4SDavid E. O'Brien (let ((i 0) kw obj) 887c80476e4SDavid E. O'Brien (save-excursion 888c80476e4SDavid E. O'Brien (goto-char pmin) 889c80476e4SDavid E. O'Brien (while (and 890c80476e4SDavid E. O'Brien (re-search-forward regexp pmax t) 891c80476e4SDavid E. O'Brien (match-beginning match) 892c80476e4SDavid E. O'Brien (setq kw (buffer-substring 893c80476e4SDavid E. O'Brien (match-beginning match) 894c80476e4SDavid E. O'Brien (match-end match)))) 895c80476e4SDavid E. O'Brien (progn 896c80476e4SDavid E. O'Brien (setq obj (assoc kw csh-completion-list)) 897c80476e4SDavid E. O'Brien (if (or (equal nil obj) 898c80476e4SDavid E. O'Brien (and (not (equal nil obj)) 899c80476e4SDavid E. O'Brien (not (= type (cdr obj))))) 900c80476e4SDavid E. O'Brien (progn 901c80476e4SDavid E. O'Brien (setq i (1+ i)) 902c80476e4SDavid E. O'Brien (csh-addto-alist kw type)))))) 903c80476e4SDavid E. O'Brien i)) 904c80476e4SDavid E. O'Brien 905c80476e4SDavid E. O'Brien(defun csh-pickup-completion-driver (pmin pmax message) 906c80476e4SDavid E. O'Brien "Driver routine for csh-pickup-completion." 907c80476e4SDavid E. O'Brien (if message 908c80476e4SDavid E. O'Brien (message "pickup completion...")) 909c80476e4SDavid E. O'Brien (let* ( 910c80476e4SDavid E. O'Brien (i1 911c80476e4SDavid E. O'Brien (csh-pickup-completion csh-completion-regexp-var 912c80476e4SDavid E. O'Brien csh-completion-type-var 913c80476e4SDavid E. O'Brien csh-completion-match-var 914c80476e4SDavid E. O'Brien pmin pmax)) 915c80476e4SDavid E. O'Brien (i2 916c80476e4SDavid E. O'Brien (csh-pickup-completion csh-completion-regexp-var2 917c80476e4SDavid E. O'Brien csh-completion-type-var 918c80476e4SDavid E. O'Brien csh-completion-match-var2 919c80476e4SDavid E. O'Brien pmin pmax)) 920c80476e4SDavid E. O'Brien (i3 921c80476e4SDavid E. O'Brien (csh-pickup-completion csh-completion-regexp-function 922c80476e4SDavid E. O'Brien csh-completion-type-function 923c80476e4SDavid E. O'Brien csh-completion-match-function 924c80476e4SDavid E. O'Brien pmin pmax))) 925c80476e4SDavid E. O'Brien (if message 926c80476e4SDavid E. O'Brien (message "pickup %d variables and %d functions." (+ i1 i2) i3)))) 927c80476e4SDavid E. O'Brien 928c80476e4SDavid E. O'Brien(defun csh-pickup-this-line () 929c80476e4SDavid E. O'Brien "Pickup all completions in current line." 930c80476e4SDavid E. O'Brien (interactive) 931c80476e4SDavid E. O'Brien (csh-pickup-completion-driver (csh-bol-point) (csh-eol-point) nil)) 932c80476e4SDavid E. O'Brien 933c80476e4SDavid E. O'Brien 934c80476e4SDavid E. O'Brien(provide 'csh-mode) 935c80476e4SDavid E. O'Brien;;; csh-mode.el ends here 936