Klimi's new dotfiles with stow.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

338 行
13 KiB

  1. ;;; ess-sas-d.el --- SAS customization
  2. ;; Copyright (C) 1997--2001 Richard M. Heiberger and A. J. Rossini
  3. ;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin
  4. ;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
  5. ;; Author: Richard M. Heiberger <rmh@temple.edu>
  6. ;; Created: 20 Aug 1997
  7. ;; Maintainer: ESS-core <ESS-core@r-project.org>
  8. ;; Keywords: languages
  9. ;; This file is part of ESS.
  10. ;; This file is free software; you can redistribute it and/or modify
  11. ;; it under the terms of the GNU General Public License as published by
  12. ;; the Free Software Foundation; either version 2, or (at your option)
  13. ;; any later version.
  14. ;; This file is distributed in the hope that it will be useful,
  15. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;; GNU General Public License for more details.
  18. ;; A copy of the GNU General Public License is available at
  19. ;; https://www.r-project.org/Licenses/
  20. ;;; Commentary:
  21. ;; This file defines all the SAS customizations for ESS behaviors. See
  22. ;; ess-sas-l and ess-sas-a for the underlying general modifications.
  23. ;;; Code:
  24. ;;; Autoloads:
  25. (require 'shell)
  26. (require 'ess-sas-l)
  27. (defcustom SAS-mode-hook nil
  28. "Hook to run when entering SAS mode."
  29. :type 'hook
  30. :group 'ess-sas)
  31. (defvar inferior-SAS-args "-stdio -linesize 80 -noovp -nosyntaxcheck"
  32. "Arguments to use for starting SAS.")
  33. (defvar inferior-SAS-args-temp nil
  34. "Hack variable, needed for args preprocessing.
  35. Better logic needed! (see 2 uses, in this file).")
  36. (defvar SAS-mode-syntax-table
  37. (let ((tab (make-syntax-table)))
  38. (modify-syntax-entry ?\\ "." tab) ;; backslash is punctuation
  39. (modify-syntax-entry ?+ "." tab)
  40. (modify-syntax-entry ?- "." tab)
  41. (modify-syntax-entry ?= "." tab)
  42. (modify-syntax-entry ?% "w" tab)
  43. (modify-syntax-entry ?< "." tab)
  44. (modify-syntax-entry ?> "." tab)
  45. (modify-syntax-entry ?& "w" tab)
  46. (modify-syntax-entry ?| "." tab)
  47. (modify-syntax-entry ?\' "\"" tab)
  48. (modify-syntax-entry ?* ". 23" tab) ; comment character
  49. (modify-syntax-entry ?\; "." tab)
  50. (modify-syntax-entry ?_ "w" tab)
  51. (modify-syntax-entry ?< "." tab)
  52. (modify-syntax-entry ?> "." tab)
  53. (modify-syntax-entry ?/ ". 14" tab) ; comment character
  54. (modify-syntax-entry ?. "w" tab)
  55. tab)
  56. "Syntax table for `SAS-mode'.")
  57. (defun ess-SAS-pre-run-hook (temp-ess-dialect)
  58. "Set up log and list files for interactive SAS."
  59. (let* ((ess-shell-buffer-name-flag (get-buffer "*shell*"))
  60. ess-shell-buffer-name
  61. ;; isn't pretty yet.
  62. ;; ess-local-process-name is defined after this function.
  63. ;; it needs to be defined prior to this function.
  64. (tmp-procname (let ((ntry 0)
  65. (done nil))
  66. ;; find a non-existent process
  67. (while (not done)
  68. (setq ntry (1+ ntry)
  69. done (not
  70. (get-process (ess-proc-name
  71. ntry
  72. temp-ess-dialect)))))
  73. (ess-proc-name ntry temp-ess-dialect)))
  74. ;; Following was tmp-local-process-name. Stolen from inferior-ess
  75. (ess-sas-lst-bufname (concat "*" tmp-procname ".lst*"))
  76. (ess-sas-log-bufname (concat "*" tmp-procname ".log*"))
  77. (explicit-shell-file-name "/bin/sh")
  78. inferior-SAS-redirect-args
  79. ess-sas-lst
  80. ess-sas-log)
  81. (ess-write-to-dribble-buffer
  82. (format "(ess-SAS-pre-run-hook 1): ess-lang=%s, ess-dialect=%s, temp-dialect=%s, buf=%s \n"
  83. ess-language
  84. ess-dialect
  85. temp-ess-dialect
  86. (current-buffer)))
  87. ;; If someone is running a *shell* buffer, rename it to avoid
  88. ;; inadvertent nuking.
  89. (if ess-shell-buffer-name-flag
  90. (with-current-buffer "*shell*"
  91. (setq ess-shell-buffer-name
  92. (rename-buffer "*ess-shell-regular*" t))))
  93. ;; Construct the LST buffer for output
  94. (if (get-buffer ess-sas-lst-bufname)
  95. nil
  96. (shell)
  97. (accept-process-output (get-buffer-process (current-buffer)))
  98. (sleep-for 2) ; need to wait, else working too fast!
  99. (setq ess-sas-lst (ess-insert-accept "tty"))
  100. (SAS-listing-mode)
  101. (shell-mode)
  102. (ess-listing-minor-mode t)
  103. (rename-buffer ess-sas-lst-bufname t))
  104. ;; Construct the LOG buffer for output
  105. (if (get-buffer ess-sas-log-bufname)
  106. nil
  107. (shell)
  108. (accept-process-output (get-buffer-process (current-buffer)))
  109. (sleep-for 2) ; need to wait, else working too fast!
  110. (setq ess-sas-log (ess-insert-accept "tty"))
  111. ;(SAS-log-mode)
  112. (shell-mode)
  113. (ess-transcript-minor-mode t)
  114. (rename-buffer ess-sas-log-bufname t))
  115. (setq inferior-SAS-redirect-args (concat " "
  116. ess-sas-lst
  117. " "
  118. ess-sas-log
  119. " ")
  120. inferior-SAS-args-temp (concat inferior-SAS-redirect-args
  121. inferior-SAS-args))
  122. ;; Restore the *shell* buffer
  123. (if ess-shell-buffer-name-flag
  124. (with-current-buffer ess-shell-buffer-name
  125. (rename-buffer "*shell*")))
  126. (delete-other-windows)
  127. (split-window-vertically)
  128. (split-window-vertically)
  129. (switch-to-buffer (nth 2 (buffer-list)))
  130. (other-window 2)
  131. (switch-to-buffer ess-sas-log-bufname)
  132. (split-window-vertically)
  133. (other-window 1)
  134. (switch-to-buffer ess-sas-lst-bufname)
  135. (other-window 2)
  136. ;;workaround
  137. (setq inferior-SAS-program
  138. (concat (file-name-as-directory ess-etc-directory)
  139. "ess-sas-sh-command"))
  140. (setq inferior-ess-program inferior-SAS-program)))
  141. (defun ess-insert-accept (command)
  142. "Submit command to process, get next line."
  143. (interactive)
  144. (goto-char (point-max))
  145. (insert command)
  146. (comint-send-input)
  147. (accept-process-output (get-buffer-process (current-buffer)))
  148. (forward-line -1)
  149. (let* ((beg (point))
  150. (ess-tty-name (progn (end-of-line) (buffer-substring beg (point)))))
  151. (goto-char (point-max))
  152. ess-tty-name))
  153. (defvar SAS-customize-alist
  154. '((ess-local-customize-alist . 'SAS-customize-alist)
  155. (ess-language . "SAS")
  156. (ess-dialect . "SAS")
  157. (inferior-ess-program . inferior-SAS-program)
  158. (ess-help-sec-regex . "^[A-Z. ---]+:$")
  159. (ess-help-sec-keys-alist . " ")
  160. (ess-object-name-db-file . "ess-sas-namedb.el")
  161. (inferior-ess-objects-command . "objects(%d)");;FIXME
  162. (inferior-ess-help-command . "help(\"%s\",pager=\"cat\",window=F)\n");;FIXME
  163. (inferior-ess-exit-command . "endsas;\n")
  164. (ess-loop-timeout . 500000 )
  165. (inferior-ess-primary-prompt . "^")
  166. (inferior-ess-secondary-prompt . "^")
  167. (comint-use-prompt-regexp . t)
  168. (inferior-ess-start-args . inferior-SAS-args-temp)
  169. ;; (ess-pre-run-hook . 'ess-SAS-pre-run-hook)
  170. ;; (ess-local-process-name . nil)
  171. )
  172. "Variables to customize for SAS")
  173. ;;; The functions of interest (mode, inferior mode)
  174. ;;;###autoload
  175. (define-derived-mode SAS-mode ess-mode "[SAS]"
  176. "Major mode for editing SAS source. See `ess-mode' for more help."
  177. :group 'ess-sas
  178. (ess-setq-vars-local SAS-customize-alist)
  179. (setq ess-local-customize-alist SAS-customize-alist)
  180. (setq-local sentence-end ";[\t\n */]*")
  181. (setq-local paragraph-start "^[ \t]*$")
  182. (setq-local paragraph-separate "^[ \t]*$")
  183. (setq-local paragraph-ignore-fill-prefix t)
  184. (setq-local adaptive-fill-mode nil)
  185. (setq-local indent-line-function 'sas-indent-line)
  186. (setq-local comment-start "/*")
  187. (setq-local comment-start-skip "/[*]")
  188. (setq-local comment-end "*/")
  189. (setq-local comment-end-skip "[*]/")
  190. (setq-local comment-column 40)
  191. (setq-local ess-local-process-name nil)
  192. (setq-local tab-stop-list ess-sas-tab-stop-list)
  193. (setq-local font-lock-keywords-case-fold-search t)
  194. ;; Local map settings, AFTER initialization (only if not yet defined)
  195. (unless sas-mode-local-map
  196. (setq sas-mode-local-map (copy-keymap (current-local-map)))
  197. (ess-sas-edit-keys-set ess-sas-edit-keys-toggle)
  198. (if ess-sas-local-unix-keys (ess-sas-local-unix-keys))
  199. (if ess-sas-local-pc-keys (ess-sas-local-pc-keys))
  200. (if ess-sas-global-unix-keys (ess-sas-global-unix-keys))
  201. (if ess-sas-global-pc-keys (ess-sas-global-pc-keys)))
  202. (define-key sas-mode-local-map ";" 'ess-electric-run-semicolon)
  203. (define-key sas-mode-local-map (kbd "\C-c\C-w") 'ess-multi-frame-SAS)
  204. ;; this is a mess
  205. ;; interactive and batch commands share sas-mode-local-map,
  206. ;; but the associated commands are very different
  207. ;; what would be better is two maps like
  208. ;; sas-batch-mode-local-map and sas-interactive-mode-local-map
  209. ;; or smart function definitions that would do the appropriate
  210. ;; thing for either batch or interactive sessions
  211. ;; however, neither of these solutions are planned
  212. ;; therefore, no key definitions can be shared between
  213. ;; batch and interactive at this time, hence the lines that
  214. ;; are commented below: uncomment at your own risk
  215. ;; (define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path)
  216. ;; (define-key sas-mode-local-map "\C-c\C-b" 'ess-sas-submit)
  217. ;; (define-key sas-mode-local-map "\C-c\C-r" 'ess-sas-submit-region)
  218. ;; (define-key sas-mode-local-map "\C-c\C-x" 'ess-sas-goto-log)
  219. ;; (define-key sas-mode-local-map "\C-c\C-y" 'ess-sas-goto-lst)
  220. (use-local-map sas-mode-local-map)
  221. (setq font-lock-defaults
  222. ;; KEYWORDS KEYWORDS-ONLY CASE-FOLD .....
  223. '(SAS-mode-font-lock-defaults nil t)))
  224. ;;;###autoload
  225. (add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode))
  226. ;; rmh Jul 10 2003
  227. (defun ess-electric-run-semicolon (arg)
  228. "Insert character. If the line contains \"run;\" or \"quit;\" and nothing else then indent line."
  229. (interactive "P")
  230. (if ess-sas-edit-keys-toggle (insert ";") (let (insertpos)
  231. (if (and (not arg)
  232. (eolp)
  233. (save-excursion
  234. (skip-chars-backward " \t")
  235. (backward-word 1)
  236. (and (looking-at "run\\|quit")
  237. (progn
  238. (skip-chars-backward " \t")
  239. (bolp)))))
  240. (progn
  241. (insert last-command-event)
  242. (funcall indent-line-function)
  243. (save-excursion
  244. (if insertpos (goto-char (1+ insertpos)))
  245. (delete-char -1))))
  246. (if insertpos
  247. (save-excursion
  248. (goto-char insertpos)
  249. (self-insert-command (prefix-numeric-value arg)))
  250. (self-insert-command (prefix-numeric-value arg))))))
  251. (defun SAS-menu ()
  252. "Start SAS from the menu."
  253. (interactive)
  254. (if ess-microsoft-p
  255. ;; replace with other choices for starting SAS?
  256. (error "SAS cannot be started this way in ESS on Windows.")
  257. (SAS)))
  258. (defun SAS ()
  259. "Call 'SAS', from SAS Institute."
  260. (interactive)
  261. (let* ((temp-dialect "SAS")) ;(cdr (rassoc ess-dialect SAS-customize-alist))))
  262. (ess-write-to-dribble-buffer
  263. (format "(SAS): ess-dial=%s, temp-dial=%s\n"
  264. ess-dialect
  265. temp-dialect))
  266. (ess-SAS-pre-run-hook temp-dialect)
  267. (setq ess-eval-visibly-p nil)
  268. ;; FIXME: `inferior-SAS-args' is defined from
  269. ;; `inferior-SAS-args-temp' in `ess-SAS-pre-run-hook'
  270. (let ((inf-buf (inferior-ess nil SAS-customize-alist)))
  271. (with-current-buffer inf-buf
  272. (use-local-map sas-mode-local-map))
  273. inf-buf)))
  274. (defun ess-multi-frame-SAS ()
  275. "Put running SAS buffers into separate frames.
  276. Load this function M-x load-file essx-sas.el RET.
  277. Then find-file myfile.sas. If myfile.sas is already in a buffer, kill-buffer
  278. it and then find-file it again.
  279. Place the cursor in a myfile.sas buffer. Run SAS with M-x SAS,
  280. Return the cursor to the myfile.sas buffer,
  281. then enter C-c C-w to put *SAS* *SAS.log* *SAS.lst* buffers into
  282. their own frames."
  283. (interactive)
  284. (delete-other-windows)
  285. (with-current-buffer "*SAS*"
  286. (make-frame))
  287. (with-current-buffer "*SAS.log*"
  288. (make-frame))
  289. (with-current-buffer "*SAS.lst*"
  290. (make-frame)))
  291. (defun ess-num-or-zero (arg)
  292. "If a number, then return that number, otherwise return 0."
  293. (or (and (numberp arg) arg) 0))
  294. ; Provide package
  295. (provide 'ess-sas-d)
  296. ;;; ess-sas-d.el ends here