Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

672 lines
28 KiB

4 years ago
  1. ;;; ess-mode.el -- Emacs Speaks Statistics root mode. -*- lexical-binding: t; -*-
  2. ;;
  3. ;; Copyright (C) 1994-2018 ESS Core Team
  4. ;; Maintainer: ESS-core <ESS-core@r-project.org>
  5. ;;
  6. ;; Keywords: languages
  7. ;;
  8. ;; This file is part of ESS
  9. ;;
  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. ;;
  15. ;; This file is distributed in the hope that it will be useful,
  16. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ;; GNU General Public License for more details.
  19. ;;
  20. ;; A copy of the GNU General Public License is available at
  21. ;; https://www.r-project.org/Licenses/
  22. ;;
  23. ;;; Commentary:
  24. ;;
  25. ;;; Code:
  26. (require 'ess)
  27. (eval-when-compile
  28. (require 'cl-lib)
  29. (require 'subr-x))
  30. (require 'ess-inf)
  31. ;; Silence the byte compiler
  32. (declare-function run-ess-r "ess-r-mode" (&optional start-args))
  33. (declare-function S+ "ess-sp6-d" (&optional proc-name))
  34. (declare-function SAS "ess-sas-d" ())
  35. ;; FIXME:This one should not be necessary
  36. (declare-function ess-display-help-on-object "ess-help" (object &optional command))
  37. ;; ESS mode
  38. ;; Major mode definition
  39. ;;*;; Hooks
  40. (defcustom ess-mode-hook nil
  41. "Hook for customizing ESS each time it is entered."
  42. :group 'ess-hooks
  43. :type 'hook)
  44. (defvar ess-mode-map
  45. (let ((map (make-sparse-keymap)))
  46. (define-key map [remap yank] #'ess-yank)
  47. (define-key map "\C-c\C-r" #'ess-eval-region)
  48. (define-key map "\C-c\M-r" #'ess-eval-region-and-go)
  49. (define-key map "\C-c\C-b" #'ess-eval-buffer)
  50. (define-key map "\C-c\M-b" #'ess-eval-buffer-and-go)
  51. (define-key map (kbd "C-c C-<up>") #'ess-eval-buffer-from-beg-to-here)
  52. (define-key map (kbd "C-c C-<down>") #'ess-eval-buffer-from-here-to-end)
  53. (define-key map "\C-c\C-f" #'ess-eval-function)
  54. (define-key map "\C-c\M-f" #'ess-eval-function-and-go)
  55. (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step)
  56. (define-key map "\C-c\C-p" #'ess-eval-paragraph-and-step)
  57. (define-key map "\C-c\M-p" #'ess-eval-paragraph-and-go)
  58. (define-key map "\C-\M-x" #'ess-eval-region-or-function-or-paragraph)
  59. (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step)
  60. (define-key map "\C-c\C-j" #'ess-eval-line)
  61. (define-key map [(control return)] #'ess-eval-region-or-line-visibly-and-step)
  62. (define-key map "\C-c\M-j" #'ess-eval-line-and-go)
  63. ;; FIXME: The next three can only work in S/R - mode
  64. (define-key map "\C-\M-a" #'ess-goto-beginning-of-function-or-para)
  65. (define-key map "\C-\M-e" #'ess-goto-end-of-function-or-para)
  66. (define-key map "\C-xnd" #'ess-narrow-to-defun-or-para)
  67. (define-key map "\C-xnf" #'ess-narrow-to-defun-or-para)
  68. (define-key map "\C-c\C-z" #'ess-switch-to-inferior-or-script-buffer)
  69. (define-key map "\C-c\C-l" #'ess-load-file)
  70. ;;; Make an alias because C-c C-l is taken up by comint in inferiors
  71. (define-key map "\C-c\M-l" #'ess-load-file)
  72. (define-key map "\C-c\C-v" #'ess-display-help-on-object)
  73. (define-key map "\C-c\C-s" #'ess-switch-process)
  74. (define-key map "\C-c\C-k" #'ess-force-buffer-current)
  75. (define-key map "\C-c`" #'ess-show-traceback)
  76. (define-key map [(control ?c) ?~] #'ess-show-call-stack)
  77. (define-key map "\C-\M-q" #'ess-indent-exp)
  78. (define-key map "{" #'skeleton-pair-insert-maybe)
  79. (define-key map "}" #'skeleton-pair-insert-maybe)
  80. (define-key map "\C-\M-h" #'ess-mark-function-or-para)
  81. (define-key map "\t" #'ess-indent-or-complete)
  82. (define-key map "\C-c\C-q" #'ess-quit)
  83. (define-key map "\M-\r" #'ess-use-this-dir)
  84. (define-key map "," #'ess-smart-comma)
  85. (define-key map "\C-c\C-d" 'ess-doc-map)
  86. (define-key map "\C-c\C-e" 'ess-extra-map)
  87. (define-key map "\C-c\C-t" 'ess-dev-map)
  88. map)
  89. "Keymap for `ess-mode'.")
  90. ;; Redefine substituted commands
  91. (substitute-key-definition 'indent-new-comment-line
  92. 'ess-indent-new-comment-line
  93. ess-mode-map global-map)
  94. (defvar ess-extra-map
  95. (let (ess-extra-map)
  96. (define-prefix-command 'ess-extra-map)
  97. (define-key ess-extra-map "\C-d" #'ess-dump-object-into-edit-buffer)
  98. (define-key ess-extra-map "d" #'ess-dump-object-into-edit-buffer)
  99. (define-key ess-extra-map "\C-e" #'ess-execute)
  100. (define-key ess-extra-map "e" #'ess-execute)
  101. (define-key ess-extra-map "\C-i" #'ess-install-library)
  102. (define-key ess-extra-map "i" #'ess-install-library)
  103. (define-key ess-extra-map "\C-l" #'ess-load-library)
  104. (define-key ess-extra-map "l" #'ess-load-library)
  105. (define-key ess-extra-map "\C-r" #'inferior-ess-reload)
  106. (define-key ess-extra-map "r" #'inferior-ess-reload)
  107. (define-key ess-extra-map "\C-s" #'ess-set-style)
  108. (define-key ess-extra-map "s" #'ess-set-style)
  109. (define-key ess-extra-map "\C-t" #'ess-build-tags-for-directory)
  110. (define-key ess-extra-map "t" #'ess-build-tags-for-directory)
  111. (define-key ess-extra-map "\C-w" #'ess-execute-screen-options)
  112. (define-key ess-extra-map "w" #'ess-execute-screen-options)
  113. (define-key ess-extra-map "/" #'ess-set-working-directory)
  114. ess-extra-map)
  115. "ESS extra map.")
  116. (easy-menu-define
  117. ess-mode-menu ess-mode-map
  118. "Menu for use in `ess-mode'."
  119. '("ESS" ; ESS-mode
  120. ["Load file" ess-load-file t]
  121. ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t]
  122. ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t]
  123. ["Eval region | line" ess-eval-region-or-line-visibly-and-step t]
  124. ["Enter expression" ess-execute t]
  125. ;; sub menus
  126. "------"
  127. ("Process"
  128. ["Goto end of process buffer" ess-switch-to-end-of-ESS t]
  129. ["Switch to process buffer" ess-switch-to-inferior-or-script-buffer t]
  130. ["Switch process" ess-switch-process t]
  131. ;; ["Recreate R and S versions known to ESS" (ess-r-s-versions-creation+menu) t]
  132. ("Start Process"
  133. ["R" R :help "Start a new R process" :active t]
  134. ["S" S :help "Start a new S process" :active t]
  135. ["Sqpe" Sqpe ess-microsoft-p] ;; :help "Start a new Sqpe process" :active t
  136. ["S+6-exisiting" S+6-existing ess-microsoft-p] ;; :help "Access an existing S process" :active t
  137. ["SAS" SAS-menu t] ;; :help "Start a new SAS process" :active t
  138. ;; The following menu item "Other" is a place-holder that will
  139. ;; be replaced with the other versions of R and Sqpe that can be run.
  140. ;; See `ess-r-define-runners' and ess-site.el
  141. ("Other"
  142. ["No other R or Sqpe versions" nil nil])
  143. ["About"
  144. (ess-goto-info "Starting up") t]
  145. ;; :help "Read about starting a new ESS process" :active t]
  146. )
  147. ("Eval visibly "
  148. :filter ess--generate-eval-visibly-submenu)
  149. ["Quit process" ess-quit t]
  150. ["Reload process" inferior-ess-reload t])
  151. "------"
  152. ("ESS Eval"
  153. ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t]
  154. ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t]
  155. ["Eval region | line & step" ess-eval-region-or-line-visibly-and-step t]
  156. "-----"
  157. ["Eval buffer" ess-eval-buffer t]
  158. ["Eval buffer till here" ess-eval-buffer-from-beg-to-here t]
  159. ["Eval buffer from here" ess-eval-buffer-from-here-to-end t]
  160. ["Eval region" ess-eval-region t]
  161. ["Eval function" ess-eval-function t]
  162. ["Eval line" ess-eval-line t]
  163. ["Eval line & step" ess-eval-line-and-step t]
  164. ["Eval paragraph" ess-eval-paragraph t]
  165. ["Eval paragraph & step" ess-eval-paragraph-and-step t]
  166. ["About" (ess-goto-info "Evaluating code") t]
  167. )
  168. ("Eval and Go"
  169. ["Eval buffer" ess-eval-buffer-and-go t]
  170. ["Eval region" ess-eval-region-and-go t]
  171. ["Eval function" ess-eval-function-and-go t]
  172. ["Eval line" ess-eval-line-and-go t]
  173. ["Eval paragraph" ess-eval-paragraph-and-go t]
  174. ["About" (ess-goto-info "Evaluating code") t]
  175. )
  176. ("Motion"
  177. ["Beginning of function or para" ess-goto-beginning-of-function-or-para t]
  178. ["End of function or para" ess-goto-end-of-function-or-para t]
  179. "-----"
  180. ["Backward list" backward-list t]
  181. ["Forward list" forward-list t]
  182. ["Next parenthesis" down-list t]
  183. ["Enclosing parenthesis" backward-up-list t]
  184. ["Backward sexp" backward-sexp t]
  185. ["Forward sexp" forward-sexp t]
  186. ["About" (Info-goto-node "(Emacs)Lists") t]
  187. )
  188. ("ESS Edit"
  189. ["Edit new object" ess-dump-object-into-edit-buffer t]
  190. ["Complete Filename" comint-replace-by-expanded-filename t]
  191. ["Complete File or Object" ess-indent-or-complete t]
  192. ["Kill sexp" kill-sexp t]
  193. ["Mark function" ess-mark-function-or-para t]
  194. ["Indent expression" ess-indent-exp t]
  195. ["Indent line" ess-indent-command t]
  196. ["Toggle Auto-Fill Mode" auto-fill-mode t]
  197. ["Undo" undo t]
  198. ["About" (ess-goto-info "Edit buffer") t]
  199. )
  200. "------"
  201. ("start-dev" :visible nil)
  202. ("end-dev" :visible nil)
  203. "------"
  204. ("Font Lock"
  205. :active ess-font-lock-keywords
  206. :filter ess--generate-font-lock-submenu)
  207. "------"
  208. ["Describe" describe-mode t]
  209. ["About editing" (ess-goto-info "Editing") t]
  210. ["Read ESS info" (ess-goto-info "") t]
  211. ["Send bug report" ess-submit-bug-report t]))
  212. ;;;###autoload
  213. (define-derived-mode ess-mode prog-mode "ESS"
  214. "Major mode for editing ESS source.
  215. Optional arg ALIST describes how to customize the editing mode.
  216. Optional arg PROC-NAME is name of associated inferior process.
  217. \\{ess-mode-map}
  218. You can send text to the inferior ESS process from other buffers containing
  219. ESS source.
  220. `ess-eval-region' sends the current region to the ESS process.
  221. `ess-eval-buffer' sends the current buffer to the ESS process.
  222. `ess-eval-function' sends the current function to the ESS process.
  223. `ess-eval-line' sends the current line to the ESS process.
  224. `ess-switch-to-ESS' switches the current buffer to the ESS process buffer.
  225. `ess-switch-to-end-of-ESS' switches the current buffer to the ESS process
  226. buffer and puts point at the end of it.
  227. `ess-eval-region-and-go', `ess-eval-buffer-and-go',
  228. `ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S
  229. process buffer after sending their text.
  230. `ess-load-file' sources a file of commands to the ESS process.
  231. \\[ess-indent-command] indents for ESS code.
  232. \\[backward-delete-char-untabify] converts tabs to spaces as it moves back.
  233. Comments are indented in a similar way to Emacs-lisp mode:
  234. `###' beginning of line
  235. `##' the same level of indentation as the code
  236. `#' the same column on the right, or to the right of such a
  237. column if that is not possible.(default value 40).
  238. \\[indent-for-comment] command automatically inserts such a
  239. `#' in the right place, or aligns such a comment if it is
  240. already inserted.
  241. \\[ess-indent-exp] command indents each line of the syntactic unit following point.
  242. Variables controlling indentation style:
  243. `ess-indent-offset'
  244. Indentation of ESS statements within surrounding block.
  245. The surrounding block's indentation is the indentation of the line on
  246. which the open-brace appears.
  247. `ess-offset-block'
  248. Indentation of blocks opened with curly braces or anonymous parentheses.
  249. `ess-offset-arguments'
  250. Indentation of function arguments or bracket indices.
  251. `ess-offset-arguments-newline'
  252. Indentation of function arguments or bracket indices when the opening
  253. delimiter is immediately followed by a newline.
  254. `ess-offset-continued'
  255. Indentation style for continued statements.
  256. `ess-align-nested-calls'
  257. Functions whose nested calls should be aligned.
  258. `ess-align-arguments-in-calls'
  259. Calls in which arguments should be aligned.
  260. `ess-align-continuations-in-calls'
  261. Whether ignore indentation after an operator in calls
  262. `ess-align-blocks'
  263. Blocks that should always be aligned vertically.
  264. `ess-indent-from-lhs'
  265. Whether function calls given as argument should be indented from the
  266. parameter name.
  267. `ess-indent-from-chain-start'
  268. Whether to indent arguments from the first of several consecutive calls.
  269. `ess-indent-with-fancy-comments'
  270. Non-nil means distinguish between #, ##, and ### for indentation.
  271. Furthermore, \\[ess-set-style] command enables you to set up predefined ess-mode
  272. indentation style. See `ess-style-alist' for predefined styles."
  273. :group 'ess
  274. ;; TODO: get rid of these and rely on modes to set variables properly
  275. (when-let ((alist (buffer-local-value 'ess-local-customize-alist (current-buffer))))
  276. (ess-setq-vars-local alist))
  277. (when-let ((alist ess-mode-editing-alist))
  278. (ess-setq-vars-local alist))
  279. ;; Keep <tabs> out of the code.
  280. (setq-local indent-tabs-mode nil)
  281. (setq mode-line-process
  282. '(" ["
  283. (:eval (ess--get-mode-line-indicator))
  284. ess--local-mode-line-process-indicator
  285. "]"))
  286. (add-hook 'ess-idle-timer-functions 'ess-synchronize-dirs nil 'local))
  287. (defun ess--get-mode-line-indicator ()
  288. "Get `ess--mode-line-process-indicator' from process buffer.
  289. Internal function to be used for dynamic mode-line display in
  290. `ess-mode'."
  291. (if ess-local-process-name
  292. (let* ((proc (get-process ess-local-process-name))
  293. (buff (when proc (process-buffer proc))))
  294. (if (and proc (buffer-live-p buff))
  295. (with-current-buffer buff (mapcar 'eval ess--mode-line-process-indicator))
  296. "none"))
  297. "none"))
  298. ;;; User commands in ess-mode
  299. (defun ess-install-library (&optional update package)
  300. "Install PACKAGE for current dialect.
  301. With UPDATE, update cached package list."
  302. (interactive "P")
  303. (ess-install-library--override update package))
  304. (cl-defgeneric ess-install-library--override (update package)
  305. "See `ess-install-library' for UPDATE, PACKAGE."
  306. (when update (message "Don't know how to update for %s" ess-dialect))
  307. (error "Cannot install %s, not available for %s" package ess-dialect))
  308. ;; Motion / manipulation commands
  309. (defun ess-goto-beginning-of-function-or-para ()
  310. "If inside a function go to the beginning of it.
  311. Otherwise go to the beginning of paragraph."
  312. (interactive)
  313. (let ((start-pos (point))
  314. beg end)
  315. (beginning-of-defun)
  316. (setq beg (point))
  317. (end-of-defun)
  318. (setq end (point))
  319. (goto-char beg)
  320. (unless (and (< beg start-pos)
  321. (> end start-pos))
  322. (let ((par-pos (save-excursion
  323. (goto-char start-pos)
  324. (forward-comment most-negative-fixnum)
  325. (backward-paragraph)
  326. (forward-comment most-positive-fixnum)
  327. (point))))
  328. (if (< end par-pos)
  329. (goto-char par-pos)
  330. (goto-char beg))))))
  331. (defun ess-goto-end-of-function-or-para ()
  332. "If inside a function go to end of it.
  333. Otherwise go to the end of paragraph."
  334. (interactive)
  335. (let ((pos (point))
  336. beg end)
  337. (end-of-defun)
  338. (setq end (point))
  339. (beginning-of-defun)
  340. (setq beg (point))
  341. (goto-char end)
  342. (when (or (< beg pos)
  343. (> end pos))
  344. (let ((par-pos (save-excursion
  345. (goto-char pos)
  346. (forward-comment most-positive-fixnum)
  347. (forward-paragraph)
  348. (point))))
  349. (when (<= par-pos beg)
  350. (goto-char par-pos))))))
  351. (defun ess-mark-function-or-para ()
  352. "Put mark at end of ESS function, point at beginning."
  353. (interactive)
  354. (ess-goto-beginning-of-function-or-para)
  355. (push-mark (point))
  356. (ess-goto-end-of-function-or-para)
  357. (exchange-point-and-mark))
  358. (define-obsolete-function-alias 'ess-mark-function 'ess-mark-function-or-para "15.09")
  359. (defun ess-narrow-to-defun-or-para ()
  360. "Make text outside current function invisible.
  361. If text is already narrowed, this is removed before narrowing to the
  362. current function."
  363. (interactive)
  364. (save-excursion
  365. (widen)
  366. (let* ((beg (progn (ess-goto-beginning-of-function-or-para)
  367. (point)))
  368. (end (progn (ess-goto-end-of-function-or-para)
  369. (point))))
  370. (narrow-to-region beg end))))
  371. (define-obsolete-function-alias 'ess-narrow-to-defun 'ess-narrow-to-defun-or-para "15.09")
  372. (defun ess-indent-new-comment-line ()
  373. "Like `indent-new-comment-line' but accounts for roxygen comments."
  374. (interactive)
  375. (cond ((and (fboundp 'ess-roxy-indent-new-comment-line)
  376. (string= ess-dialect "R"))
  377. (ess-roxy-indent-new-comment-line))
  378. (t
  379. (indent-new-comment-line))))
  380. ;;; Formatting / indentation
  381. (defvar-local ess--installed-style-vars nil
  382. "A cons of the form (STYLE . VARS).
  383. VARS is a list of all style vars which were not set explicitly to
  384. buffer local values by the user in mode hooks.")
  385. (defun ess-set-style (&optional style _quiet)
  386. "Set up the `ess-mode' style variables from the `ess-style' variable.
  387. If STYLE argument is given, use that instead. It makes the ESS
  388. indentation style variables buffer local. QUIET is for backward
  389. compatibility and is ignored.
  390. In programs, when STYLE is nil, the `ess-style' is installed. In
  391. this case, if `ess-style' is buffer local, all settings are
  392. overwritten, otherwise only those settings which are not already
  393. buffer local. For example, `ess-style' is buffer local when it is
  394. set in .dir-locals and thus must have priority over the user
  395. settings in the mode hook."
  396. (interactive
  397. (list (let ((styles (mapcar (lambda (x) (symbol-name (car x)))
  398. ess-style-alist)))
  399. (intern (ess-completing-read
  400. "Set ESS mode indentation style"
  401. styles nil t nil nil ess-style)))))
  402. (let* ((keep-local (and (null style)
  403. (not (local-variable-p 'ess-style))))
  404. (style (or style ess-style))
  405. (style-alist (or (cdr (assq style ess-style-alist))
  406. (error "Bad ESS style: %s" style)))
  407. (vars (if keep-local
  408. ;; Install, but Keep user's buffer-local settings.
  409. (cl-loop for (var . _) in (cdr (assq 'DEFAULT ess-style-alist))
  410. unless (local-variable-p var)
  411. collect var)
  412. (mapcar #'car style-alist))))
  413. (when (called-interactively-p 'any)
  414. (message "Set indentation style to %s" style))
  415. (mapc (lambda (var)
  416. (make-local-variable var)
  417. (set var (cdr (assq var style-alist))))
  418. vars)
  419. style))
  420. (defun ess-indent-command (&optional whole-exp)
  421. "Indent current line as ESS code, or in some cases insert a tab character.
  422. If `tab-always-indent' is non-nil, always indent current line.
  423. Otherwise, indent the current line only if point is at the left
  424. margin or in the line's indentation; otherwise insert a tab. If
  425. given, WHOLE-EXP means indent rigidly all the lines of the
  426. expression starting after point so that this line becomes
  427. properly indented. The relative indentation among the lines of
  428. the expression are preserved.
  429. If in a roxygen block at the beginning of the line with
  430. `ess-roxy-hide-show-p' non-nil, call `ess-roxy-toggle-hiding'
  431. instead of indenting."
  432. (interactive "P")
  433. (cond ((and (fboundp 'ess-roxy-entry-p)
  434. (fboundp 'ess-roxy-toggle-hiding)
  435. (bolp)
  436. (ess-roxy-entry-p)
  437. ess-roxy-hide-show-p)
  438. (ess-roxy-toggle-hiding))
  439. (whole-exp
  440. ;; If arg, always indent this line as S
  441. ;; and shift remaining lines of expression the same amount.
  442. (let ((shift-amt (funcall indent-line-function))
  443. beg end)
  444. (save-excursion
  445. (if tab-always-indent
  446. (beginning-of-line))
  447. (setq beg (point))
  448. (backward-up-list 1)
  449. (forward-list 1)
  450. (setq end (point))
  451. (goto-char beg)
  452. (forward-line 1)
  453. (setq beg (point)))
  454. (if (> end beg)
  455. (indent-code-rigidly beg end shift-amt))))
  456. ((and (not tab-always-indent)
  457. (save-excursion
  458. (skip-chars-backward " \t")
  459. (not (bolp))))
  460. (insert-tab))
  461. (t (funcall indent-line-function))))
  462. (defun ess-indent-or-complete ()
  463. "When region is selected indent the region.
  464. Otherwise, if `tab-always-indent' is 'complete, try to indent, if
  465. code is already indented, complete instead. Also see
  466. `ess-first-tab-never-complete'."
  467. (interactive)
  468. (if (use-region-p)
  469. (indent-region (region-beginning) (region-end))
  470. (let ((shift (let ((indent (current-indentation)))
  471. (ess-indent-command)
  472. (- (current-indentation) indent))))
  473. (when (and (or (equal tab-always-indent 'complete)
  474. ess-tab-complete-in-script)
  475. (numberp shift) ;; can be nil if tab-always-indent is nil
  476. (equal shift 0)
  477. (or (eq last-command 'ess-indent-or-complete)
  478. (null ess-first-tab-never-complete)
  479. (and (eq ess-first-tab-never-complete 'unless-eol)
  480. (looking-at "\\s-*$"))
  481. (and (eq ess-first-tab-never-complete 'symbol)
  482. (not (looking-at "\\w\\|\\s_")))
  483. (and (eq ess-first-tab-never-complete 'symbol-or-paren)
  484. (not (looking-at "\\w\\|\\s_\\|\\s)")))
  485. (and (eq ess-first-tab-never-complete 'symbol-or-paren-or-punct)
  486. (not (looking-at "\\w\\|\\s_\\|\\s)\\|\\s.")))))
  487. (completion-at-point)))))
  488. (defun ess-indent-exp ()
  489. "Indent each line of the ESS grouping following point."
  490. (interactive)
  491. (cond ((and (fboundp 'ess-r-indent-exp)
  492. (string= ess-dialect "R"))
  493. (ess-r-indent-exp))
  494. (t
  495. (save-excursion
  496. (let ((start (point))
  497. (end (ignore-errors (forward-sexp 1) (point))))
  498. (when end
  499. (indent-region start end)))))))
  500. (defun ess-indent-line ()
  501. "Indent current line as ESS code.
  502. Return the amount the indentation changed by."
  503. (declare (obsolete 'indent-line-function "ESS 19.04"))
  504. (funcall indent-line-function))
  505. ;;; Dump Objects
  506. (defun ess-dump-object-into-edit-buffer (object)
  507. "Edit an ESS OBJECT in its own buffer.
  508. Without a prefix argument, this simply finds the file pointed to by
  509. `ess-source-directory'. If this file does not exist, or if a
  510. prefix argument is given, a dump() command is sent to the ESS process to
  511. generate the source buffer."
  512. (interactive
  513. (progn
  514. (ess-force-buffer-current "Process to dump from: ")
  515. (ess-read-object-name "Object to edit")))
  516. (let* ((dirname (file-name-as-directory
  517. (if (stringp ess-source-directory)
  518. ess-source-directory
  519. (with-current-buffer (process-buffer (ess-get-process
  520. ess-local-process-name))
  521. (ess-setq-vars-local ess-local-customize-alist)
  522. (apply ess-source-directory nil)))))
  523. (filename (concat dirname (convert-standard-filename (format ess-dump-filename-template object))))
  524. (old-buff (get-file-buffer filename)))
  525. ;; If the directory doesn't exist, offer to create it
  526. (unless (file-exists-p (directory-file-name dirname))
  527. (if (y-or-n-p (format "Directory %s does not exist. Create it? " dirname))
  528. (make-directory (directory-file-name dirname))
  529. (error "Directory %s does not exist" dirname)))
  530. ;; Three options:
  531. ;; (1) Pop to an existing buffer containing the file in question
  532. ;; (2) Find an existing file
  533. ;; (3) Create a new file by issuing a dump() command to S
  534. ;; Force option (3) if there is a prefix arg
  535. (cond (current-prefix-arg
  536. (ess-dump-object object filename))
  537. (old-buff
  538. (pop-to-buffer old-buff))
  539. ((file-exists-p filename)
  540. (ess-find-dump-file-other-window filename)
  541. (message "Read %s" filename))
  542. (t (ess-dump-object object filename)))))
  543. (defun ess-dump-object (object filename)
  544. "Dump the ESS object OBJECT into file FILENAME."
  545. (unless (file-writable-p filename)
  546. (error "Can't dump %s as %f is not writeable" object filename))
  547. (let ((dump-cmd (format inferior-ess-dump-command object filename)))
  548. ;; Make sure we start fresh
  549. (when (get-file-buffer filename)
  550. (kill-buffer (get-file-buffer filename)))
  551. (ess-command dump-cmd)
  552. (message "Dumped in %s" filename)
  553. (ess-find-dump-file-other-window filename)
  554. ;; PD, 1Apr97
  555. ;;This ensures that the object gets indented according to ess-mode,
  556. ;;not as the R/S deparser does it. At the same time, it gets rid
  557. ;;of the mess generated by sending TAB characters to the readline
  558. ;;functions in R when you eval-buffer-*.
  559. (indent-region (point-min-marker) (point-max-marker) nil)
  560. (set-buffer-modified-p nil) ; no need to safe just because of indenting
  561. ;; Don't make backups for temporary files; it only causes clutter.
  562. ;; The ESS object itself is a kind of backup, anyway.
  563. (unless ess-keep-dump-files
  564. (make-local-variable 'make-backup-files)
  565. (setq make-backup-files nil))
  566. ;; Don't get confirmation to delete dumped files when loading
  567. (when (eq ess-keep-dump-files 'check)
  568. (setq ess-keep-dump-files nil))
  569. ;; Delete the file if necessary
  570. (when ess-delete-dump-files
  571. (delete-file (buffer-file-name)))))
  572. (defun ess-find-dump-file-other-window (filename)
  573. "Find ESS source file FILENAME in another window."
  574. (unless (file-readable-p filename)
  575. (ess-write-to-dribble-buffer
  576. (format "%s does not exist. Bad dump, starting fresh." filename)))
  577. ;; Generate a buffer with the dumped data
  578. (find-file-other-window filename)
  579. (auto-save-mode 1) ; Auto save in this buffer
  580. (when (and ess-function-template
  581. (goto-char (point-max))
  582. (re-search-backward ess-dumped-missing-re nil t))
  583. (replace-match ess-function-template t t)
  584. (set-buffer-modified-p nil) ; Don't offer to save if killed now
  585. (goto-char (point-min))
  586. (ignore-errors
  587. ;; This may fail if there are no opens
  588. (down-list 1))))
  589. ;;; Runners
  590. (defun ess-define-runner (name dialect &optional path)
  591. "Create a function NAME.
  592. This function starts the inferior process with the specified
  593. version. DIALECT can be \"R,\" \"S,\", \"SAS.\" If given, PATH
  594. should be the absolute path to the program. It defaults to NAME."
  595. (let ((name name)
  596. (dialect dialect)
  597. (path path))
  598. (fset (intern name)
  599. (lambda (&optional start-args)
  600. "Start this process version in an inferior ESS buffer.
  601. Function defined using `ess-define-runner'."
  602. (interactive "P")
  603. (cond ((string= dialect "R")
  604. (let ((inferior-ess-r-program (or path name)))
  605. (require 'ess-r-mode)
  606. (run-ess-r start-args)))
  607. ((string= dialect "S")
  608. (let ((inferior-S+-program (or path name)))
  609. (require 'ess-sp6-d)
  610. (S+)))
  611. ((string= dialect "SAS")
  612. (let ((inferior-SAS-program (or path name)))
  613. (require 'ess-sas-d)
  614. (SAS))))))))
  615. (provide 'ess-mode)
  616. ;;; ess-mode.el ends here