gsl-mode-0.1.el 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. ;;; gsl-mode.el --- Major mode for editing GSL.
  2. ;;; Based on a copy of python-mode.el.
  3. ;; Copyright (C) 2005 Sverker Nilsson
  4. ;; Copyright (C) 1992,1993,1994 Tim Peters
  5. ;; Author: 2005 Sverker Nilsson
  6. ;; 1995-1997 Barry A. Warsaw
  7. ;; 1992-1994 Tim Peters
  8. ;; Maintainer: sverker.is@home.se
  9. ;; Created: Jun 20, 2005
  10. ;; Version: 0.1
  11. ;; Last Modified: Nov 23, 2005
  12. ;; Keywords: gsl guppy specification language
  13. ;; This software is provided as-is, without express or implied
  14. ;; warranty. Permission to use, copy, modify, distribute or sell this
  15. ;; software, without fee, for any purpose and by any individual or
  16. ;; organization, is hereby granted, provided that the above copyright
  17. ;; notice and this paragraph appear in all copies.
  18. ;;
  19. ;;; Commentary:
  20. ;; This is a major mode for editing GSL, the Guppy Specifcation Language.
  21. ;;
  22. ;; The following statements, placed in your .emacs file or
  23. ;; site-init.el, will cause this file to be autoloaded, and
  24. ;; gsl-mode invoked, when visiting .gsl files (assuming this file is
  25. ;; in your load-path):
  26. ;;
  27. ;; (autoload 'gsl-mode "gsl-mode" "GSL editing mode." t)
  28. ;; (setq auto-mode-alist
  29. ;; (cons '("\\.gsl$" . gsl-mode) auto-mode-alist))
  30. ;;
  31. ;; (Where you have installed eg by copying gsl-mode-0.1 to gsl-mode.)
  32. ;;; Code:
  33. ;; user definable variables
  34. ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  35. (defvar gsl-mode-hook nil
  36. "*Hook called by `gsl-mode'.")
  37. ;; constants
  38. (defconst gsl-indent-offset 1
  39. "*Indentation increment. This version of gsl-mode only supports 1.")
  40. (defconst gsl-mode-version "0.1"
  41. "`gsl-mode' version number.")
  42. (defconst gsl-help-address "sverker.is@home.se"
  43. "Address accepting submission of bug reports.")
  44. (defun gsl-mode-version ()
  45. "Echo the current version of `gsl-mode' in the minibuffer."
  46. (interactive)
  47. (message "Using `gsl-mode' version %s" gsl-mode-version)
  48. (gsl-keep-region-active))
  49. (defun gsl-submit-bug-report (enhancement-p)
  50. "Submit via mail a bug report on `gsl-mode'.
  51. With \\[universal-argument] just submit an enhancement request."
  52. (interactive
  53. (list (not (y-or-n-p
  54. "Is this a bug report? (hit `n' to send other comments) "))))
  55. (let ((reporter-prompt-for-summary-p (if enhancement-p
  56. "(Very) brief summary: "
  57. t)))
  58. (require 'reporter)
  59. (reporter-submit-bug-report
  60. gsl-help-address ;address
  61. (concat "gsl-mode " gsl-mode-version) ;pkgname
  62. ;; varlist
  63. (if enhancement-p nil
  64. '()
  65. )
  66. nil ;pre-hooks
  67. nil ;post-hooks
  68. "Dear Sverker,") ;salutation
  69. (if enhancement-p nil
  70. (set-mark (point))
  71. (insert
  72. "[Please replace this text with a sufficiently large code sample\n\
  73. and an exact recipe so that I can reproduce your problem. Failure\n\
  74. to do so may mean a greater delay in fixing the bug.]\n\n")
  75. (exchange-point-and-mark)
  76. (gsl-keep-region-active))))
  77. (defun gsl-current-indentation ()
  78. (save-excursion
  79. (beginning-of-line)
  80. (while (looking-at "\\.")
  81. (forward-char 1))
  82. (current-column)))
  83. (defun gsl-compute-indentation ()
  84. (save-excursion
  85. (forward-line -1)
  86. (beginning-of-line)
  87. (while (and (not (looking-at "\\."))
  88. (not (forward-line -1))))
  89. (gsl-current-indentation)))
  90. (defun gsl-outdent-p ()
  91. nil
  92. )
  93. (defun gsl-indent-to (need)
  94. (save-excursion
  95. (beginning-of-line)
  96. (setq change (- need (gsl-current-indentation)))
  97. (if (> change 0)
  98. (insert-char ?. change)
  99. (delete-char (- change)))))
  100. (defun gsl-back-to-indentation ()
  101. (beginning-of-line)
  102. (forward-char (gsl-current-indentation)))
  103. (defun gsl-indent-line (&optional arg)
  104. "Fix the indentation of the current line according to GSL rules.
  105. This function is normally bound to `indent-line-function' so
  106. \\[indent-for-tab-command] will call it."
  107. (interactive "P")
  108. (let* ((ci (current-indentation))
  109. (move-to-indentation-p (<= (current-column) ci))
  110. (need (gsl-compute-indentation)))
  111. (gsl-indent-to need)
  112. (if move-to-indentation-p (gsl-back-to-indentation))))
  113. (defun gsl-keep-region-active ()
  114. ;; do whatever is necessary to keep the region active in XEmacs.
  115. ;; Ignore byte-compiler warnings you might see. Also note that
  116. ;; FSF's Emacs 19 does it differently and doesn't its policy doesn't
  117. ;; require us to take explicit action.
  118. (and (boundp 'zmacs-region-stays)
  119. (setq zmacs-region-stays t)))
  120. (defun gsl-shift-region (start end count)
  121. (save-excursion
  122. (goto-char end) (beginning-of-line) (setq end (point))
  123. (goto-char start) (beginning-of-line) (setq start (point))
  124. (if (> count 0)
  125. (while (< (point) end)
  126. (if (looking-at "\\.")
  127. (progn
  128. (insert-char ?. count)
  129. (setq end (+ end count))))
  130. (forward-line 1)
  131. )
  132. (while (< (point) end)
  133. (if (looking-at "\\.\\.")
  134. (progn
  135. (delete-char (- count))
  136. (setq end (+ end count)))
  137. )
  138. (forward-line 1)
  139. )
  140. )
  141. ))
  142. (defun gsl-shift-region-left (start end &optional count)
  143. "Shift region of GSL code to the left.
  144. The lines from the line containing the start of the current region up
  145. to (but not including) the line containing the end of the region are
  146. shifted to the left, by `gsl-indent-offset' columns.
  147. If a prefix argument is given, the region is instead shifted by that
  148. many columns. With no active region, outdent only the current line.
  149. You cannot outdent the region if any line is already at column zero."
  150. (interactive
  151. (let ((p (point))
  152. (m (mark))
  153. (arg current-prefix-arg))
  154. (if m
  155. (list (min p m) (max p m) arg)
  156. (list p (save-excursion (forward-line 1) (point)) arg))))
  157. (setq count (prefix-numeric-value
  158. (or count gsl-indent-offset)))
  159. ;; if any line starting with dots has less than count+1 dots,
  160. ;; don't shift the region
  161. (save-excursion
  162. (goto-char start)
  163. (while (< (point) end)
  164. (beginning-of-line 1)
  165. (if (looking-at "\\.")
  166. (progn
  167. (setq x 0)
  168. (while (< x count)
  169. (forward-char 1)
  170. (if (not (looking-at "\\."))
  171. (error "Region is at left edge."))
  172. (setq x (+ x 1)))))
  173. (forward-line 1)))
  174. (gsl-shift-region start end (- count))
  175. (gsl-keep-region-active))
  176. (defun gsl-shift-region-right (start end &optional count)
  177. "Shift region of GSL code to the right.
  178. The lines from the line containing the start of the current region up
  179. to (but not including) the line containing the end of the region are
  180. shifted to the right, by `gsl-indent-offset' columns.
  181. If a prefix argument is given, the region is instead shifted by that
  182. many columns. With no active region, indent only the current line."
  183. (interactive
  184. (let ((p (point))
  185. (m (mark))
  186. (arg current-prefix-arg))
  187. (if m
  188. (list (min p m) (max p m) arg)
  189. (list p (save-excursion (forward-line 1) (point)) arg))))
  190. (gsl-shift-region start end (prefix-numeric-value
  191. (or count gsl-indent-offset)))
  192. (gsl-keep-region-active))
  193. (if nil
  194. ()
  195. (setq gsl-mode-map (make-sparse-keymap))
  196. (define-key gsl-mode-map "\C-c<" 'gsl-shift-region-left)
  197. (define-key gsl-mode-map "\C-c\C-l" 'gsl-shift-region-left)
  198. (define-key gsl-mode-map "\C-c>" 'gsl-shift-region-right)
  199. (define-key gsl-mode-map "\C-c\C-r" 'gsl-shift-region-right)
  200. (define-key gsl-mode-map "\C-c?" 'gsl-describe-mode)
  201. (define-key gsl-mode-map "\C-c\C-b" 'gsl-submit-bug-report)
  202. (define-key gsl-mode-map "\C-c\C-v" 'gsl-mode-version)
  203. )
  204. ;;;###autoload
  205. (defun gsl-mode ()
  206. "Major mode for editing GSL files.
  207. To submit a problem report, enter `\\[gsl-submit-bug-report]' from a
  208. `gsl-mode' buffer. Do `\\[gsl-describe-mode]' for detailed documentation.
  209. This mode knows about GSL dotted indentation.
  210. Paragraphs are separated by blank lines only.
  211. COMMANDS
  212. \\{gsl-mode-map}
  213. "
  214. (interactive)
  215. ;; set up local variables
  216. (kill-all-local-variables)
  217. (make-local-variable 'indent-line-function)
  218. (setq major-mode 'gsl-mode
  219. mode-name "GSL"
  220. indent-line-function 'gsl-indent-line
  221. )
  222. (use-local-map gsl-mode-map)
  223. ;; run the mode hook
  224. (run-hooks 'gsl-mode-hook)
  225. )
  226. ;; Documentation functions
  227. ;; dump the long form of the mode blurb; does the usual doc escapes,
  228. ;; plus lines of the form ^[vc]:name$ to suck variable & command docs
  229. ;; out of the right places, along with the keys they're on & current
  230. ;; values
  231. (defun gsl-dump-help-string (str)
  232. (with-output-to-temp-buffer "*Help*"
  233. (let ((locals (buffer-local-variables))
  234. funckind funcname func funcdoc
  235. (start 0) mstart end
  236. keys )
  237. (while (string-match "^%\\([vc]\\):\\(.+\\)\n" str start)
  238. (setq mstart (match-beginning 0) end (match-end 0)
  239. funckind (substring str (match-beginning 1) (match-end 1))
  240. funcname (substring str (match-beginning 2) (match-end 2))
  241. func (intern funcname))
  242. (princ (substitute-command-keys (substring str start mstart)))
  243. (cond
  244. ((equal funckind "c") ; command
  245. (setq funcdoc (documentation func)
  246. keys (concat
  247. "Key(s): "
  248. (mapconcat 'key-description
  249. (where-is-internal func py-mode-map)
  250. ", "))))
  251. ((equal funckind "v") ; variable
  252. (setq funcdoc (documentation-property func 'variable-documentation)
  253. keys (if (assq func locals)
  254. (concat
  255. "Local/Global values: "
  256. (prin1-to-string (symbol-value func))
  257. " / "
  258. (prin1-to-string (default-value func)))
  259. (concat
  260. "Value: "
  261. (prin1-to-string (symbol-value func))))))
  262. (t ; unexpected
  263. (error "Error in py-dump-help-string, tag `%s'" funckind)))
  264. (princ (format "\n-> %s:\t%s\t%s\n\n"
  265. (if (equal funckind "c") "Command" "Variable")
  266. funcname keys))
  267. (princ funcdoc)
  268. (terpri)
  269. (setq start end))
  270. (princ (substitute-command-keys (substring str start))))
  271. (print-help-return-message)))
  272. (defun gsl-describe-mode ()
  273. "Dump long form of gsl-mode docs."
  274. (interactive)
  275. (gsl-dump-help-string "Major mode for editing GSL files.
  276. Knows about GSL indentation.
  277. KINDS OF LINES
  278. Each physical line in the file is either a `markup line'
  279. (the line starts with a dot character '.') or a `text line'
  280. (the line starts with some other character). Text lines starting
  281. with a dot may be entered by quoting by a backslash ('\\')).
  282. INDENTATION
  283. Unlike most programming languages, GSL uses indentation, and only
  284. indentation, to specify block structure. Unlike other programming
  285. languages the indentation is not based on blanks but on another
  286. special character; currently this is fixed to be the '.' character.
  287. The indentation that can be supplied automatically by GSL-mode is
  288. just a guess: only you know the block structure you intend, so only
  289. you can supply correct indentation.
  290. Primarily for entering new code:
  291. \t\\[indent-for-tab-command]\t indent line appropriately
  292. \t\\[newline-and-indent]\t insert newline, then indent
  293. The \\[indent-for-tab-command] and \\[newline-and-indent] keys will indent the current line to reproduce
  294. the same indentation as the closest preceding markup line.
  295. Primarily for reindenting existing code:
  296. \t\\[gsl-shift-region-left]\t shift region left
  297. \t\\[gsl-shift-region-right]\t shift region right
  298. The indentation of the markup lines in the region is changed by +/- 1
  299. or the argument given. Text lines in the region will not be changed.
  300. OTHER COMMANDS
  301. Use \\[gsl-mode-version] to see the current version of gsl-mode.
  302. Use \\[gsl-submit-bug-report] to submit a bug report or enhancement proposal.
  303. This text is displayed via the \\[gsl-describe-mode] command.
  304. HOOKS
  305. Entering GSL mode calls with no arguments the value of the variable
  306. `gsl-mode-hook', if that value exists and is not nil; see the `Hooks'
  307. section of the Elisp manual for details.
  308. "))
  309. (provide 'gsl-mode)
  310. ;;; gsl-mode.el ends here