home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / jargon-mode.el < prev    next >
Encoding:
Text File  |  1993-07-07  |  17.0 KB  |  530 lines

  1. ;; jargon-mode.el - Major mode for reading the Jargon File
  2. ;;
  3. ;; Version 0.9
  4. ;;
  5. ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  6. ;; Copyright (C) 1993 Sascha Wildner <swildner@channelz.GUN.de>,
  7. ;;
  8. ;; Authors:
  9. ;;
  10. ;;    Sascha Wildner <swildner@channelz.GUN.de>
  11. ;;    Jonathan Stigelman <Stig@netcom.com>
  12. ;;
  13. ;; Other contributors:
  14. ;;
  15. ;;    Dong-Ping Deng <deng@bunny.rhic.bnl.gov>
  16. ;;    Erik C. Ostrom <eostrom@nic.gac.edu>
  17. ;;    Timo Rinne <tri@cirion.fi>
  18. ;;
  19. ;; This program is free software; you can redistribute it and/or modify
  20. ;; it under the terms of the GNU General Public License as published by
  21. ;; the Free Software Foundation; either version 1, or (at your option)
  22. ;; any later version.
  23. ;;
  24. ;; This program is distributed in the hope that it will be useful,
  25. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27. ;; GNU General Public License for more details.
  28. ;;
  29. ;; The GNU General Public License is available by anonymous ftp from
  30. ;; prep.ai.mit.edu in pub/gnu/COPYING.  Alternately, you can write to
  31. ;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  32. ;; USA.
  33. ;;
  34. ;;
  35. ;; To install, copy jargon-mode.el into your lisp directory, byte-compile it
  36. ;; (M-x byte-compile-file) and put the following lines into your .emacs file:
  37. ;;
  38. ;; (autoload 'jargon-mode "jargon-mode"
  39. ;;           "Major mode for browsing the Jargon File." t)
  40. ;; (setq auto-mode-alist (cons
  41. ;;                        '("[jJ]argon.*\\.\\(txt\\|ascii\\)" . jargon-mode)
  42. ;;                        auto-mode-alist))
  43. ;;
  44. ;;
  45. ;; --- HISTORY ---
  46. ;; 19 Feb 93
  47. ;;        Created jargon.el
  48. ;; 30 Mar 93
  49. ;;        Changed name to jargon-mode.el
  50. ;;        Added installation information
  51. ;; 31 Mar 93
  52. ;;        jargon-next-entry now goes ahead when at preceding colon
  53. ;;        Rebound '<' to jargon-first-entry and '>' to jargon-last-entry
  54. ;;        Added jargon-beginning-of-entry
  55. ;;        Added jargon-next-reference and jargon-prev-reference
  56. ;;        Added default to jargon-chase-reference
  57. ;;        Added prefix argument handling where it makes sense
  58. ;;        Buffer is now made read-only
  59. ;;        Bound scroll-up and scroll-down to <SPC> and <DEL>
  60. ;;        Fixed a bug in jargon-chase-reference (remove TABs and NLs)
  61. ;; 06 Apr 93
  62. ;;        Bound describe-mode to '?'
  63. ;; 11 Apr 93
  64. ;;        Fixed a bug in jargon-chase-reference (sort out double refs)
  65. ;; 14 Apr 93
  66. ;;        Added jargon-output-to-cut-file
  67. ;; 16 Apr 93
  68. ;;        jargon-chase-reference now catches "" input
  69. ;;        Added jargon-quit
  70. ;; 17 Apr 93
  71. ;;        Rebound '?' to jargon-mini-help
  72. ;;        A longer help can now be obtained with describe-mode
  73. ;;        jargon-chase-reference now catches pseudo-entries
  74. ;;        jargon-mode now runs jargon-mode-hook as the last step
  75. ;; 22 Apr 93
  76. ;;        case-fold-search is nil now only when necessary
  77. ;; 26 Apr 93
  78. ;;        Wrote a better documentation string for jargon-mode
  79. ;; 21 May 93
  80. ;;        jargon-prev-entry at the first entry now moves to the top
  81. ;;        jargon-next-entry at the last entry now moves to the bottom
  82. ;; 22 May 93
  83. ;;        jargon-chase-reference now finds the first reference in a file
  84. ;; 27 May 93
  85. ;;        Added jargon-chase-reference-blind and
  86. ;;        jargon-trace-back-references
  87. ;; 31 May 93
  88. ;;        Added jargon-prev-keyword and jargon-next-keyword
  89. ;;
  90. ;; May/June 93    Jonathan Stigelman <Stig@netcom.com>
  91. ;;        
  92. ;;        changed the keybindings around to correspond more to info
  93. ;;              mode and view mode.
  94. ;;
  95. ;;        added narrowwing functionality...  Causes ugliness elsewhere
  96. ;;        because the code could stand to be more modular.
  97. ;;
  98. ;;              tried to reduce some of the redundant code...
  99. ;;              
  100. ;;              added highlighting support for emacs 19 (get my hilit19.el)
  101. ;;        
  102. ;;        eliminated redundant creation of very long completion list
  103. ;;        for jargon-find-entry
  104. ;;
  105. ;;        added jargon-dfs-cut-to-buffer (Depth First Search).
  106. ;;        It's kinda slow...because of missing modularity.
  107. ;;
  108. ;; LCD Archive Entry:
  109. ;; jargon-mode.el|Sascha Wildner|swildner@channelz.GUN.de|
  110. ;; Major mode for reading the Jargon File.|
  111. ;; 28-June-93|0.9|~/modes/jargon-mode.el.Z|
  112.  
  113. (defvar jargon-mode-map nil
  114.   "Local keymap for jargon mode buffers.")
  115.  
  116. (defvar jargon-entry-regexp "^:[^:]+:"
  117.   "Regular expression for recognizing entries.")
  118.  
  119. (defvar jargon-reference-regexp "{[^{}]+}"
  120.   "Regular expression for recognizing references.")
  121.  
  122. (defvar jargon-cut-file (expand-file-name "~/jargon.cut")
  123.   "File where exerpts of the jargon file are placed")
  124.  
  125. (defvar jargon-reference-backtrace nil
  126.   "List to trace back reference jumps.")
  127.  
  128. (defvar jargon-narrow-mode t
  129.   "Buffer is narrowwed to just the entry that you're reading")
  130.  
  131. (defvar jargon-highlight t
  132.   "Buffer is narrowwed to just the entry that you're reading")
  133.  
  134. (if jargon-mode-map
  135.     nil
  136.   (setq jargon-mode-map (make-keymap))
  137.   (suppress-keymap jargon-mode-map)
  138.  
  139.   ; these mimic less(1) (or view-less.el)
  140.   (define-key jargon-mode-map " " 'scroll-up)
  141.   (define-key jargon-mode-map "b" 'scroll-down)
  142.   (define-key jargon-mode-map "g" 'jargon-first-entry)
  143.   (define-key jargon-mode-map "G" 'jargon-last-entry)
  144.   (define-key jargon-mode-map "/" 'isearch-forward)
  145.   (define-key jargon-mode-map "?" 'isearch-backward)
  146.  
  147.   ; these mimic info mode
  148.   (define-key jargon-mode-map "n" 'jargon-next-entry)
  149.   (define-key jargon-mode-map "p" 'jargon-prev-entry)
  150.   (define-key jargon-mode-map "q" 'jargon-quit)
  151.   (define-key jargon-mode-map "h" 'jargon-mini-help)
  152.   (define-key jargon-mode-map "s" 'jargon-find-entry)
  153.   (define-key jargon-mode-map "f" 'jargon-chase-reference-query)
  154.   (define-key jargon-mode-map "l" 'jargon-trace-back-references)
  155.   (define-key jargon-mode-map "u" 'jargon-trace-back-references)
  156.   (define-key jargon-mode-map "\177" 'jargon-trace-back-references)
  157.   (define-key jargon-mode-map "L" 'jargon-clear-trace-back)
  158.  
  159.   ; synonyms and jargon-specific bindings
  160.   (define-key jargon-mode-map "a" 'jargon-beginning-of-entry)
  161.  
  162.   (define-key jargon-mode-map "D" 'jargon-dfs-to-buffer)
  163.   (define-key jargon-mode-map "N" 'jargon-narrow-toggle)
  164.   (define-key jargon-mode-map "w" 'widen)
  165.  
  166.   (define-key jargon-mode-map "c" 'jargon-chase-reference)
  167.   (define-key jargon-mode-map "\r" 'jargon-chase-reference)
  168.  
  169.   (define-key jargon-mode-map "\M-\t" 'jargon-prev-reference)
  170.   (define-key jargon-mode-map "\t" 'jargon-next-reference)
  171.  
  172.   (define-key jargon-mode-map "[" 'jargon-prev-keyword)
  173.   (define-key jargon-mode-map "]" 'jargon-next-keyword)
  174.  
  175.   (define-key jargon-mode-map "o" 'jargon-output-to-cut-file)
  176.   )
  177.  
  178. (defun jargon-beginning-of-entry ()
  179.   "Go to the beginning of the current entry."
  180.   (interactive)
  181.   (beginning-of-line)
  182.   (if (not (looking-at jargon-entry-regexp))
  183.       (re-search-backward jargon-entry-regexp (point-min) 'noerr)))
  184.  
  185. (defun jargon-chase-reference-query ()
  186.   (interactive)
  187.   (jargon-chase-reference 'ask))
  188.  
  189. (defun jargon-slurp-ref (&optional where)
  190.   "get the reference under point"
  191.   (let (default i (opoint (point)))
  192.     (if where (goto-char where))
  193.     (setq default (cond ((looking-at jargon-reference-regexp)
  194.              (buffer-substring (1+ (match-beginning 0))
  195.                        (1- (match-end 0))))
  196.             ((and (save-excursion
  197.                 (search-backward "{" nil t)
  198.                 (looking-at jargon-reference-regexp))
  199.                   (> (match-end 0) (point)))
  200.              (buffer-substring (1+ (match-beginning 0))
  201.                        (1- (match-end 0))))
  202.             (t "")))
  203.     (goto-char opoint)
  204.     (while (setq i (string-match "[ \n\t]+" default i))
  205.       (setq default (concat (substring default 0 i) " "
  206.                 (substring default (match-end 0))))
  207.       (setq i (1+ i)))
  208.     default))
  209.  
  210. (defun jargon-read-ref-complete ()
  211.   (let ((completion-ignore-case nil)
  212.     jargon-narrow-mode jargon-highlight
  213.     completions str end default entry)
  214.     (save-restriction
  215.       (widen)
  216.       (save-excursion
  217.      (jargon-next-entry)
  218.      (setq end (point))
  219.      (jargon-prev-entry)
  220.      (while (re-search-forward jargon-reference-regexp end t)
  221.        (setq str (jargon-slurp-ref (match-beginning 0)))
  222.        (or (member str completions)
  223.            (setq completions (cons (cons str nil) completions))))))
  224.     (if (not completions)
  225.     (error "No references in this entry")
  226.       (setq default (cond ((eq (length completions) 1)
  227.                (car (car completions)))
  228.               (t (jargon-slurp-ref))))
  229.       (while (null entry)
  230.     (setq entry (completing-read "Chase reference: " completions
  231.                      nil t default))
  232.     (if (string= entry "")
  233.         (setq entry nil)))
  234.       entry)))
  235.  
  236. (defun jargon-chase-reference (&optional ask)
  237.   "Follow a reference from the current entry."
  238.   (interactive)
  239.   (let ((entry (if ask
  240.            (jargon-read-ref-complete)
  241.          (jargon-slurp-ref))))
  242.     (setq jargon-reference-backtrace
  243.       (cons (point) jargon-reference-backtrace))
  244.     (jargon-find-entry entry)))
  245.  
  246. (defun jargon-clear-trace-back ()
  247.   (interactive)
  248.   (setq jargon-reference-backtrace nil)
  249.   (message "Reference backtrace cleared."))
  250.  
  251. (defvar jargon-find-completions nil
  252.   "List of completions for searches")
  253.  
  254. (defun jargon-build-completions ()
  255.   (save-excursion
  256.     (save-restriction
  257.       (widen)
  258.       (goto-char (point-min))
  259.       (while (re-search-forward jargon-entry-regexp nil t)
  260.     (setq jargon-find-completions
  261.           (cons (cons (buffer-substring
  262.                (1+ (match-beginning 0))
  263.                (1- (match-end 0))) nil)
  264.             jargon-find-completions)))))
  265.   jargon-find-completions)
  266.  
  267. (defun jargon-find-entry (str)
  268.   "Find a certain entry."
  269.   (interactive
  270.    (let ((completion-ignore-case nil))
  271.      (or jargon-find-completions
  272.      (jargon-build-completions)
  273.      (error "No entries in this buffer"))
  274.      (list (completing-read "Find entry: " jargon-find-completions nil t))))
  275.   (widen)
  276.   (let ((case-fold-search nil)
  277.     (opoint (point)))
  278.     (goto-char (point-min))
  279.     (goto-char (if (re-search-forward (concat "^:" (regexp-quote str)
  280.                           ":") nil t)
  281.            (match-beginning 0)
  282.          opoint)))
  283.   (jargon-narrow))
  284.  
  285. (defun jargon-narrow-toggle ()
  286.   "toggle jargon-narrow-mode"
  287.   (interactive)
  288.   (and jargon-narrow-mode (progn (widen) (recenter)))
  289.   (if (setq jargon-narrow-mode (not jargon-narrow-mode))
  290.       (jargon-narrow)))
  291.  
  292. (defun jargon-narrow ()
  293.   "narrow jargon buffer to just this word's definition"
  294.   (if (or jargon-highlight jargon-narrow-mode)
  295.       (let (p1 p2)
  296.     (save-excursion
  297.       (forward-char)
  298.       (re-search-forward "^\\(= . =\\|:[^:]+:\\)" nil t)
  299.       (beginning-of-line)
  300.       (setq p2 (point))
  301.       (forward-char)
  302.       (re-search-backward jargon-entry-regexp nil t)
  303.       (setq p1 (point)))
  304.     (and jargon-narrow-mode (narrow-to-region p1 p2))
  305.     (if (and jargon-highlight (featurep 'hilit19))
  306.         (hilit-rehighlight-region p1 p2 'quietly)))))
  307.  
  308. (defun jargon-first-entry ()
  309.   "Go to the first entry."
  310.   (interactive)
  311.   (widen)
  312.   (goto-char (point-min))
  313.   (jargon-next-entry))
  314.  
  315. (defun jargon-last-entry ()
  316.   "Go to the last entry."
  317.   (interactive)
  318.   (widen)
  319.   (goto-char (point-max))
  320.   (jargon-prev-entry))
  321.  
  322. (defun jargon-mini-help ()
  323.   "Display some commands in the minibuffer."
  324.   (interactive)
  325.   (message
  326.    "[n]ext, [p]revious, [TAB] next ref, [RET] follow ref, [u]p to last ref, [q]uit"))
  327.  
  328. (defun jargon-next-entry (&optional arg)
  329.   "Go to the next entry.  With arg, do it arg times."
  330.   (interactive "p")
  331.   (widen)
  332.   (or arg (setq arg 1))
  333.   (while (> arg 0)
  334.     (forward-char)
  335.     (if (re-search-forward jargon-entry-regexp (point-max) 0)
  336.     (beginning-of-line))
  337.     (setq arg (1- arg)))
  338.   (jargon-narrow))
  339.  
  340. (defun jargon-next-keyword (&optional arg)
  341.   "Move to the next reference or entry.  With arg, do it arg times."
  342.   (interactive "p")
  343.   (or arg (setq arg 1))
  344.   (while (> arg 0)
  345.     (condition-case nil
  346.     (jargon-next-reference 1)
  347.       (error (jargon-next-entry 1)))
  348.     (setq arg (1- arg))))
  349.  
  350. (defun jargon-next-reference (&optional arg)
  351.   "Move to the next reference in this entry.  With arg, do it arg times."
  352.   (interactive "p")
  353.   (or arg (setq arg 1))
  354.   (let ((end (save-excursion (forward-char)
  355.                  (re-search-forward jargon-entry-regexp
  356.                         (point-max) 'noerr)
  357.                  (beginning-of-line)
  358.                  (point))))
  359.     (while (> arg 0)
  360.       (forward-char)
  361.       (if (re-search-forward jargon-reference-regexp end t)
  362.       (goto-char (match-beginning 0))
  363.     (backward-char)
  364.     (error "No more references in this entry"))
  365.       (setq arg (1- arg)))))
  366.  
  367. (defun jargon-prev-entry (&optional arg)
  368.   "Go to the previous entry.  With arg, do it arg times."
  369.   (interactive "p")
  370.   (widen)
  371.   (or arg (setq arg 1))
  372.   (while (> arg 0)
  373.     (if (re-search-backward jargon-entry-regexp (point-min) 0)
  374.     (beginning-of-line))
  375.     (setq arg (1- arg)))
  376.   (jargon-narrow))
  377.  
  378. (defun jargon-prev-keyword (&optional arg)
  379.   "Move to the previous reference or entry.  With arg, do it arg times."
  380.   (interactive "p")
  381.   (or arg (setq arg 1))
  382.   (while (> arg 0)
  383.     (condition-case nil
  384.     (jargon-prev-reference 1)
  385.       (error (if (not (looking-at jargon-entry-regexp))
  386.          (jargon-prev-entry 1)
  387.            (widen)
  388.            (if (bobp)
  389.            nil
  390.          (backward-char 2)
  391.          (jargon-narrow)
  392.          (setq arg (1+ arg))))))
  393.     (setq arg (1- arg))))
  394.  
  395. (defun jargon-prev-reference (&optional arg)
  396.   "Move to the previous reference in this entry.  With arg, do it arg times."
  397.   (interactive "p")
  398.   (or arg (setq arg 1))
  399.   (let ((beg (save-excursion (re-search-backward jargon-entry-regexp
  400.                          (point-min) 'noerr)
  401.                  (beginning-of-line)
  402.                  (point))))
  403.     (while (> arg 0)
  404.       (if (re-search-backward jargon-reference-regexp beg t)
  405.       (goto-char (match-beginning 0))
  406.     (error "No previous references in this entry"))
  407.       (setq arg (1- arg)))))
  408.  
  409. (defun jargon-read-cutfile-name (prompt)
  410.   (read-file-name
  411.    (concat prompt " (default " (file-name-nondirectory jargon-cut-file) ") ")
  412.    (file-name-directory jargon-cut-file)
  413.    jargon-cut-file))
  414.  
  415. (defun jargon-output-to-cut-file (file-name)
  416.   "Append the current entry to a cut file."
  417.   (interactive (list (jargon-read-cutfile-name "Append entry to cut file:")))
  418.   (save-excursion
  419.     (jargon-beginning-of-entry)
  420.     (setq beg (point))
  421.     (jargon-next-entry)
  422.     (setq end (point))
  423.     (append-to-file beg end file-name)))
  424.  
  425. (defun jargon-cut-to-buffer (buf-name)
  426.   "Append the current entry to a cut file."
  427.   (interactive "BCut to buffer: ")
  428.   (save-excursion
  429.     (jargon-beginning-of-entry)
  430.     (setq beg (point))
  431.     (jargon-next-entry)
  432.     (setq end (point))
  433.     (append-to-buffer buf-name beg end)))
  434.  
  435. (defun jargon-dfs-to-buffer (buffer depth)
  436.   "Do a depth-first elaboration of the current keyword and dump this to buffer"
  437.   (interactive "BRecursive cut-to-buffer: \nnDepth: ")
  438.   (let ((jargon-dfs-visited nil)
  439.     (jargon-dfs-buffer buffer)
  440.     (jargon-dfs-maxdepth depth)
  441.     jargon-narrow-mode jargon-highlight)
  442.     (jargon-dfs-dump 0))
  443.   (jargon-narrow))
  444.  
  445. (defun jargon-dfs-dump (level)
  446.   (jargon-beginning-of-entry)
  447.   (if (memq (point) jargon-dfs-visited)
  448.       nil
  449.     (setq jargon-dfs-visited (cons (point) jargon-dfs-visited))
  450.     (message (buffer-substring (point) (save-excursion (forward-char)
  451.                                (search-forward ":"))))
  452.     (jargon-cut-to-buffer jargon-dfs-buffer)
  453.     (let (done)
  454.       (while (and (< level jargon-dfs-maxdepth) (not done))
  455.     (condition-case nil
  456.         (progn (jargon-next-reference)
  457.            (save-excursion
  458.              (jargon-chase-reference)
  459.              (jargon-dfs-dump (1+ level))))
  460.       (error (setq done t)))))))
  461.  
  462. (defun jargon-trace-back-references ()
  463.   "Trace back reference jumps."
  464.   (interactive)
  465.   (widen)
  466.   (if (null jargon-reference-backtrace)
  467.       (error "No further backtrace.")
  468.     (goto-char (car jargon-reference-backtrace))
  469.     (jargon-narrow)
  470.     (setq jargon-reference-backtrace 
  471.       (cdr jargon-reference-backtrace))))
  472.  
  473. (defun jargon-quit ()
  474.   "Quit reading the Jargon File and select another buffer."
  475.   (interactive)
  476.   (switch-to-buffer (prog1 (other-buffer (current-buffer))
  477.               (bury-buffer (current-buffer)))))
  478.  
  479. (defun jargon-mode ()
  480.   "Major mode for reading the Jargon File.
  481.  
  482. The Jargon File is a huge collection of hacker slang, humor, and folklore which
  483. is currently maintained by Eric S. Raymond <esr@snark.thyrsus.com>.  It's
  484. available for anonymous ftp on prep.ai.mit.edu in the directory pub/gnu.
  485.  
  486. The following commands are available:
  487.  
  488.   \\[jargon-mini-help]    Display quick reference in minibuffer.
  489.  
  490.   \\[jargon-next-entry]    Go to the next entry.
  491.   \\[jargon-prev-entry]    Go to the previous entry.
  492.   \\[jargon-find-entry]    Go to a specific entry.
  493.   \\[jargon-beginning-of-entry]    Go to the beginning of current entry.
  494.  
  495.   \\[jargon-chase-reference-query]    Chase a reference.
  496.   \\[jargon-chase-reference]    Chase a reference w/o confirmation.
  497.   \\[jargon-next-reference]    Go to the next reference
  498.   \\[jargon-prev-reference]    Go to the previous reference.
  499.   \\[jargon-trace-back-references]    Trace back reference jumps.
  500.   \\[jargon-clear-trace-back]    Clear the reference jump backtrace.
  501.  
  502.   \\[jargon-narrow-toggle]    Toggle jargon-narrow-mode
  503.   \\[widen]            Temporarily widen the buffer
  504.  
  505.   \\[jargon-next-keyword]    Next keyword (entry or reference).
  506.   \\[jargon-prev-keyword]    Previous keyword.
  507.   \\[jargon-first-entry]    Go to the first entry.
  508.   \\[jargon-last-entry]    Go to the last entry.
  509.  
  510.   \\[jargon-output-to-cut-file]    Append the current entry to a cut file.
  511.   \\[jargon-quit]    Quit reading the Jargon File.
  512.  
  513. The following variables influence the behavior of jargon-mode:
  514.  
  515. jargon-entry-regexp
  516.     The regular expression used for recognizing entries.
  517.  
  518. jargon-reference-regexp
  519.     The regular expression used for recognizing references.
  520.  
  521.  
  522. Turning on jargon-mode calls the value of the variable jargon-mode-hook with
  523. no args, if that value is non-nil."
  524.   (interactive)
  525.   (setq major-mode 'jargon-mode)
  526.   (setq mode-name "Jargon")
  527.   (setq buffer-read-only t)
  528.   (use-local-map jargon-mode-map)
  529.   (run-hooks 'jargon-mode-hook))
  530.