hp-emodex.sl 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. %
  2. % HP-EMODEX.SL - General HP EMODE Extensions
  3. %
  4. % Author: Alan Snyder
  5. % Hewlett-Packard/CRC
  6. % Date: 2 August 1982
  7. %
  8. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  9. %%%%% Changes: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  10. % WFG 23 August 1982
  11. % - Modified transpose-characters-command to behave as if at end of line if
  12. % the last command dispatched on was InsertSelfCharacter.
  13. % - Made several "lispy" commands specific to Lisp mode rather than text
  14. % mode.
  15. (BothTimes (load common))
  16. % The following symbolic constants should be used in source code
  17. % instead of the equivalent (Char X) expression to avoid fooling
  18. % EMODE's stupid LISP parser while editing this file:
  19. (CompileTime (setf LEFT-PAREN 40))
  20. (CompileTime (setf RIGHT-PAREN 41))
  21. (CompileTime (setf LEFT-PAREN-ID (int2id 40)))
  22. (CompileTime (setf RIGHT-PAREN-ID (int2id 41)))
  23. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  24. % Window Scrolling Functions
  25. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  26. (fluid '(CurrentLineIndex))
  27. (de scroll-window-by-lines (n)
  28. % Scroll the contents of the current window up (n > 0) or down (n < 0)
  29. % by |n| lines. CurrentLineIndex may be adjusted to keep it within
  30. % the desired window location.
  31. (let* ((window-height (current-window-height))
  32. (new-top-line (+ (current-window-top-line) n))
  33. (buffer-last-line (- (current-buffer-visible-size) 1))
  34. )
  35. % adjust to keep something in the window
  36. (cond
  37. ((< new-top-line 0) (setf new-top-line 0))
  38. ((> new-top-line buffer-last-line) (setf new-top-line buffer-last-line))
  39. )
  40. % adjust cursor if no longer in window
  41. (cond
  42. ((< CurrentLineIndex new-top-line)
  43. (SelectLine new-top-line))
  44. ((>= CurrentLineIndex (+ new-top-line window-height))
  45. (SelectLine (+ new-top-line window-height -1)))
  46. )
  47. (current-window-set-top-line new-top-line)
  48. ))
  49. (de scroll-window-by-pages (n)
  50. % Scroll the contents of the current window up (n > 0) or down (n < 0)
  51. % by |n| screen-fulls. CurrentLineIndex may be adjusted to keep it within
  52. % the desired window location.
  53. (let* ((old-top-line (current-window-top-line))
  54. (window-height (current-window-height))
  55. (new-top-line (+ (current-window-top-line) (* n window-height)))
  56. (buffer-last-line (- (current-buffer-visible-size) 1))
  57. )
  58. % don't do the scroll if no change is needed
  59. (cond ((and (> new-top-line (- window-height))
  60. (<= new-top-line buffer-last-line))
  61. (setf new-top-line (max new-top-line 0))
  62. % keep the cursor at the same relative location in the window!
  63. (SelectLine (min (+ CurrentLineIndex (- new-top-line old-top-line))
  64. (- (current-buffer-size) 1)))
  65. (current-window-set-top-line new-top-line)
  66. ))))
  67. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  68. % Window Scrolling Commands
  69. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  70. (de scroll-window-up-line-command ()
  71. (scroll-window-by-lines 1)
  72. )
  73. (de scroll-window-down-line-command ()
  74. (scroll-window-by-lines -1)
  75. )
  76. (de scroll-window-up-page-command ()
  77. (scroll-window-by-pages 1)
  78. )
  79. (de scroll-window-down-page-command ()
  80. (scroll-window-by-pages -1)
  81. )
  82. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  83. % Basic Indenting Primitives
  84. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  85. (de current-line-indent ()
  86. % Return the indentation of the current line, in terms of spaces.
  87. (for (in ch CurrentLine)
  88. (while (or (= ch (char space)) (= ch (char tab))))
  89. (sum (if (= ch (char tab)) 8 1))
  90. ))
  91. (de current-line-strip-indent ()
  92. % Strip all leading blanks and tabs from the current line.
  93. (while (and CurrentLine (char-blank? (car CurrentLine)))
  94. (setf CurrentLine (cdr CurrentLine))
  95. (if (> point 0) (setf point (- point 1)))
  96. ))
  97. (de strip-previous-blanks ()
  98. % Strip all blanks and tabs before point.
  99. (while (and (> point 0)
  100. (char-blank? (current-line-fetch (- point 1))))
  101. ($DeleteBackwardCharacter))
  102. )
  103. (de indent-current-line (n)
  104. % Adjust the current line to have the specified indentation.
  105. (current-line-strip-indent)
  106. (let ((n-spaces (remainder n 8))
  107. (n-tabs (quotient n 8)))
  108. (for (from i 1 n-spaces 1)
  109. (do (setf CurrentLine (cons (char space) CurrentLine))
  110. (setf point (+ 1 point))))
  111. (for (from i 1 n-tabs 1)
  112. (do (setf CurrentLine (cons (char tab) CurrentLine))
  113. (setf point (+ 1 point))))
  114. ))
  115. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  116. % Basic Indenting Commands
  117. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  118. (SetTextKey (char (meta !\)) 'delete-horizontal-space-command)
  119. (de delete-horizontal-space-command ()
  120. (prog (ch)
  121. (while (< point (current-line-length))
  122. (setf ch (current-line-fetch point))
  123. (if (not (char-blank? ch)) (exit))
  124. (DeleteCharacter)
  125. )
  126. (while (> point 0)
  127. (setf ch (current-line-fetch (- point 1)))
  128. (if (not (char-blank? ch)) (exit))
  129. (setf point (- point 1))
  130. (DeleteCharacter)
  131. )
  132. ))
  133. (SetTextKey (CharSequence (cntrl X) (cntrl O)) 'delete-blank-lines-command)
  134. (de delete-blank-lines-command ()
  135. (cond ((current-line-blank?)
  136. % We are on a blank line.
  137. % Replace multiple blank lines with one.
  138. % First, search backwards for the first blank line
  139. % and save its index.
  140. (while (> CurrentLineIndex 0)
  141. ($BackwardLine)
  142. (cond ((not (current-line-blank?))
  143. ($ForwardLine)
  144. (exit))
  145. )
  146. )
  147. (delete-following-blank-lines)
  148. )
  149. (t
  150. % We are on a non-blank line. Delete any blank lines
  151. % that follow this one.
  152. (delete-following-blank-lines)
  153. )
  154. ))
  155. (de delete-following-blank-lines ()
  156. % Delete any blank lines that immediately follow the current one.
  157. (if (not (current-line-is-last?))
  158. (progn
  159. (let ((old-index CurrentLineIndex)
  160. (old-point point)
  161. first-index
  162. )
  163. % Advance past the current line until the next nonblank line.
  164. (move-to-next-line)
  165. (setf first-index CurrentLineIndex)
  166. (while T
  167. (cond ((not (current-line-blank?)) (exit))
  168. ((current-line-is-last?) ($EndOfLine) (exit))
  169. (t (move-to-next-line))
  170. ))
  171. (delete_or_copy T first-index 0 CurrentLineIndex point)
  172. (current-buffer-goto old-index old-point)
  173. ))))
  174. (SetTextKey (char (meta M)) 'back-to-indentation-command)
  175. (SetTextKey (char (meta (cntrl M))) 'back-to-indentation-command)
  176. (de back-to-indentation-command ()
  177. ($BeginningOfLine)
  178. (while (char-blank? (CurrentCharacter))
  179. ($ForwardCharacter)
  180. ))
  181. (SetTextKey (char (meta ^)) 'delete-indentation-command)
  182. (de delete-indentation-command ()
  183. (current-line-strip-indent)
  184. ($BeginningOfLine)
  185. (if (not (current-line-is-first?))
  186. (progn
  187. ($DeleteBackwardCharacter)
  188. (if (and (not (= point 0))
  189. (not (= (current-line-fetch (- point 1)) #.LEFT-PAREN))
  190. (not (= (CurrentCharacter) #.RIGHT-PAREN))
  191. )
  192. (InsertCharacter (char space))
  193. ))))
  194. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  195. % LISP Indenting
  196. % Note: this is a crock - need more sophisticated scanning
  197. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  198. (SetLispKey (char tab) 'lisp-tab-command)
  199. (SetLispKey (char (meta (cntrl tab))) 'lisp-tab-command)
  200. (SetLispKey (char LF) 'lisp-linefeed-command)
  201. (SetLispKey (char (meta (cntrl Q))) 'lisp-indent-sexpr)
  202. (de lisp-tab-command ()
  203. (indent-current-line (lisp-current-line-indent)))
  204. (de lisp-linefeed-command ()
  205. ($CRLF)
  206. (indent-current-line (lisp-current-line-indent)))
  207. (de lisp-indent-sexpr ()
  208. (if (not (move-down-list))
  209. (Ding)
  210. (let ((old-line CurrentLineIndex)
  211. (old-point (- point 1))
  212. final-line)
  213. (if (not (forward-scan-for-right-paren -1))
  214. (Ding)
  215. (setf final-line CurrentLineIndex)
  216. (for (from i (+ old-line 1) final-line 1)
  217. (do
  218. (SelectLine i)
  219. (indent-current-line (lisp-current-line-indent))
  220. ))
  221. (current-buffer-goto old-line old-point)))
  222. ))
  223. (de lisp-current-line-indent ()
  224. (let ((old-point point)
  225. (old-line CurrentLineIndex)
  226. indentation
  227. previous-line)
  228. (cond ((and (> CurrentLineIndex 0)
  229. (setf previous-line (GetBufferText (- CurrentLineIndex 1)))
  230. (>= (size previous-line) 0)
  231. (= (indx previous-line 0) #.LEFT-PAREN)
  232. )
  233. 2)
  234. (t
  235. (setf point 0)
  236. (backward_sexpr)
  237. (setf indentation (LineColumn point (List2String CurrentLine)))
  238. (current-buffer-goto old-line old-point)
  239. indentation
  240. ))))
  241. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  242. % Miscellaneous Commands
  243. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  244. (SetTextKey (char (cntrl T)) 'transpose-characters-command)
  245. % Transpose the last two characters, if we're at the end of the line, or if
  246. % a character was just inserted. Otherwise, transpose the characters on
  247. % either side of point.
  248. (de transpose-characters-command ()
  249. (progn
  250. (if (or
  251. (= point (current-line-length))
  252. (eq last_operation 'InsertSelfCharacter))
  253. % We are at the end of a non-empty line, or last character was self
  254. % inserting.
  255. ($BackwardCharacter))
  256. (cond
  257. % We are at the beginning of a line, or the line has fewer then two
  258. % characters?
  259. ((or (= point 0) (< (current-line-length) 2))
  260. (Ding))
  261. (t
  262. % We are in the middle of a line.
  263. (prog (ch)
  264. ($BackwardCharacter)
  265. (setf ch (CurrentCharacter))
  266. (DeleteCharacter)
  267. ($ForwardCharacter)
  268. (InsertCharacter ch)
  269. )
  270. ))))
  271. (SetTextKey (char (meta @)) 'mark-word-command)
  272. (de mark-word-command ()
  273. (let ((old-index CurrentLineIndex)
  274. (old-point point))
  275. (forward_word)
  276. (SetMark)
  277. (current-buffer-goto old-index old-point)
  278. ))
  279. (SetTextKey (char (meta (cntrl @))) 'mark-sexp-command)
  280. (de mark-sexp-command ()
  281. (let ((old-index CurrentLineIndex)
  282. (old-point point))
  283. (forward_sexpr)
  284. (SetMark)
  285. (current-buffer-goto old-index old-point)
  286. ))
  287. (SetTextKey (CharSequence (cntrl X) H) 'mark-whole-buffer-command)
  288. (de mark-whole-buffer-command ()
  289. ($EndOfBuffer)
  290. (SetMark)
  291. ($BeginningOfBuffer)
  292. )
  293. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  294. % LISP Defun Commands and Primitives
  295. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  296. (SetLispKey (char (meta (cntrl A))) 'beginning-of-defun-command)
  297. (SetLispKey (char (meta (cntrl ![))) 'beginning-of-defun-command)
  298. (de beginning-of-defun-command ()
  299. % Move BACKWARD (literally) to the beginning of the current
  300. % (or previous) DEFUN. If this is impossible, Ding and don't move.
  301. (if (at-buffer-start?)
  302. (Ding)
  303. ($BackwardCharacter)
  304. (if (not (beginning-of-defun)) (progn ($ForwardCharacter) (Ding)))
  305. ))
  306. (de beginning-of-defun ()
  307. % Move backward to the beginning of the current DEFUN. A DEFUN is
  308. % heuristically defined to be a line whose first character is a left
  309. % parenthesis. If no DEFUN is found, point is left unchanged and
  310. % NIL is returned; otherwise T is returned.
  311. (let ((pos (buffer-get-position))
  312. )
  313. ($BeginningOfLine)
  314. (while T
  315. (cond ((= (CurrentCharacter) #.LEFT-PAREN) (exit T))
  316. ((current-line-is-first?)
  317. (buffer-set-position pos)
  318. (exit NIL))
  319. (t (move-to-previous-line))
  320. ))))
  321. (SetLispKey (char (meta (cntrl E))) 'end-of-defun-command)
  322. (SetLispKey (char (meta (cntrl !]))) 'end-of-defun-command)
  323. (de end-of-defun-command ()
  324. % Move FORWARD (literally) to the beginning of the next line following
  325. % the end of a DEFUN.
  326. (let ((old-line CurrentLineIndex)
  327. )
  328. (if (or (not (end-of-defun)) (< CurrentLineIndex old-line))
  329. % If there is no current defun, or we were past the end of the
  330. % previous DEFUN, then we should continue onward to look for the
  331. % next DEFUN.
  332. (if (forward-defun)
  333. (forward_sexpr)
  334. (Ding)
  335. )))
  336. (move-to-next-line)
  337. )
  338. (de forward-defun ()
  339. % Move forward to the beginning of the next DEFUN.
  340. % If no DEFUN is found, point is left unchanged and
  341. % NIL is returned; otherwise T is returned.
  342. (let ((pos (buffer-get-position))
  343. )
  344. (while T
  345. (move-to-next-line)
  346. (cond ((= (CurrentCharacter) #.LEFT-PAREN) (exit T))
  347. ((current-line-is-last?)
  348. (buffer-set-position pos)
  349. (exit NIL))
  350. ))))
  351. (de end-of-defun ()
  352. % Move forward to the end of the current DEFUN.
  353. % If there is no current DEFUN, don't move and return NIL.
  354. % Otherwise, return T.
  355. (cond ((not (beginning-of-defun)) NIL)
  356. (t (forward_sexpr) T)
  357. ))
  358. (SetLispKey (char (meta (cntrl H))) 'mark-defun-command)
  359. (de mark-defun-command ()
  360. (end-of-defun-command)
  361. (SetMark)
  362. (beginning-of-defun-command)
  363. (if (> CurrentLineIndex 0)
  364. (progn
  365. (move-to-previous-line)
  366. (if (not (current-line-blank?))
  367. (move-to-next-line))
  368. ))
  369. )
  370. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  371. % Lisp List Commands and Primitives
  372. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  373. (fluid '(paren_depth)) % see Search.RED
  374. % Perhaps SetLispKey is more appropriate?
  375. (SetTextKey (char (meta (cntrl P))) 'move-past-previous-list)
  376. (de move-past-previous-list ()
  377. % Move to the beginning of the current or previous list. In other words,
  378. % find the previous left paren whose matching right paren is after point
  379. % or is the first right paren before point.
  380. % If no such left paren can be found, Ding, but do not move.
  381. (if (not (reverse-scan-for-left-paren 0)) (Ding))
  382. )
  383. % (SetTextKey (char (meta (cntrl #.LEFT-PAREN-ID))) 'backward-up-list)
  384. (SetTextKey (char (meta (cntrl U))) 'backward-up-list)
  385. (de backward-up-list ()
  386. % Move to the left of the current list. "Dual" to forward-up-list.
  387. (if (not (reverse-scan-for-left-paren 1)) (Ding))
  388. )
  389. (de reverse-scan-for-left-paren (depth)
  390. % Scan backwards (starting with the character before point) for
  391. % a left paren at depth >= the specified depth. If found, the
  392. % left paren will be after point and T will be returned. Otherwise,
  393. % point will not change and NIL will be returned.
  394. (let ((old-position (buffer-get-position))
  395. ch
  396. )
  397. (setf paren_depth 0)
  398. (while T
  399. (cond ((and (= ch #.LEFT-PAREN) (>= paren_depth depth))
  400. (exit T))
  401. ((at-buffer-start?)
  402. (buffer-set-position old-position)
  403. (exit NIL))
  404. (t ($BackwardCharacter)
  405. (setf ch (CurrentCharacter))
  406. (adjust_depth ch)
  407. )
  408. ))))
  409. (SetTextKey (char (meta (cntrl N))) 'move-past-next-list)
  410. (de move-past-next-list ()
  411. % Move to the right of the current or next list. In other words,
  412. % find the next right paren whose matching left paren is before point
  413. % or is the first left paren after point.
  414. % If no such right paren can be found, Ding, but do not move.
  415. (if (not (forward-scan-for-right-paren 0)) (Ding))
  416. )
  417. % (SetTextKey (char (meta (cntrl #.RIGHT-PAREN-ID))) 'forward-up-list)
  418. (SetTextKey (char (meta (cntrl O))) 'forward-up-list)
  419. (de forward-up-list ()
  420. % Move to the right of the current list. In other words,
  421. % find the next right paren whose matching left paren is before point.
  422. % If no such right paren can be found, Ding, but do not move.
  423. (if (not (forward-scan-for-right-paren -1)) (Ding))
  424. )
  425. (de forward-scan-for-right-paren (depth)
  426. % Scan forward (starting with the character after point) for
  427. % a right paren at depth <= the specified depth. If found, the
  428. % right paren will be before point and T will be returned. Otherwise,
  429. % point will not change and NIL will be returned.
  430. (let ((old-position (buffer-get-position))
  431. ch
  432. )
  433. (setf paren_depth 0)
  434. (while T
  435. (cond ((at-buffer-end?)
  436. (buffer-set-position old-position)
  437. (exit NIL)))
  438. (setf ch (CurrentCharacter))
  439. (adjust_depth ch)
  440. ($ForwardCharacter)
  441. (cond ((and (= ch #.RIGHT-PAREN) (<= paren_depth depth))
  442. (exit T))
  443. ))))
  444. (SetTextKey (char (meta (cntrl D))) 'down-list)
  445. (de down-list ()
  446. % Move inside the next contained list. In other words,
  447. % find the next left paren without an intervening right paren.
  448. % If no such left paren can be found, Ding, but do not move.
  449. (if (not (move-down-list)) (Ding))
  450. )
  451. (de move-down-list ()
  452. (let ((old-position (buffer-get-position))
  453. ch
  454. )
  455. (while T
  456. (cond ((at-buffer-end?)
  457. (buffer-set-position old-position)
  458. (exit NIL)))
  459. (setf ch (CurrentCharacter))
  460. ($ForwardCharacter)
  461. (cond ((= ch #.LEFT-PAREN)
  462. (exit T))
  463. ((= ch #.RIGHT-PAREN)
  464. (buffer-set-position old-position)
  465. (exit NIL))
  466. ))))
  467. (SetTextKey (char (meta #.LEFT-PAREN-ID)) 'insert-parens)
  468. (de insert-parens ()
  469. (InsertCharacter #.LEFT-PAREN)
  470. (InsertCharacter #.RIGHT-PAREN)
  471. ($BackwardCharacter)
  472. )
  473. (SetTextKey (char (meta #.RIGHT-PAREN-ID)) 'move-over-paren)
  474. (de move-over-paren ()
  475. (if (forward-scan-for-right-paren 0)
  476. (progn
  477. ($BackwardCharacter)
  478. (strip-previous-blanks)
  479. ($ForwardCharacter)
  480. (lisp-linefeed-command)
  481. )
  482. (Ding)))