home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1590 < prev    next >
Internet Message Format  |  1990-12-28  |  29KB

  1. From: mip@IDA.LiU.SE (Mikael Patel)
  2. Newsgroups: alt.sources
  3. Subject: TILE Forth Release 2.0, package 5 of 6
  4. Message-ID: <1962@majestix.ida.liu.se>
  5. Date: 16 Jul 90 18:58:40 GMT
  6.  
  7.  
  8. #! /bin/sh
  9. # This is a shell archive.  Remove anything before this line, then unpack
  10. # it by saving it into a file and typing "sh file".  To overwrite existing
  11. # files, type "sh file -c".  You can also feed this as standard input via
  12. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  13. # will see the following message at the end:
  14. #        "End of archive 5 (of 6)."
  15. # Contents:  src/forth.el
  16. # Wrapped by mip@mina on Fri Jun 29 16:49:13 1990
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f src/forth.el -a "${1}" != "-c" ; then 
  19.   echo shar: Will not over-write existing file \"src/forth.el\"
  20. else
  21. echo shar: Extracting \"src/forth.el\" \(27117 characters\)
  22. sed "s/^X//" >src/forth.el <<'END_OF_src/forth.el'
  23. X;; This file is part of GNU Emacs.
  24. X
  25. X;; GNU Emacs is distributed in the hope that it will be useful,
  26. X;; but WITHOUT ANY WARRANTY.  No author or distributor
  27. X;; accepts responsibility to anyone for the consequences of using it
  28. X;; or for whether it serves any particular purpose or works at all,
  29. X;; unless he says so in writing.  Refer to the GNU Emacs General Public
  30. X;; License for full details.
  31. X
  32. X;; Everyone is granted permission to copy, modify and redistribute
  33. X;; GNU Emacs, but only under the conditions described in the
  34. X;; GNU Emacs General Public License.   A copy of this license is
  35. X;; supposed to have been given to you along with GNU Emacs so you
  36. X;; can know your rights and responsibilities.  It should be in a
  37. X;; file named COPYING.  Among other things, the copyright notice
  38. X;; and this notice must be preserved on all copies.
  39. X
  40. X;;; $Header: forth.el,v 2.10 89/12/05 mip@ida.liu.se Exp $
  41. X
  42. X;;-------------------------------------------------------------------
  43. X;; A Forth indentation, documentation search and interaction library
  44. X;;-------------------------------------------------------------------
  45. X;;
  46. X;; Written by Goran Rydqvist, gorry@ida.liu.se, Summer 1988
  47. X;; Started:    16 July 88
  48. X;; Version:    2.10
  49. X;; Last update:    5 December 1989 by Mikael Patel, mip@ida.liu.se
  50. X;; Last update:    25 June 1990 by Goran Rydqvist, gorry@ida.liu.se
  51. X;;
  52. X;; Documentation: See forth-mode (^HF forth-mode)
  53. X;;-------------------------------------------------------------------
  54. X
  55. X
  56. X(defvar forth-positives
  57. X  " : begin do ?do while if else case block[ does> exception> struct.type struct.init struct.does accept task.type task.body subclass method enum.type "
  58. X  "Contains all words which will cause the indent-level to be incremented
  59. Xon the next line.
  60. XOBS! All words in forth-positives must be surrounded by spaces.")
  61. X
  62. X(defvar forth-negatives
  63. X  " ; ]; until repeat while +loop loop else then again endcase does> exception> struct.init struct.does struct.end accept.end task.body task.end subclass.end enum.end "
  64. X  "Contains all words which will cause the indent-level to be decremented
  65. Xon the current line.
  66. XOBS! All words in forth-negatives must be surrounded by spaces.")
  67. X
  68. X(defvar forth-zeroes
  69. X  " : ; does> exception> struct.end task.end enum.end"
  70. X  "Contains all words which causes the indent to go to zero")
  71. X
  72. X(defvar forth-mode-abbrev-table nil
  73. X  "Abbrev table in use in Forth-mode buffers.")
  74. X
  75. X(define-abbrev-table 'forth-mode-abbrev-table ())
  76. X
  77. X(defvar forth-mode-map nil
  78. X  "Keymap used in Forth mode.")
  79. X
  80. X(if (not forth-mode-map)
  81. X    (setq forth-mode-map (make-sparse-keymap)))
  82. X
  83. X(global-set-key "\e\C-m" 'forth-send-paragraph)
  84. X(global-set-key "\C-x\C-m" 'forth-split)
  85. X(global-set-key "\e " 'forth-reload)
  86. X
  87. X(define-key forth-mode-map "\e\C-m" 'forth-send-paragraph)
  88. X(define-key forth-mode-map "\eo" 'forth-send-buffer)
  89. X(define-key forth-mode-map "\C-x\C-m" 'forth-split)
  90. X(define-key forth-mode-map "\e " 'forth-reload)
  91. X(define-key forth-mode-map "\t" 'forth-indent-command)
  92. X(define-key forth-mode-map "\C-m" 'reindent-then-newline-and-indent)
  93. X
  94. X(defvar forth-mode-syntax-table nil
  95. X  "Syntax table in use in Forth-mode buffers.")
  96. X
  97. X(if (not forth-mode-syntax-table)
  98. X    (progn
  99. X      (setq forth-mode-syntax-table (make-syntax-table))
  100. X      (modify-syntax-entry ?\\ "\\" forth-mode-syntax-table)
  101. X      (modify-syntax-entry ?/ ". 14" forth-mode-syntax-table)
  102. X      (modify-syntax-entry ?* ". 23" forth-mode-syntax-table)
  103. X      (modify-syntax-entry ?+ "." forth-mode-syntax-table)
  104. X      (modify-syntax-entry ?- "." forth-mode-syntax-table)
  105. X      (modify-syntax-entry ?= "." forth-mode-syntax-table)
  106. X      (modify-syntax-entry ?% "." forth-mode-syntax-table)
  107. X      (modify-syntax-entry ?< "." forth-mode-syntax-table)
  108. X      (modify-syntax-entry ?> "." forth-mode-syntax-table)
  109. X      (modify-syntax-entry ?& "." forth-mode-syntax-table)
  110. X      (modify-syntax-entry ?| "." forth-mode-syntax-table)
  111. X      (modify-syntax-entry ?\' "\"" forth-mode-syntax-table)
  112. X      (modify-syntax-entry ?\t "    " forth-mode-syntax-table)
  113. X      (modify-syntax-entry ?) ">   " forth-mode-syntax-table)
  114. X      (modify-syntax-entry ?( "<   " forth-mode-syntax-table)
  115. X      (modify-syntax-entry ?\( "()  " forth-mode-syntax-table)
  116. X      (modify-syntax-entry ?\) ")(  " forth-mode-syntax-table)))
  117. X
  118. X(defconst forth-indent-level 2
  119. X  "Indentation of Forth statements.")
  120. X
  121. X(defun forth-mode-variables ()
  122. X  (set-syntax-table forth-mode-syntax-table)
  123. X  (setq local-abbrev-table forth-mode-abbrev-table)
  124. X  (make-local-variable 'paragraph-start)
  125. X  (setq paragraph-start (concat "^$\\|" page-delimiter))
  126. X  (make-local-variable 'paragraph-separate)
  127. X  (setq paragraph-separate paragraph-start)
  128. X  (make-local-variable 'indent-line-function)
  129. X  (setq indent-line-function 'forth-indent-line)
  130. X  (make-local-variable 'require-final-newline)
  131. X  (setq require-final-newline t)
  132. X  (make-local-variable 'comment-start)
  133. X  (setq comment-start "( ")
  134. X  (make-local-variable 'comment-end)
  135. X  (setq comment-end " )")
  136. X  (make-local-variable 'comment-column)
  137. X  (setq comment-column 40)
  138. X  (make-local-variable 'comment-start-skip)
  139. X  (setq comment-start-skip "( ")
  140. X  (make-local-variable 'comment-indent-hook)
  141. X  (setq comment-indent-hook 'forth-comment-indent)
  142. X  (make-local-variable 'parse-sexp-ignore-comments)
  143. X  (setq parse-sexp-ignore-comments t))
  144. X  
  145. X(defun forth-mode ()
  146. X  "
  147. XMajor mode for editing Forth code. Tab indents for Forth code. Comments
  148. Xare delimited with ( ). Paragraphs are separated by blank lines only.
  149. XDelete converts tabs to spaces as it moves back.
  150. X\\{forth-mode-map}
  151. X Forth-split
  152. X    Positions the current buffer on top and a forth-interaction window
  153. X    below. The window size is controlled by the forth-percent-height
  154. X    variable (see below).
  155. X Forth-reload
  156. X    Reloads the forth library and restarts the forth process.
  157. X Forth-send-buffer
  158. X    Sends the current buffer, in text representation, as input to the
  159. X    forth process.
  160. X Forth-send-paragraph
  161. X    Sends the previous or the current paragraph to the forth-process.
  162. X    Note that the cursor only need to be with in the paragraph to be sent.
  163. Xforth-documentation
  164. X    Search for documentation of forward adjacent to cursor. Note! To use
  165. X    this mode you have to add a line, to your .emacs file, defining the
  166. X    directories to search through for documentation files (se variable
  167. X    forth-help-load-path below) e.g. (setq forth-help-load-path '(nil)).
  168. X
  169. XVariables controlling interaction and startup
  170. X forth-percent-height
  171. X    Tells split how high to make the edit portion, in percent of the
  172. X    current screen height.
  173. X forth-program-name
  174. X    Tells the library which program name to execute in the interation
  175. X    window.
  176. X
  177. XVariables controlling indentation style:
  178. X forth-positives
  179. X    A string containing all words which causes the indent-level of the
  180. X    following line to be incremented.
  181. X    OBS! Each word must be surronded by spaces.
  182. X forth-negatives
  183. X    A string containing all words which causes the indentation of the
  184. X    current line to be decremented, if the word begin the line. These
  185. X    words also has a cancelling effect on the indent-level of the
  186. X    following line, independent of position.
  187. X    OBS! Each word must be surronded by spaces.
  188. X forth-zeroes
  189. X    A string containing all words which causes the indentation of the
  190. X    current line to go to zero, if the word begin the line.
  191. X    OBS! Each word must be surronded by spaces.
  192. X forth-indent-level
  193. X    Indentation increment/decrement of Forth statements.
  194. X
  195. X Note! A word which decrements the indentation of the current line, may
  196. X    also be mentioned in forth-positives to cause the indentation to
  197. X    resume the previous level.
  198. X
  199. XVariables controling documentation search
  200. X forth-help-load-path
  201. X    List of directories to search through to find *.doc
  202. X    (forth-help-file-suffix) files. Nil means current default directory.
  203. X    The specified directories must contain at least one .doc file. If it
  204. X    does not and you still want the load-path to scan that directory, create
  205. X    an empty file dummy.doc.
  206. X forth-help-file-suffix
  207. X    The file names to search for in each directory specified by
  208. X    forth-help-load-path. Defaulted to '*.doc'. 
  209. X"
  210. X  (interactive)
  211. X  (kill-all-local-variables)
  212. X  (use-local-map forth-mode-map)
  213. X  (setq mode-name "Forth")
  214. X  (setq major-mode 'forth-mode)
  215. X  (forth-mode-variables)
  216. X  (if (not (forth-process-running-p))
  217. X      (run-forth forth-program-name))
  218. X  (run-hooks 'forth-mode-hook))
  219. X
  220. X(defun forth-comment-indent ()
  221. X  (save-excursion
  222. X    (beginning-of-line)
  223. X    (if (looking-at ":[ \t]*")
  224. X    (progn
  225. X      (end-of-line)
  226. X      (skip-chars-backward " \t\n")
  227. X      (1+ (current-column)))
  228. X      comment-column)))
  229. X
  230. X(defun forth-current-indentation ()
  231. X  (save-excursion
  232. X    (beginning-of-line)
  233. X    (back-to-indentation)
  234. X    (current-column)))
  235. X
  236. X(defun forth-delete-indentation ()
  237. X  (let ((b nil) (m nil))
  238. X    (save-excursion
  239. X      (beginning-of-line)
  240. X      (setq b (point))
  241. X      (back-to-indentation)
  242. X      (setq m (point)))
  243. X    (delete-region b m)))
  244. X
  245. X(defun forth-indent-line (&optional flag)
  246. X  "Correct indentation of the current Forth line."
  247. X  (let ((x (forth-calculate-indent)))
  248. X    (forth-indent-to x)))
  249. X  
  250. X(defun forth-indent-command ()
  251. X  (interactive)
  252. X  (forth-indent-line t))
  253. X
  254. X(defun forth-indent-to (x)
  255. X  (let ((p nil))
  256. X    (setq p (- (current-column) (forth-current-indentation)))
  257. X    (forth-delete-indentation)
  258. X    (beginning-of-line)
  259. X    (indent-to x)
  260. X    (if (> p 0) (forward-char p))))
  261. X
  262. X;;Calculate indent
  263. X(defun forth-calculate-indent ()
  264. X  (let ((w1 nil) (indent 0) (centre 0))
  265. X    (save-excursion
  266. X      (beginning-of-line)
  267. X      (skip-chars-backward " \t\n")
  268. X      (beginning-of-line)
  269. X      (back-to-indentation)
  270. X      (setq indent (current-column))
  271. X      (setq centre indent)
  272. X      (setq indent (+ indent (forth-sum-line-indentation))))
  273. X    (save-excursion
  274. X      (beginning-of-line)
  275. X      (back-to-indentation)
  276. X      (let ((p (point)))
  277. X    (skip-chars-forward "^ \t\n")
  278. X    (setq w1 (buffer-substring p (point)))))
  279. X    (if (> (- indent centre) forth-indent-level)
  280. X    (setq indent (+ centre forth-indent-level)))
  281. X    (if (> (- centre indent) forth-indent-level)
  282. X    (setq indent (- centre forth-indent-level)))
  283. X    (if (< indent 0) (setq indent 0))
  284. X    (setq indent (- indent
  285. X            (if (string-match 
  286. X             (regexp-quote (concat " " w1 " "))
  287. X             forth-negatives)
  288. X            forth-indent-level 0)))
  289. X    (if (string-match (regexp-quote (concat " " w1 " ")) forth-zeroes)
  290. X    (setq indent 0))
  291. X    indent))
  292. X
  293. X(defun forth-sum-line-indentation ()
  294. X  "Add upp the positive and negative weights of all words on the current line."
  295. X  (let ((b (point)) (e nil) (sum 0) (w nil) (t1 nil) (t2 nil) (first t))
  296. X    (end-of-line) (setq e (point))
  297. X    (goto-char b)
  298. X    (while (< (point) e)
  299. X      (setq w (forth-next-word))
  300. X      (setq t1 (string-match (regexp-quote (concat " " w " "))
  301. X                 forth-positives))
  302. X      (setq t2 (string-match (regexp-quote (concat " " w " "))
  303. X                 forth-negatives))
  304. X      (if (and t1 t2)
  305. X      (setq sum (+ sum forth-indent-level)))
  306. X      (if t1
  307. X      (setq sum (+ sum forth-indent-level)))
  308. X      (if (and t2 (not first))
  309. X      (setq sum (- sum forth-indent-level)))
  310. X      (skip-chars-forward " \t")
  311. X      (setq first nil))
  312. X    sum))
  313. X
  314. X
  315. X(defun forth-next-word ()
  316. X  "Return the next forth-word. Skip anything enclosed in double quotes or ()."
  317. X  (let ((w1 nil))
  318. X    (while (not w1)
  319. X      (skip-chars-forward " \t\n")
  320. X      (let ((p (point)))
  321. X    (skip-chars-forward "^ \t\n")
  322. X    (setq w1 (buffer-substring p (point))))
  323. X      (cond ((string-match "\"" w1)
  324. X         (progn
  325. X           (skip-chars-forward "^\"")
  326. X           (setq w1 nil)))
  327. X        ((string-match "\(" w1)
  328. X         (progn
  329. X           (skip-chars-forward "^\)")
  330. X           (setq w1 nil)))
  331. X        (t nil)))
  332. X    w1))
  333. X      
  334. X
  335. X;; Forth commands
  336. X
  337. X(defvar forth-program-name "forth"
  338. X  "*Program invoked by the `run-forth' command.")
  339. X
  340. X(defvar forth-band-name nil
  341. X  "*Band loaded by the `run-forth' command.")
  342. X
  343. X(defvar forth-program-arguments nil
  344. X  "*Arguments passed to the Forth program by the `run-forth' command.")
  345. X
  346. X(defun run-forth (command-line)
  347. X  "Run an inferior Forth process. Output goes to the buffer `*forth*'.
  348. XWith argument, asks for a command line. Split up screen and run forth 
  349. Xin the lower portion. The current-buffer when called will stay in the
  350. Xupper portion of the screen, and all other windows are deleted.
  351. XCall run-forth again to make the *forth* buffer appear in the lower
  352. Xpart of the screen."
  353. X  (interactive
  354. X   (list (let ((default
  355. X         (or forth-process-command-line
  356. X             (forth-default-command-line))))
  357. X       (if current-prefix-arg
  358. X           (read-string "Run Forth: " default)
  359. X           default))))
  360. X  (setq forth-process-command-line command-line)
  361. X  (forth-start-process command-line)
  362. X  (forth-split)
  363. X  (forth-set-runlight forth-runlight:input))
  364. X
  365. X(defun reset-forth ()
  366. X  "Reset the Forth process."
  367. X  (interactive)
  368. X  (let ((process (get-process forth-program-name)))
  369. X    (cond ((or (not process)
  370. X           (not (eq (process-status process) 'run))
  371. X           (yes-or-no-p
  372. X"The Forth process is running, are you SURE you want to reset it? "))
  373. X       (message "Resetting Forth process...")
  374. X       (forth-reload)
  375. X       (message "Resetting Forth process...done")))))
  376. X
  377. X(defun forth-default-command-line ()
  378. X  (concat forth-program-name " -emacs"
  379. X      (if forth-program-arguments
  380. X          (concat " " forth-program-arguments)
  381. X          "")
  382. X      (if forth-band-name
  383. X          (concat " -band " forth-band-name)
  384. X          "")))
  385. X
  386. X;;;; Internal Variables
  387. X
  388. X(defvar forth-process-command-line nil
  389. X  "Command used to start the most recent Forth process.")
  390. X
  391. X(defvar forth-previous-send ""
  392. X  "Most recent expression transmitted to the Forth process.")
  393. X
  394. X(defvar forth-process-filter-queue '()
  395. X  "Queue used to synchronize filter actions properly.")
  396. X
  397. X(defvar forth-prompt "ok"
  398. X  "The current forth prompt string.")
  399. X
  400. X(defvar forth-start-hook nil
  401. X  "If non-nil, a procedure to call when the Forth process is started.
  402. XWhen called, the current buffer will be the Forth process-buffer.")
  403. X
  404. X(defvar forth-signal-death-message nil
  405. X  "If non-nil, causes a message to be generated when the Forth process dies.")
  406. X
  407. X(defvar forth-percent-height 62
  408. X  "Tells run-forth how high the upper window should be in percent.")
  409. X
  410. X(defconst forth-runlight:input ?I
  411. X  "The character displayed when the Forth process is waiting for input.")
  412. X
  413. X(defvar forth-mode-string ""
  414. X  "String displayed in the mode line when the Forth process is running.")
  415. X
  416. X;;;; Evaluation Commands
  417. X
  418. X(defun forth-send-string (&rest strings)
  419. X  "Send the string arguments to the Forth process.
  420. XThe strings are concatenated and terminated by a newline."
  421. X  (cond ((forth-process-running-p)
  422. X     (forth-send-string-1 strings))
  423. X    ((yes-or-no-p "The Forth process has died.  Reset it? ")
  424. X     (reset-forth)
  425. X     (goto-char (point-max))
  426. X     (forth-send-string-1 strings))))
  427. X
  428. X(defun forth-send-string-1 (strings)
  429. X  (let ((string (apply 'concat strings)))
  430. X    (forth-send-string-2 string)))
  431. X
  432. X(defun forth-send-string-2 (string)
  433. X  (let ((process (get-process forth-program-name)))
  434. X    (if (not (eq (current-buffer) (get-buffer forth-program-name)))
  435. X    (progn
  436. X     (forth-process-filter-output string)
  437. X     (forth-process-filter:finish)))
  438. X    (send-string process (concat string "\n"))
  439. X    (if (eq (current-buffer) (process-buffer process))
  440. X    (set-marker (process-mark process) (point)))))
  441. X
  442. X
  443. X(defun forth-send-region (start end)
  444. X  "Send the current region to the Forth process.
  445. XThe region is sent terminated by a newline."
  446. X  (interactive "r")
  447. X  (let ((process (get-process forth-program-name)))
  448. X    (if (and process (eq (current-buffer) (process-buffer process)))
  449. X    (progn (goto-char end)
  450. X           (set-marker (process-mark process) end))))
  451. X  (forth-send-string "\n" (buffer-substring start end) "\n"))
  452. X
  453. X(defun forth-end-of-paragraph ()
  454. X  (if (looking-at "[\t\n ]+") (skip-chars-backward  "\t\n "))
  455. X  (if (not (re-search-forward "\n[ \t]*\n" nil t))
  456. X      (goto-char (point-max))))
  457. X
  458. X(defun forth-send-paragraph ()
  459. X  "Send the current or the previous paragraph to the Forth process"
  460. X  (interactive)
  461. X  (let (end)
  462. X    (save-excursion
  463. X      (forth-end-of-paragraph)
  464. X      (skip-chars-backward  "\t\n ")
  465. X      (setq end (point))
  466. X      (if (re-search-backward "\n[ \t]*\n" nil t)
  467. X      (setq start (point))
  468. X    (goto-char (point-min)))
  469. X      (skip-chars-forward  "\t\n ")
  470. X      (forth-send-region (point) end))))
  471. X  
  472. X(defun forth-send-buffer ()
  473. X  "Send the current buffer to the Forth process."
  474. X  (interactive)
  475. X  (if (eq (current-buffer) (forth-process-buffer))
  476. X      (error "Not allowed to send this buffer's contents to Forth"))
  477. X  (forth-send-region (point-min) (point-max)))
  478. X
  479. X
  480. X;;;; Basic Process Control
  481. X
  482. X(defun forth-start-process (command-line)
  483. X  (let ((buffer (get-buffer-create "*forth*")))
  484. X    (let ((process (get-buffer-process buffer)))
  485. X      (save-excursion
  486. X    (set-buffer buffer)
  487. X    (progn (if process (delete-process process))
  488. X           (goto-char (point-max))
  489. X           (setq mode-line-process '(": %s"))
  490. X           (add-to-global-mode-string 'forth-mode-string)
  491. X           (setq process
  492. X             (apply 'start-process
  493. X                (cons forth-program-name
  494. X                  (cons buffer
  495. X                    (forth-parse-command-line
  496. X                     command-line)))))
  497. X           (set-marker (process-mark process) (point-max))
  498. X           (forth-process-filter-initialize t)
  499. X           (forth-modeline-initialize)
  500. X           (set-process-sentinel process 'forth-process-sentinel)
  501. X           (set-process-filter process 'forth-process-filter)
  502. X           (run-hooks 'forth-start-hook)))
  503. X    buffer)))
  504. X
  505. X(defun forth-parse-command-line (string)
  506. X  (setq string (substitute-in-file-name string))
  507. X  (let ((start 0)
  508. X    (result '()))
  509. X    (while start
  510. X      (let ((index (string-match "[ \t]" string start)))
  511. X    (setq start
  512. X          (cond ((not index)
  513. X             (setq result
  514. X               (cons (substring string start)
  515. X                 result))
  516. X             nil)
  517. X            ((= index start)
  518. X             (string-match "[^ \t]" string start))
  519. X            (t
  520. X             (setq result
  521. X               (cons (substring string start index)
  522. X                 result))
  523. X             (1+ index))))))
  524. X    (nreverse result)))
  525. X
  526. X
  527. X(defun forth-process-running-p ()
  528. X  "True iff there is a Forth process whose status is `run'."
  529. X  (let ((process (get-process forth-program-name)))
  530. X    (and process
  531. X     (eq (process-status process) 'run))))
  532. X
  533. X(defun forth-process-buffer ()
  534. X  (let ((process (get-process forth-program-name)))
  535. X    (and process (process-buffer process))))
  536. X
  537. X;;;; Process Filter
  538. X
  539. X(defun forth-process-sentinel (proc reason)
  540. X  (let ((inhibit-quit nil))
  541. X    (forth-process-filter-initialize (eq reason 'run))
  542. X    (if (eq reason 'run)
  543. X    (forth-modeline-initialize)
  544. X    (setq forth-mode-string "")))
  545. X  (if (and (not (memq reason '(run stop)))
  546. X       forth-signal-death-message)
  547. X      (progn (beep)
  548. X         (message
  549. X"The Forth process has died!  Do M-x reset-forth to restart it"))))
  550. X
  551. X(defun forth-process-filter-initialize (running-p)
  552. X  (setq forth-process-filter-queue (cons '() '()))
  553. X  (setq forth-prompt "ok"))
  554. X
  555. X
  556. X(defun forth-process-filter (proc string)
  557. X  (forth-process-filter-output string)
  558. X  (forth-process-filter:finish))
  559. X
  560. X(defun forth-process-filter:enqueue (action)
  561. X  (let ((next (cons action '())))
  562. X    (if (cdr forth-process-filter-queue)
  563. X    (setcdr (cdr forth-process-filter-queue) next)
  564. X    (setcar forth-process-filter-queue next))
  565. X    (setcdr forth-process-filter-queue next)))
  566. X
  567. X(defun forth-process-filter:finish ()
  568. X  (while (car forth-process-filter-queue)
  569. X    (let ((next (car forth-process-filter-queue)))
  570. X      (setcar forth-process-filter-queue (cdr next))
  571. X      (if (not (cdr next))
  572. X      (setcdr forth-process-filter-queue '()))
  573. X      (apply (car (car next)) (cdr (car next))))))
  574. X
  575. X;;;; Process Filter Output
  576. X
  577. X(defun forth-process-filter-output (&rest args)
  578. X  (if (not (and args
  579. X        (null (cdr args))
  580. X        (stringp (car args))
  581. X        (string-equal "" (car args))))
  582. X      (forth-process-filter:enqueue
  583. X       (cons 'forth-process-filter-output-1 args))))
  584. X
  585. X(defun forth-process-filter-output-1 (&rest args)
  586. X  (save-excursion
  587. X    (forth-goto-output-point)
  588. X    (apply 'insert-before-markers args)))
  589. X
  590. X(defun forth-guarantee-newlines (n)
  591. X  (save-excursion
  592. X    (forth-goto-output-point)
  593. X    (let ((stop nil))
  594. X      (while (and (not stop)
  595. X          (bolp))
  596. X    (setq n (1- n))
  597. X    (if (bobp)
  598. X        (setq stop t)
  599. X      (backward-char))))
  600. X    (forth-goto-output-point)
  601. X    (while (> n 0)
  602. X      (insert-before-markers ?\n)
  603. X      (setq n (1- n)))))
  604. X
  605. X(defun forth-goto-output-point ()
  606. X  (let ((process (get-process forth-program-name)))
  607. X    (set-buffer (process-buffer process))
  608. X    (goto-char (process-mark process))))
  609. X
  610. X(defun forth-modeline-initialize ()
  611. X  (setq forth-mode-string "  "))
  612. X
  613. X(defun forth-set-runlight (runlight)
  614. X  (aset forth-mode-string 0 runlight)
  615. X  (forth-modeline-redisplay))
  616. X
  617. X(defun forth-modeline-redisplay ()
  618. X  (save-excursion (set-buffer (other-buffer)))
  619. X  (set-buffer-modified-p (buffer-modified-p))
  620. X  (sit-for 0))
  621. X
  622. X;;;; Process Filter Operations
  623. X
  624. X(defun add-to-global-mode-string (x)
  625. X  (cond ((null global-mode-string)
  626. X     (setq global-mode-string (list "" x " ")))
  627. X    ((not (memq x global-mode-string))
  628. X     (setq global-mode-string
  629. X           (cons ""
  630. X             (cons x
  631. X               (cons " "
  632. X                 (if (equal "" (car global-mode-string))
  633. X                     (cdr global-mode-string)
  634. X                     global-mode-string))))))))
  635. X
  636. X
  637. X;; Misc
  638. X
  639. X(setq auto-mode-alist (append auto-mode-alist
  640. X                '(("\\.f83$" . forth-mode))))
  641. X
  642. X(defun forth-split ()
  643. X  (interactive)
  644. X  (forth-split-1 "*forth*"))
  645. X
  646. X(defun forth-split-1 (buffer)
  647. X  (if (not (eq (window-buffer) (get-buffer buffer)))
  648. X      (progn
  649. X    (delete-other-windows)
  650. X    (split-window-vertically
  651. X     (/ (* (screen-height) forth-percent-height) 100))
  652. X    (other-window 1)
  653. X    (switch-to-buffer buffer)
  654. X    (goto-char (point-max))
  655. X    (other-window 1))))
  656. X    
  657. X(defun forth-reload ()
  658. X  (interactive)
  659. X  (let ((process (get-process forth-program-name)))
  660. X    (if process (kill-process process t)))
  661. X  (sleep-for-millisecs 100)
  662. X  (forth-mode))
  663. X
  664. X
  665. X;; Special section for forth-help
  666. X
  667. X(defvar forth-help-buffer "*Forth-help*"
  668. X  "Buffer used to display the requested documentation.")
  669. X
  670. X(defvar forth-help-load-path nil
  671. X  "List of directories to search through to find *.doc
  672. X (forth-help-file-suffix) files. Nil means current default directory.
  673. X The specified directories must contain at least one .doc file. If it
  674. X does not and you still want the load-path to scan that directory, create
  675. X an empty file dummy.doc.")
  676. X
  677. X(defvar forth-help-file-suffix "*.doc"
  678. X  "The file names to search for in each directory.")
  679. X
  680. X(setq forth-search-command-prefix "grep -n \"^    [^(]* ")
  681. X(defvar forth-search-command-suffix "/dev/null")
  682. X(defvar forth-grep-error-regexp ": No such file or directory")
  683. X
  684. X(defun forth-function-called-at-point ()
  685. X  "Return the space delimited word a point."
  686. X  (save-excursion
  687. X    (save-restriction
  688. X      (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
  689. X      (skip-chars-backward "^ \t\n" (point-min))
  690. X      (if (looking-at "[ \t\n]")
  691. X      (forward-char 1))
  692. X      (let (obj (p (point)))
  693. X    (skip-chars-forward "^ \t\n")
  694. X    (buffer-substring p (point))))))
  695. X
  696. X(defun forth-help-names-extend-comp (path-list result)
  697. X  (cond ((null path-list) result)
  698. X    ((null (car path-list))
  699. X     (forth-help-names-extend-comp (cdr path-list) 
  700. X           (concat result forth-help-file-suffix " ")))
  701. X    (t (forth-help-names-extend-comp
  702. X        (cdr path-list) (concat result
  703. X                    (expand-file-name (car path-list)) "/"
  704. X                    forth-help-file-suffix " ")))))
  705. X
  706. X(defun forth-help-names-extended ()
  707. X  (if forth-help-load-path
  708. X      (forth-help-names-extend-comp forth-help-load-path "")
  709. X    (error "forth-help-load-path not specified")))
  710. X
  711. X
  712. X(define-key forth-mode-map "\C-hf" 'forth-documentation)
  713. X
  714. X(defun forth-documentation (function)
  715. X  "Display the full documentation of FORTH word."
  716. X  (interactive
  717. X   (let ((fn (forth-function-called-at-point))
  718. X     (enable-recursive-minibuffers t)         
  719. X     search-list
  720. X     val)
  721. X     (setq val (read-string (format "Describe forth word (default %s): " fn)))
  722. X     (list (if (equal val "") fn val))))
  723. X  (forth-get-doc (concat forth-search-command-prefix
  724. X             (grep-regexp-quote (concat function " ("))
  725. X             "[^)]*\-\-\" " (forth-help-names-extended)
  726. X             forth-search-command-suffix))
  727. X  (message "C-x C-m switches back to the forth interaction window"))
  728. X
  729. X(defun forth-get-doc (command)
  730. X  "Display the full documentation of command."
  731. X  (let ((curwin (get-buffer-window (window-buffer)))
  732. X    reswin
  733. X    pointmax)
  734. X    (with-output-to-temp-buffer forth-help-buffer
  735. X      (progn
  736. X    (call-process "sh" nil forth-help-buffer t "-c" command)
  737. X    (setq reswin (get-buffer-window forth-help-buffer))))
  738. X    (setq reswin (get-buffer-window forth-help-buffer))
  739. X    (select-window reswin)
  740. X    (save-excursion
  741. X      (goto-char (setq pointmax (point-max)))
  742. X      (insert "--------------------\n\n"))
  743. X    (let (fd doc) 
  744. X      (while (setq fd (forth-get-file-data pointmax))
  745. X    (setq doc (forth-get-doc-string fd))
  746. X    (save-excursion
  747. X      (goto-char (point-max))
  748. X      (insert (substring (car fd) (string-match "[^/]*$" (car fd)))
  749. X          ":\n\n" doc "\n")))
  750. X      (if (not doc)
  751. X      (progn (goto-char (point-max)) (insert "Not found"))))
  752. X    (select-window curwin)))
  753. X  
  754. X(defun forth-skip-error-lines ()
  755. X  (let ((lines 0))
  756. X    (save-excursion
  757. X      (while (re-search-forward forth-grep-error-regexp nil t)
  758. X    (beginning-of-line)
  759. X    (forward-line 1)
  760. X    (setq lines (1+ lines))))
  761. X    (forward-line lines)))
  762. X
  763. X(defun forth-get-doc-string (fd)
  764. X  "Find file (car fd) and extract documentation from line (nth 1 fd)."
  765. X  (let (result)
  766. X    (save-window-excursion
  767. X      (find-file (car fd))
  768. X      (goto-line (nth 1 fd))
  769. X      (if (not (eq (nth 1 fd) (1+ (count-lines (point-min) (point)))))
  770. X      (error "forth-get-doc-string: serious error"))
  771. X      (if (not (re-search-backward "\n[\t ]*\n" nil t))
  772. X      (goto-char (point-min))
  773. X    (goto-char (match-end 0)))
  774. X      (let ((p (point)))
  775. X    (if (not (re-search-forward "\n[\t ]*\n" nil t))
  776. X        (goto-char (point-max)))
  777. X    (setq result (buffer-substring p (point))))
  778. X      (bury-buffer (current-buffer)))
  779. X    result))
  780. X
  781. X(defun forth-get-file-data (limit)
  782. X  "Parse grep output and return '(filename line#) list. Return nil when
  783. X passing limit."
  784. X  (forth-skip-error-lines)
  785. X  (if (< (point) limit)
  786. X      (let ((result (forth-get-file-data-cont limit)))
  787. X    (forward-line 1)
  788. X    (beginning-of-line)
  789. X    result)))
  790. X
  791. X(defun forth-get-file-data-cont (limit)
  792. X  (let (result)
  793. X    (let ((p (point)))
  794. X      (skip-chars-forward "^:")
  795. X      (setq result (buffer-substring p (point))))
  796. X    (if (< (point) limit)
  797. X    (let ((p (1+ (point))))
  798. X      (forward-char 1)
  799. X      (skip-chars-forward "^:")
  800. X      (list result (string-to-int (buffer-substring p (point))))))))
  801. X
  802. X(defun grep-regexp-quote (str)
  803. X  (let ((i 0) (m 1) (res ""))
  804. X    (while (/= m 0)
  805. X      (setq m (string-to-char (substring str i)))
  806. X      (if (/= m 0)
  807. X      (progn
  808. X        (setq i (1+ i))
  809. X        (if (string-match (regexp-quote (char-to-string m))
  810. X                  ".*\\^$[]")
  811. X        (setq res (concat res "\\")))
  812. X        (setq res (concat res (char-to-string m))))))
  813. X    res))
  814. X
  815. X
  816. X(define-key forth-mode-map "\C-x\C-e" 'forth-compile)
  817. X(define-key forth-mode-map "\C-x\C-n" 'next-error)
  818. X(require 'compile "compile")
  819. X
  820. X(defvar forth-compile-command "forth ")
  821. X(defvar forth-compilation-window-percent-height 30)
  822. X
  823. X(defun forth-compile (command)
  824. X  (interactive (list (setq forth-compile-command (read-string "Compile command: " forth-compile-command))))
  825. X  (forth-split-1 "*compilation*")
  826. X  (setq ctools-compile-command command)
  827. X  (compile1 ctools-compile-command "No more errors"))
  828. X
  829. X
  830. END_OF_src/forth.el
  831. if test 27117 -ne `wc -c <src/forth.el`; then
  832.     echo shar: \"src/forth.el\" unpacked with wrong size!
  833. fi
  834. # end of overwriting check
  835. fi
  836. echo shar: End of archive 5 \(of 6\).
  837. cp /dev/null ark5isdone
  838. MISSING=""
  839. for I in 1 2 3 4 5 6 ; do
  840.     if test ! -f ark${I}isdone ; then
  841.     MISSING="${MISSING} ${I}"
  842.     fi
  843. done
  844. if test "${MISSING}" = "" ; then
  845.     echo You have unpacked all 6 archives.
  846.     rm -f ark[1-9]isdone
  847. else
  848.     echo You still need to unpack the following archives:
  849.     echo "        " ${MISSING}
  850. fi
  851. ##  End of shell archive.
  852. exit 0
  853.