43 |
;; =========== |
;; =========== |
44 |
;; Indentation for rc and es modes is very limited, but for Bourne shells |
;; Indentation for rc and es modes is very limited, but for Bourne shells |
45 |
;; and its derivatives it is quite customizable. |
;; and its derivatives it is quite customizable. |
46 |
;; |
;; |
47 |
;; The following description applies to sh and derived shells (bash, |
;; The following description applies to sh and derived shells (bash, |
48 |
;; zsh, ...). |
;; zsh, ...). |
49 |
;; |
;; |
50 |
;; There are various customization variables which allow tailoring to |
;; There are various customization variables which allow tailoring to |
51 |
;; a wide variety of styles. Most of these variables are named |
;; a wide variety of styles. Most of these variables are named |
52 |
;; sh-indent-for-XXX and sh-indent-after-XXX. For example. |
;; sh-indent-for-XXX and sh-indent-after-XXX. For example. |
53 |
;; sh-indent-after-if controls the indenting of a line following |
;; sh-indent-after-if controls the indenting of a line following |
54 |
;; an if statement, and sh-indent-for-fi controls the indentation |
;; an if statement, and sh-indent-for-fi controls the indentation |
55 |
;; of the line containing the fi. |
;; of the line containing the fi. |
56 |
;; |
;; |
57 |
;; You can set each to a numeric value, but it is often more convenient |
;; You can set each to a numeric value, but it is often more convenient |
58 |
;; to a symbol such as `+' which uses the value of variable `sh-basic-offset'. |
;; to a symbol such as `+' which uses the value of variable `sh-basic-offset'. |
59 |
;; By changing this one variable you can increase or decrease how much |
;; By changing this one variable you can increase or decrease how much |
60 |
;; indentation there is. Valid symbols: |
;; indentation there is. Valid symbols: |
61 |
;; |
;; |
62 |
;; + Indent right by sh-basic-offset |
;; + Indent right by sh-basic-offset |
63 |
;; - Indent left by sh-basic-offset |
;; - Indent left by sh-basic-offset |
64 |
;; ++ Indent right twice sh-basic-offset |
;; ++ Indent right twice sh-basic-offset |
65 |
;; -- Indent left twice sh-basic-offset |
;; -- Indent left twice sh-basic-offset |
66 |
;; * Indent right half sh-basic-offset |
;; * Indent right half sh-basic-offset |
67 |
;; / Indent left half sh-basic-offset. |
;; / Indent left half sh-basic-offset. |
68 |
;; |
;; |
69 |
;; There are 4 commands to help set the indentation variables: |
;; There are 4 commands to help set the indentation variables: |
70 |
;; |
;; |
71 |
;; `sh-show-indent' |
;; `sh-show-indent' |
72 |
;; This shows what variable controls the indentation of the current |
;; This shows what variable controls the indentation of the current |
73 |
;; line and its value. |
;; line and its value. |
74 |
;; |
;; |
75 |
;; `sh-set-indent' |
;; `sh-set-indent' |
76 |
;; This allows you to set the value of the variable controlling the |
;; This allows you to set the value of the variable controlling the |
77 |
;; current line's indentation. You can enter a number or one of a |
;; current line's indentation. You can enter a number or one of a |
79 |
;; or its negative, or half it, or twice it, etc. If you've used |
;; or its negative, or half it, or twice it, etc. If you've used |
80 |
;; cc-mode this should be familiar. If you forget which symbols are |
;; cc-mode this should be familiar. If you forget which symbols are |
81 |
;; valid simply press C-h at the prompt. |
;; valid simply press C-h at the prompt. |
82 |
;; |
;; |
83 |
;; `sh-learn-line-indent' |
;; `sh-learn-line-indent' |
84 |
;; Simply make the line look the way you want it, then invoke this |
;; Simply make the line look the way you want it, then invoke this |
85 |
;; command. It will set the variable to the value that makes the line |
;; command. It will set the variable to the value that makes the line |
86 |
;; indent like that. If called with a prefix argument then it will set |
;; indent like that. If called with a prefix argument then it will set |
87 |
;; the value to one of the symbols if applicable. |
;; the value to one of the symbols if applicable. |
88 |
;; |
;; |
89 |
;; `sh-learn-buffer-indent' |
;; `sh-learn-buffer-indent' |
90 |
;; This is the deluxe function! It "learns" the whole buffer (use |
;; This is the deluxe function! It "learns" the whole buffer (use |
91 |
;; narrowing if you want it to process only part). It outputs to a |
;; narrowing if you want it to process only part). It outputs to a |
98 |
;; pattern; if they don't it will be set to nil. |
;; pattern; if they don't it will be set to nil. |
99 |
;; Whether `sh-basic-offset' is set is determined by variable |
;; Whether `sh-basic-offset' is set is determined by variable |
100 |
;; `sh-learn-basic-offset'. |
;; `sh-learn-basic-offset'. |
101 |
;; |
;; |
102 |
;; Unfortunately, `sh-learn-buffer-indent' can take a long time to run |
;; Unfortunately, `sh-learn-buffer-indent' can take a long time to run |
103 |
;; (e.g. if there are large case statements). Perhaps it does not make |
;; (e.g. if there are large case statements). Perhaps it does not make |
104 |
;; sense to run it on large buffers: if lots of lines have different |
;; sense to run it on large buffers: if lots of lines have different |
106 |
;; *indent* buffer; if there is a consistent style then running |
;; *indent* buffer; if there is a consistent style then running |
107 |
;; `sh-learn-buffer-indent' on a small region of the buffer should |
;; `sh-learn-buffer-indent' on a small region of the buffer should |
108 |
;; suffice. |
;; suffice. |
109 |
;; |
;; |
110 |
;; Saving indentation values |
;; Saving indentation values |
111 |
;; ------------------------- |
;; ------------------------- |
112 |
;; After you've learned the values in a buffer, how to you remember |
;; After you've learned the values in a buffer, how to you remember |
115 |
;; the buffer. |
;; the buffer. |
116 |
;; You can do this automatically like this: |
;; You can do this automatically like this: |
117 |
;; (add-hook 'sh-set-shell-hook 'sh-learn-buffer-indent) |
;; (add-hook 'sh-set-shell-hook 'sh-learn-buffer-indent) |
118 |
;; |
;; |
119 |
;; However... `sh-learn-buffer-indent' is extremely slow, |
;; However... `sh-learn-buffer-indent' is extremely slow, |
120 |
;; especially on large-ish buffer. Also, if there are conflicts the |
;; especially on large-ish buffer. Also, if there are conflicts the |
121 |
;; "last one wins" which may not produce the desired setting. |
;; "last one wins" which may not produce the desired setting. |
122 |
;; |
;; |
123 |
;; So...There is a minimal way of being able to save indentation values and |
;; So...There is a minimal way of being able to save indentation values and |
124 |
;; to reload them in another buffer or at another point in time. |
;; to reload them in another buffer or at another point in time. |
125 |
;; |
;; |
126 |
;; Use `sh-name-style' to give a name to the indentation settings of |
;; Use `sh-name-style' to give a name to the indentation settings of |
127 |
;; the current buffer. |
;; the current buffer. |
128 |
;; Use `sh-load-style' to load indentation settings for the current |
;; Use `sh-load-style' to load indentation settings for the current |
130 |
;; Use `sh-save-styles-to-buffer' to write all the styles to a buffer |
;; Use `sh-save-styles-to-buffer' to write all the styles to a buffer |
131 |
;; in lisp code. You can then store it in a file and later use |
;; in lisp code. You can then store it in a file and later use |
132 |
;; `load-file' to load it. |
;; `load-file' to load it. |
133 |
;; |
;; |
134 |
;; Indentation variables - buffer local or global? |
;; Indentation variables - buffer local or global? |
135 |
;; ---------------------------------------------- |
;; ---------------------------------------------- |
136 |
;; I think that often having them buffer-local makes sense, |
;; I think that often having them buffer-local makes sense, |
137 |
;; especially if one is using `sh-learn-buffer-indent'. However, if |
;; especially if one is using `sh-learn-buffer-indent'. However, if |
138 |
;; a user sets values using customization, these changes won't appear |
;; a user sets values using customization, these changes won't appear |
139 |
;; to work if the variables are already local! |
;; to work if the variables are already local! |
140 |
;; |
;; |
141 |
;; To get round this, there is a variable `sh-make-vars-local' and 2 |
;; To get round this, there is a variable `sh-make-vars-local' and 2 |
142 |
;; functions: `sh-make-vars-local' and `sh-reset-indent-vars-to-global-values'. |
;; functions: `sh-make-vars-local' and `sh-reset-indent-vars-to-global-values'. |
143 |
;; |
;; |
144 |
;; If `sh-make-vars-local' is non-nil, then these variables become |
;; If `sh-make-vars-local' is non-nil, then these variables become |
145 |
;; buffer local when the mode is established. |
;; buffer local when the mode is established. |
146 |
;; If this is nil, then the variables are global. At any time you |
;; If this is nil, then the variables are global. At any time you |
147 |
;; can make them local with the command `sh-make-vars-local'. |
;; can make them local with the command `sh-make-vars-local'. |
148 |
;; Conversely, to update with the global values you can use the |
;; Conversely, to update with the global values you can use the |
149 |
;; command `sh-reset-indent-vars-to-global-values'. |
;; command `sh-reset-indent-vars-to-global-values'. |
150 |
;; |
;; |
151 |
;; This may be awkward, but the intent is to cover all cases. |
;; This may be awkward, but the intent is to cover all cases. |
152 |
;; |
;; |
153 |
;; Awkward things, pitfalls |
;; Awkward things, pitfalls |
154 |
;; ------------------------ |
;; ------------------------ |
155 |
;; Indentation for a sh script is complicated for a number of reasons: |
;; Indentation for a sh script is complicated for a number of reasons: |
156 |
;; |
;; |
157 |
;; 1. You can't format by simply looking at symbols, you need to look |
;; 1. You can't format by simply looking at symbols, you need to look |
158 |
;; at keywords. [This is not the case for rc and es shells.] |
;; at keywords. [This is not the case for rc and es shells.] |
159 |
;; 2. The character ")" is used both as a matched pair "(" ... ")" and |
;; 2. The character ")" is used both as a matched pair "(" ... ")" and |
165 |
;; 4. A line may be continued using the "\". |
;; 4. A line may be continued using the "\". |
166 |
;; 5. The character "#" (outside a string) normally starts a comment, |
;; 5. The character "#" (outside a string) normally starts a comment, |
167 |
;; but it doesn't in the sequence "$#"! |
;; but it doesn't in the sequence "$#"! |
168 |
;; |
;; |
169 |
;; To try and address points 2 3 and 5 I used a feature that cperl mode |
;; To try and address points 2 3 and 5 I used a feature that cperl mode |
170 |
;; uses, that of a text's syntax property. This, however, has 2 |
;; uses, that of a text's syntax property. This, however, has 2 |
171 |
;; disadvantages: |
;; disadvantages: |
175 |
;; buffer is read-only buffer we have to cheat and bypass the read-only |
;; buffer is read-only buffer we have to cheat and bypass the read-only |
176 |
;; status. This is for cases where the buffer started read-only buffer |
;; status. This is for cases where the buffer started read-only buffer |
177 |
;; but the user issued `toggle-read-only'. |
;; but the user issued `toggle-read-only'. |
178 |
;; |
;; |
179 |
;; Bugs |
;; Bugs |
180 |
;; ---- |
;; ---- |
181 |
;; - Indenting many lines is slow. It currently does each line |
;; - Indenting many lines is slow. It currently does each line |
182 |
;; independently, rather than saving state information. |
;; independently, rather than saving state information. |
183 |
;; |
;; |
184 |
;; - `sh-learn-buffer-indent' is extremely slow. |
;; - `sh-learn-buffer-indent' is extremely slow. |
185 |
;; |
;; |
186 |
;; Richard Sharman <rsharman@pobox.com> June 1999. |
;; Richard Sharman <rsharman@pobox.com> June 1999. |
187 |
|
|
188 |
;;; Code: |
;;; Code: |
1032 |
:group 'sh-indentation) |
:group 'sh-indentation) |
1033 |
|
|
1034 |
(defcustom sh-indent-for-then '+ |
(defcustom sh-indent-for-then '+ |
1035 |
"*How much to indent an then relative to an if." |
"*How much to indent a then relative to an if." |
1036 |
:type `(choice ,@ sh-number-or-symbol-list ) |
:type `(choice ,@ sh-number-or-symbol-list ) |
1037 |
:group 'sh-indentation) |
:group 'sh-indentation) |
1038 |
|
|
1932 |
(setq have-result nil) |
(setq have-result nil) |
1933 |
)) |
)) |
1934 |
) ;; cond |
) ;; cond |
1935 |
|
|
1936 |
(unless have-result |
(unless have-result |
1937 |
;; Continuation lines are handled specially |
;; Continuation lines are handled specially |
1938 |
(if (sh-this-is-a-continuation) |
(if (sh-this-is-a-continuation) |
2025 |
(sh-debug "No prev line!") |
(sh-debug "No prev line!") |
2026 |
(sh-debug "result: %s align-point: %s" result align-point) |
(sh-debug "result: %s align-point: %s" result align-point) |
2027 |
) |
) |
2028 |
|
|
2029 |
(if align-point |
(if align-point |
2030 |
;; was: (setq result (append result (list (list t align-point)))) |
;; was: (setq result (append result (list (list t align-point)))) |
2031 |
(setq result (append (list (list t align-point)) result)) |
(setq result (append (list (list t align-point)) result)) |
2032 |
) |
) |
2033 |
(sh-debug "result is now: %s" result) |
(sh-debug "result is now: %s" result) |
2034 |
|
|
2035 |
(or result |
(or result |
2036 |
(if prev-line-end |
(if prev-line-end |
2037 |
(setq result (list (list t prev-line-end))) |
(setq result (list (list t prev-line-end))) |
2038 |
(setq result (list (list '= 'sh-first-lines-indent))) |
(setq result (list (list '= 'sh-first-lines-indent))) |
2039 |
)) |
)) |
2040 |
|
|
2041 |
(if (eq result t) |
(if (eq result t) |
2042 |
(setq result nil)) |
(setq result nil)) |
2043 |
(sh-debug "result is: %s" result) |
(sh-debug "result is: %s" result) |
2213 |
;; Possible return values: |
;; Possible return values: |
2214 |
;; nil - nothing |
;; nil - nothing |
2215 |
;; a string - possibly a keyword |
;; a string - possibly a keyword |
2216 |
;; |
;; |
2217 |
(if (bolp) |
(if (bolp) |
2218 |
nil |
nil |
2219 |
(let ((going t) |
(let ((going t) |
2587 |
((numberp (setq sval (sh-var-value var))) |
((numberp (setq sval (sh-var-value var))) |
2588 |
(setq ival (sh-calculate-indent info)) |
(setq ival (sh-calculate-indent info)) |
2589 |
(setq diff (- curr-indent ival)) |
(setq diff (- curr-indent ival)) |
2590 |
|
|
2591 |
(sh-debug "curr-indent: %d ival: %d diff: %d var:%s sval %s" |
(sh-debug "curr-indent: %d ival: %d diff: %d var:%s sval %s" |
2592 |
curr-indent ival diff var sval) |
curr-indent ival diff var sval) |
2593 |
(setq new-val (+ sval diff)) |
(setq new-val (+ sval diff)) |
2664 |
(defvar sh-learned-buffer-hook nil |
(defvar sh-learned-buffer-hook nil |
2665 |
"*An abnormal hook, called with an alist of learned variables.") |
"*An abnormal hook, called with an alist of learned variables.") |
2666 |
;;; Example of how to use sh-learned-buffer-hook |
;;; Example of how to use sh-learned-buffer-hook |
2667 |
;; |
;; |
2668 |
;; (defun what-i-learned (list) |
;; (defun what-i-learned (list) |
2669 |
;; (let ((p list)) |
;; (let ((p list)) |
2670 |
;; (save-excursion |
;; (save-excursion |
2677 |
;; (setq p (cdr p))) |
;; (setq p (cdr p))) |
2678 |
;; (insert ")\n") |
;; (insert ")\n") |
2679 |
;; ))) |
;; ))) |
2680 |
;; |
;; |
2681 |
;; (add-hook 'sh-learned-buffer-hook 'what-i-learned) |
;; (add-hook 'sh-learned-buffer-hook 'what-i-learned) |
2682 |
|
|
2683 |
|
|
2869 |
(format "Suggested sh-basic-offset: %d" suggested)) |
(format "Suggested sh-basic-offset: %d" suggested)) |
2870 |
nil out-buffer)))) |
nil out-buffer)))) |
2871 |
|
|
2872 |
|
|
2873 |
(setq learned-var-list |
(setq learned-var-list |
2874 |
(append (list (list 'sh-indent-comment comment-col (point-max))) |
(append (list (list 'sh-indent-comment comment-col (point-max))) |
2875 |
learned-var-list)) |
learned-var-list)) |