lisp-indenting.sl 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % Lisp-Indenting.SL - NMODE Lisp Indenting commands
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 25 August 1982
  8. % Revised: 12 November 1982
  9. %
  10. % 25-Feb-83 Alan Snyder
  11. % Move-down-list renamed to Move-forward-down-list.
  12. % 12-Nov-82 Alan Snyder
  13. % Improved indenting using new structure-movement primitives.
  14. % Changed multi-line indenting commands to clear any blank lines.
  15. % Added LISP-INDENT-REGION-COMMAND.
  16. %
  17. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  18. (CompileTime (load objects fast-int fast-vectors))
  19. (fluid '(nmode-command-argument nmode-command-argument-given))
  20. (de lisp-tab-command ()
  21. (cond (nmode-command-argument-given
  22. (let ((n nmode-command-argument))
  23. (cond ((< n 0)
  24. (let ((last-line (- (current-line-pos) 1)))
  25. (set-line-pos (+ (current-line-pos) n))
  26. (let ((first-line (current-line-pos)))
  27. (while (<= (current-line-pos) last-line)
  28. (lisp-indent-or-clear-current-line)
  29. (move-to-next-line)
  30. )
  31. (current-buffer-goto first-line 0)
  32. )))
  33. ((> n 0)
  34. (while (> n 0)
  35. (lisp-indent-or-clear-current-line)
  36. (move-to-next-line)
  37. (if (at-buffer-end?) (exit))
  38. (setf n (- n 1))
  39. ))
  40. (t
  41. (lisp-indent-current-line)
  42. (move-to-start-of-line)
  43. ))))
  44. (t (lisp-indent-current-line))))
  45. (de lisp-indent-current-line ()
  46. (indent-current-line (lisp-current-line-indent)))
  47. (de lisp-indent-or-clear-current-line ()
  48. (indent-current-line
  49. (if (current-line-blank?)
  50. 0
  51. (lisp-current-line-indent))))
  52. (de lisp-indent-sexpr ()
  53. (if (not (move-forward-down-list)) % Find next open bracket
  54. (Ding) % None found
  55. % otherwise
  56. (move-backward-item) % Move back to the open bracket
  57. (let ((old-line (current-line-pos))
  58. (old-point (current-char-pos))
  59. )
  60. (if (not (move-forward-form)) % Find end of form
  61. (Ding) % No matching close bracket found
  62. % otherwise
  63. (for (from i (+ old-line 1) (current-line-pos))
  64. (do
  65. (set-line-pos i)
  66. (lisp-indent-or-clear-current-line)
  67. ))
  68. (current-buffer-goto old-line old-point)
  69. ))))
  70. (de lisp-indent-region-command ()
  71. (if nmode-command-argument-given
  72. (indent-region #'indent-to-argument)
  73. (indent-region #'lisp-indent-or-clear-current-line)
  74. ))
  75. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  76. %
  77. % Basic Indenting Primitive
  78. %
  79. % This function determines what indentation the current line should receive.
  80. %
  81. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  82. (de lisp-current-line-indent ()
  83. % Return the desired indentation for the current line.
  84. % Point is unchanged.
  85. (let ((old-pos (buffer-get-position)))
  86. (unwind-protect
  87. (unsafe-lisp-current-line-indent)
  88. (buffer-set-position old-pos)
  89. )))
  90. (de unsafe-lisp-current-line-indent ()
  91. % Return the desired indentation for the current line.
  92. % Point may change.
  93. (move-to-start-of-line)
  94. (let ((item (move-backward-form))
  95. (number-of-forms 0)
  96. (leftmost-form-type NIL)
  97. )
  98. % If there are multiple forms at the same level of nesting
  99. % on the same line, we want to find the left-most one.
  100. (while (or (eq item 'ATOM) (eq item 'STRUCTURE))
  101. (setf number-of-forms (+ number-of-forms 1))
  102. (setf leftmost-form-type item)
  103. (let ((next-item (move-backward-form-within-line)))
  104. (if (not next-item) (exit)) % We have the first item on the line.
  105. (setf item next-item)
  106. ))
  107. (selectq item
  108. ((ATOM STRUCTURE) (current-display-column)) % Line up with form.
  109. (OPENER (lisp-indent-under-paren leftmost-form-type number-of-forms))
  110. (t 0) % There is no previous form.
  111. )))
  112. (de lisp-indent-under-paren (leftmost-form-type number-of-forms)
  113. % This function is called to determine the indentation for a line
  114. % that immediately follows (i.e., there is no intervening line
  115. % containing a form) the line containing the open paren that
  116. % begins the nesting level for the line being indented. This
  117. % function is called with the current position being at the open
  118. % paren. NUMBER-OF-FORMS specifies the number of forms that
  119. % follow the open paren on its line. LEFTMOST-FORM-TYPE specifies
  120. % the type of the first such form (either ATOM, STRUCTURE, or NIL).
  121. (skip-prefixes) % Skip over any "prefix characters" (like ' in Lisp).
  122. (let ((paren-column (current-display-column))
  123. the-atom pos1 pos2 atom-text atom-string second-column
  124. )
  125. (if (not (eq leftmost-form-type 'ATOM))
  126. (+ paren-column 1)
  127. % Otherwise
  128. (move-forward-item) % Move past the paren.
  129. (setf pos1 (buffer-get-position))
  130. (move-forward-form) % Move past the first form.
  131. (setf pos2 (buffer-get-position))
  132. (setf atom-text (extract-text NIL pos1 pos2))
  133. (setf atom-string (string-upcase (vector-fetch atom-text 0)))
  134. (if (internp atom-string) (setf the-atom (intern atom-string)))
  135. (when (> number-of-forms 1)
  136. (move-forward-form)
  137. (move-backward-form)
  138. (setf second-column (current-display-column))
  139. )
  140. (lisp-indent-under-atom
  141. the-atom paren-column second-column number-of-forms)
  142. )))
  143. (de lisp-indent-under-atom (the-id paren-column
  144. second-column number-of-forms)
  145. % This function is called to determine the indentation for a line
  146. % that immediately follows (i.e., there is no intervening line
  147. % containing a form) the line containing the open paren that
  148. % begins the nesting level for the line being indented.
  149. % The open paren is followed on the same line by at least one form
  150. % that is not a structure.
  151. % NUMBER-OF-FORMS specifies the number of forms that
  152. % follow the open paren on its line. If there are two or more forms,
  153. % then SECOND-COLUMN is the display column of the second form;
  154. % otherwise, SECOND-COLUMN is NIL. If the first
  155. % form is recognized as being an
  156. % interned ID, then THE-ID is that ID; otherwise, THE-ID is NIL.
  157. % PAREN-COLUMN is the display column of the open paren.
  158. (or
  159. (if the-id (id-specific-indent the-id paren-column second-column))
  160. second-column
  161. (+ paren-column 1)
  162. ))
  163. (put 'prog 'indentation 2)
  164. (put 'lambda 'indentation 2)
  165. (put 'lambdaq 'indentation 2)
  166. (put 'while 'indentation 2)
  167. (put 'de 'indentation 2)
  168. (put 'defun 'indentation 2)
  169. (put 'defmacro 'indentation 2)
  170. (put 'df 'indentation 2)
  171. (put 'dm 'indentation 2)
  172. (put 'dn 'indentation 2)
  173. (put 'ds 'indentation 2)
  174. (put 'let 'indentation 2)
  175. (put 'let* 'indentation 2)
  176. (put 'if 'indentation 2)
  177. (put 'when 'indentation 2)
  178. (put 'unless 'indentation 2)
  179. (put 'defmethod 'indentation 2)
  180. (put 'defflavor 'indentation 2)
  181. (put 'selectq 'indentation 2)
  182. (put 'catch 'indentation 2)
  183. (put 'catch-all 'indentation 2)
  184. (put 'setf 'indentation 2)
  185. (put 'setq 'indentation 2)
  186. (de id-specific-indent (id paren-column second-column)
  187. % The default indentation for a pattern like this:
  188. % .... (foo bar ...
  189. % bletch ...
  190. % is to line up bletch with bar. This pattern applies when FOO
  191. % is an atom (not a structure) and there is at least one
  192. % form (e.g. BAR) following it on the same line. This function
  193. % is used to specify exceptions to this rule. It is invoked
  194. % only when FOO is an INTERNed ID, since the exceptions are
  195. % defined by putting a property on the ID.
  196. (let ((indent (get id 'indentation)))
  197. (if indent (+ paren-column indent))
  198. ))