From: Andreas Gerler Date: Thu, 23 Nov 2023 18:28:00 +0000 (+0100) Subject: update ess X-Git-Url: http://git.bundesbrandschatzamt.de/?a=commitdiff_plain;h=1016c15f48e12a1f018b1b9249c6ab85bd0bef03;p=emacsconfig.git update ess Signed-off-by: Andreas Gerler --- diff --git a/elpa/ess-20191014.1343/.dir-locals.el b/elpa/ess-20191014.1343/.dir-locals.el deleted file mode 100644 index 0cefb6e1..00000000 --- a/elpa/ess-20191014.1343/.dir-locals.el +++ /dev/null @@ -1,11 +0,0 @@ -;;; Directory Local Variables -;;; For more information see (info "(emacs) Directory Variables") - -((nil - (bug-reference-bug-regexp . "#\\(?2:[0-9]+\\)") - (bug-reference-url-format . "https://github.com/emacs-ess/ess/issues/%s") - (sentence-end-double-space)) - (emacs-lisp-mode - (outline-regexp . "\f\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*") - (indent-tabs-mode)) - (ess-r-mode . ((ess-style . RRR)))) diff --git a/elpa/ess-20191014.1343/allnews.info b/elpa/ess-20191014.1343/allnews.info deleted file mode 100644 index 405663f2..00000000 --- a/elpa/ess-20191014.1343/allnews.info +++ /dev/null @@ -1,1933 +0,0 @@ -This is allnews.info, produced by makeinfo version 6.5 from -allnews.texi. - -Changes and New Features in 19.04 (unreleased): - - * ESS[R]: There is a new menu entry for reloading the R process. It - is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same - process name and start arguments that were used to start the - process. - - * iESS: Process runners now return the inferior buffer. Note that - callers of inferior runners should not assume that the current - buffer has been set to the inferior buffer. Instead, use - 'with-current-buffer' with the return value of the inferior. - - * iESS[SAS]: The SAS keymap was only set in iESS buffers called - '*SAS*'. This is now fixed. - - * ESS[R]: Fixed longstanding indentation issues involving '::' and - ':::' operators. - - * Implement a more reliable check for the process busy state. - Background actions such as completion and directory synchronization - should not block the process and should not cause printing of the - extraneous output to the interpreter. - - * Activate 'goto-address-mode' for url and email highlighting in - inferior buffers. - - * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. - Users who liked the previous behavior (i.e. underscore inserting - "<-") should bind 'ess-insert-assign' to the underscore in their - Emacs initialization file. For example, '(define-key - ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key - inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it - in all ESS R buffers. - - * ESS major modes are now defined using 'define-derived-mode'. This - makes ESS major modes respect modern conventions such as having - -mode-hook and -mode-map. Users are encouraged - to place customizations under the appropriate mode. - - * New option ess-auto-width controls setting the width option on - window changes. Users can change it to 'frame, 'window, or an - integer. See the documentation for details. - 'ess-auto-width-visible' controls visibility. - - * ESS now respects 'display-buffer-alist'. Users can now use - 'display-buffer-alist' to manage how and where windows appear. See - *Note (ess)Controlling buffer display:: for more information and - examples. - - * 'ess-roxy-mode' can now be enabled in non-R buffers. This is - primarily intended to support roxygen documentation for cpp - buffers. Preview functionality is not supported outside R buffers. - - * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. - - * 'ess-style' now has effects when set as a file or directory local - variable. - - * 'ess-default-style' is now obsolete, use 'ess-style' instead. - - * Options for 'ess-gen-proc-buffer-name-function' have been renamed. - ess-gen-proc-buffer-name:projectile-or-simple was renamed to - ess-gen-proc-buffer-name:project-or-simple and - ess-gen-proc-buffer-name:projectile-or-directory was renamed to - ess-gen-proc-buffer-name:project-or-directory. As the name - suggests, these now rely on project.el (included with Emacs) rather - than projectile.el, which is a third-party package. - - * ESS[R]: devtools commands ask about saving modified buffers before - running. Users can disable the questioning with - 'ess-save-silently'. - - * ESS[R] help pages now provide links to other help topics. This is - similar with what you would see with, for example - 'options(help_type = ``html'')' but works with the plain-text - version as well. This only works with 'options(useFancyQuotes = - TRUE)' (the default). - - * 'ess-rdired' buffers now derive from tabulated-list-mode. They - should look better and be a bit faster overall. The size column - now displays object sizes in bytes. - - * 'ess-rdired' buffers now auto-update. The frequency is governed by - the new option 'ess-rdired-auto-update-interval'. - - * ESS[R]: 'electric-layout-mode' is now supported. This - automatically inserts a newline after an opening curly brace in R - buffers. To enable it, customize 'ess-r-mode-hook'. - - * ESS[R]: imenu now supports assignment with the equals sign. - - * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. - - * ESS removed support for many unused languages. This includes old - versions of S+, ARC, OMG, VST, and XLS. - - The following have been made obsolete or removed, see their -documentation for more detail: - - * Libraries for literate data analysis are obsolete and not loaded by - default. This includes 'ess-noweb', 'ess-swv', and related - functionality like 'Rnw-mode'. Users are encouraged to switch to - one of several other packages that deal with these modes. For - example, polymode , - , or markdown-mode with edit-indirect - . - - * Support for 'auto-complete' is obsolete. The 'auto-complete' - package is unmaintained and so ESS support is now obsolete. Users - are encouraged to switch to 'company-mode' instead. - - * User options for controlling display of buffers. This includes - 'ess-show-buffer-action', 'inferior-ess-same-window', - 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See - above about ESS respecting 'display-buffer-alist'. - - * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. - Use the Emacs-wide setting of 'tab-always-indent' instead. - - * 'inferior-ess-*-start-file' variables. All modes except Stata did - not respect customization of this variable. In order to load a - file on startup, you should put a function on - 'ess-*-post-run-hook'. - - Bug Fixes in 18.10.3: - * More 'Makefile' fixes, notably installing '*.el's. - - Bug Fixes in 18.10.2: - * ESS[R] Fix namespace evaluation in non-installed packages. - Evaluation is directed into GlobalEnv as originally intended. - * 'Makefile' fixes, notably for 'make install' and including full - docs in the tarballs. - - Bug Fixes in 18.10-1: - * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and - 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave - as the old versions of 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step'. - - Changes and New Features in 18.10: - - * This is the last release to support Emacs older than 25.1. Going - forward, only GNU Emacs 25.1 and newer will be supported. Soon - after this release, support for older Emacs versions will be - dropped from the git master branch. Note that MELPA uses the git - master branch to produce ESS snapshots, so if you are using Emacs < - 25.1 from MELPA and are unable to upgrade, you should switch to - MELPA-stable. - - * ESS now displays the language dialect in the mode-line. So, for - example, R buffers will now show ESS[R] rather than ESS[S]. - - * The ESS manual has been updated and revised. - - * The ESS initialization process has been further streamlined. If - you update the autoloads (which installation from 'package-install' - does), you should not need to '(require 'ess-site)' at all, as - autoloads should automatically load ESS when it is needed (e.g. - the first time an R buffer is opened). In order to defer loading - your ESS config, you may want to do something like - '(with-require-after-load "ess" )' in your Emacs - init file. Users of the popular 'use-package' Emacs package can - now do '(use-package ess :defer t)' to take advantage of this - behavior. *Note (ess)Activating and Loading ESS:: for more - information on this feature. - - * ESS now respects Emacs conventions for keybindings. This means - that The 'C-c [letter]' bindings have been removed. This affects - 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in - 'sas-mode-local-map'; 'C-c f', which was bound to - 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', - which was bound to 'ess-handy-commands' in 'Rd-mode-map', - 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' - - * Functions 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step' now behave consistently with - other evaluation function inside a package. - - * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets - the working directory to the root of the current package including - for example C or C++ files within '/src'). - - * ESS[R]: Long + + prompts in the inferior no longer offset output. - - * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This - strips the entire + + sequence. - - * ESS modes now inherit from 'prog-mode'. In the next release, ESS - modes will use 'define-derived-mode' so that each mode will have - (for example) its own hooks and keymaps. - - * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. - Users need to install the 'lintr' package to use it. Customizable - options include 'ess-use-flymake', 'ess-r-flymake-linters', and - 'ess-r-flymake-lintr-cache'. - - * ESS[R]: Gained support for xref in Emacs 25+. *Note (emacs)Xref:: - - * ESS[R]: The startup screen is cleaner. It also displays the - startup directory with an explicit 'setwd()'. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[R]: 'Makevars' files open with 'makefile-mode'. - - * New variable 'ess-write-to-dribble'. This allows users to disable - the dribble ('*ESS*') buffer if they wish. - - * All of the '*-program-name' variables have been renamed to - '*-program'. Users who previously customized e.g. - 'inferior-ess-R-program-name' will need to update their - customization to 'inferior-ess-R-program'. These variables are - treated as risky variables. - - * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It - provides similar functionality but for any keybinding, not just - '_'. For instance if you bind it to ';', repeated invocations - cycle through between assignment and inserting ';'. - - * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the - documentation for details. New user customization option - 'ess-assign-list' controls which assignment operators are cycled. - - * ESS[R] In remote sessions, the ESSR package is now fetched from - GitHub. - - * Commands that send the region to the inferior process now deal with - rectangular regions. See the documentation of 'ess-eval-region' - for details. This only works on Emacs 25.1 and newer. - - * ESS[R]: Improvements to interacting with iESS in non-R files. - Interaction with inferior process in non-R files within packages - (for instance C or C++ files) has been improved. This is a work in - progress. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in - JAGS mode. - - Many improvements to fontification: - - * Improved customization for faces. ESS now provides custom faces - for (nearly) all faces used and places face customization options - into their own group. Users can customize these options using 'M-x - customize-group RET ess-faces'. - - * Many new keywords were added to 'ess-R-keywords' and - 'ess-R-modifiers'. See the documentation for details. - - * ESS[R]: 'in' is now only fontified when inside a 'for' construct. - This avoids spurious fontification, especially in the output buffer - where 'in' is a common English word. - - * ESS: Font-lock keywords are now generated lazily. That means you - can now add or remove keywords from variables like 'ess-R-keywords' - in your Emacs configuration file after loading ESS (i.e. in the - ':config' section for 'use-package' users). - - * ESS[R]: Fontification of roxygen '@param' keywords now supports - comma-separated parameters. - - * ESS[R]: Certain keywords are only fontified if followed by a - parenthesis. Function-like keywords such as 'if ()' or 'stop()' - are no longer fontified as keyword if not followed by an opening - parenthesis. The same holds for search path modifiers like - 'library()' or 'require()'. - - * ESS[R]: Fixed fontification toggling. Especially certain syntactic - elements such as '%op%' operators and backquoted function - definitions. - - * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. - This command asks with completion for a font-lock group to toggle. - This functionality is equivalent to the font-lock menu. - - Notable bug fixes: - - * 'prettify-symbols-mode' no longer breaks indentation. This is - accomplished by having the pretty symbols occupy the same number of - characters as their non-pretty cousins. You may customize the new - variable 'ess-r-prettify-symbols' to control this behavior. - - * ESS: Inferior process buffers are now always displayed on startup. - Additionally, they don't hang Emacs on failures. - - Obsolete libraries, functions, and variables: - - * The 'ess-r-args.el' library has been obsoleted and will be removed - in the next release. Use 'eldoc-mode' instead, which is on by - default. - - * Functions and options dealing with the smart assign key are - obsolete. The following functions have been made obsolete and will - be removed in the next release of ESS: 'ess-smart-S-assign', - 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', - 'ess-disable-smart-S-assign'. - - The variable 'ess-smart-S-assign-key' is now deprecated and will be - removed in the next release. If you would like to continue using - '_' for inserting assign in future releases, please bind - 'ess-insert-assign' in 'ess-mode-map' the normal way. - - * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. - Use 'ess-s-versions' instead. You may pass arguments by starting - the inferior process with the universal argument. - - Changes and New Features in 17.11: - - * The ESS initialization process has been streamlined. You can now - load the R and Stata modes independently from the rest of ESS. Just - put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your - init file. This is for experienced Emacs users as this requires - setting up autoloads for '.R' files manually. We will keep - maintaining 'ess-site' for easy loading of all ESS features. - - * Reloading and quitting the process is now more robust. If no - process is attached, ESS now switches automatically to one - (prompting you for selection if there are several running). - Reloading and quitting will now work during a debug session or when - R is prompting for input (for instance after a crash). Finally, - the window configuration is saved and restored after reloading to - prevent the buffer of the new process from capturing the cursor. - - * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working - directory of the current process to the current package directory. - - * ESS[R] Lookup for references in inferior buffers has been improved. - New variable 'ess-r-package-source-roots' contains package - sub-directories which are searched recursively during the file - lookup point. Directories in 'ess-tracebug-search-path' are now - also searched recursively. - - * ESS[R] Namespaced evaluation is now automatically enabled only in - the 'R/' directory. This way ESS will not attempt to update - function definitions from a package if you are working from e.g. a - test file. - - Changes and New Features in 16.10: - - * ESS[R]: Syntax highlighting is now more consistent. Backquoted - names are not fontified as strings (since they really are - identifiers). Furthermore they are now correctly recognized when - they are function definitions or function calls. - * ESS[R]: Backquoted names and '%op%' operators are recognized as - sexp. This is useful for code navigation, e.g. with 'C-M-f' and - 'C-M-b'. - * ESS[R]: Integration of outline mode with roxygen examples fields. - You can use outline mode's code folding commands to fold the - examples field. This is especially nice to use with well - documented packages with long examples set. Set - 'ess-roxy-fold-examples' to non-nil to automatically fold the - examples field when you open a buffer. - * ESS[R]: New experimental feature: syntax highlighting in roxygen - examples fields. This is turned off by default. Set - 'ess-roxy-fontify-examples' to non-nil to try it out. - * ESS[R]: New package development command 'ess-r-devtools-ask' bound - to 'C-c C-w C-a'. It asks with completion for any devtools command - that takes 'pkg' as argument. - * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. - Currently only implemented for R. The R method runs - 'inferior-ess-r-reload-hook' on reloading. - * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers - as well. - - Bug fixes in 16.10: - * ESS[R]: Fix broken (un)flagging for debugging inside packages - * ESS[R]: Fixes (and improvements) in Package development - * ESS[R]: Completion no longer produces '...=' inside 'list( )'. - * ESS[R]: Better debugging and tracing in packages. - * ESS[R]: Better detection of symbols at point. - * ESS[R]: No more spurious warnings on deletion of temporary files. - * ESS[julia]: help and completion work (better) - * ESS[julia]: available via 'ess-remote' - - Changes and New Features in 16.04: - - * ESS[R]: 'developer' functionality has been refactored. The new - user interface consists of a single command - 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once - an evaluation environment has been set with, all subsequent ESS - evaluation will source the code into that environment. By default, - for file within R packages the evaluation environment is set to the - package environment. Set 'ess-r-package-auto-set-evaluation-env' - to 'nil' to disable this. - * ESS[R]: New 'ess-r-package-mode' This development mode provides - features to make package development easier. Currently, most of - the commands are based on the 'devtools' packages and are - accessible with 'C-c C-w' prefix. See the documentation of - 'ess-r-package-mode' function for all available commands. With - 'C-u' prefix each command asks for extra arguments to the - underlying devtools function. This mode is automatically enabled - in all files within R packages and is indicated with '[pkg:NAME]' - in the mode-line. - * ESS[R]: Help lookup has been improved. It is now possible to get - help for namespaced objects such as pkg::foobar. Furthermore, ESS - recognizes more reliably when you change 'options('html_type')'. - * ESS[R]: New specialized breakpoints for debugging magrittr pipes - * ESS: ESS now implements a simple message passing interface to - communicate between ESS and inferior process. - - Bug fixes in 16.04: - * ESS[R]: Roxygen blocks with backtics are now correctly filled - * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' - * ESS[R]: Error highlighting now understands 'testthat' type errors - * ESS[Julia]: Added getwd and setwd generic commands - - Changes and New Features in 15.09: - - * ESS[R]: The indentation logic has been refactored. It should be - faster, more consistent and more flexible. There are three types - of indentation settings, those starting with 'ess-offset-' give the - actual offsets, those starting with 'ess-indent-' are control - (commonly Boolean) variables, and those starting with 'ess-align-' - are vertical alignment overrides which inhibit default offsets in - specific situations. See 'ess-style-alist' for detailed - description of the new indentation system and provided default - indentation styles. - - * ESS[R]: Deprecation of old indentation settings. As a consequence - of the indentation re-factoring 'ess-brace-imaginary-offset', - 'ess-expression-offset' and all delimiter-specific offsets are - deprecated. The settings for indentation of continued statements - have been replaced by 'ess-offset-continuations'. It can be set to - either 'cascade' or 'straight' (the default). - 'ess-arg-function-offset' has been replaced by - 'ess-indent-from-lhs' and has been generalised to assignments. - This setting now works with both statement blocks and expressions - and only takes effect for offsets set to 'prev-call' and - 'open-delim' in order to produce a consistent indentation. - - * ESS: A test framework has been set up. - - * ESS[R]: A new RStudio style is provided to mimic as closely as - possible R files indented via RStudio. To reproduce the setup of - some of the RStudio users, the RStudio- style with - 'ess-offset-arguments' set to 'prev-line' is also provided. In - addition, the new RRR+ style is equivalent to RRR except it indents - blocks in function calls relatively to the opening delimiter. This - style does not try to save horizontal space and produces more - indentation. - - * ESS[R]: Roxygen fields will now be indented on paragraph refilling - in order to make the documentation more readable. You can also - refill commented lines in the 'examples' field without squashing - the surrounding code in the comments. - - * ESS[R]: ESS can now format your code! This is controlled through - the settings 'ess-fill-calls' and 'ess-fill-continuations'. When - activated, '(fill-paragraph)' formats your calls and your - formulas/continuations while making sure they don't go past - 'fill-column'. Repeated refills cycle through different styles - (see the docstrings for more details). By default, the refilled - region blinks. Set 'ess-blink-filling' to nil to prevent this. - - * ESS[R]: Fix occasional missing error location fontification in - inferior buffers. - - * ESS[R]: ess-developer now correctly assigned the environment of new - functions to the package namespace. - - * ESS[Julia]: ?[topic] now works in the *julia* buffer. Note that - support for editing Julia code now depends on 'julia-mode.el' from - the Julia project. If you install ESS from the official - tarball/zip file, 'julia-mode.el' is already included. Otherwise, - if you install ESS by running 'make', then the latest version of - 'julia-mode.el' is downloaded (and so you need an active internet - connection to install) during the installation process. - Alternatively, if you run ESS without running 'make', then ensure - that you have the 'julia-mode.el', which you can get easily from - MELPA for example. - - * iESS: For naming inferior processes, ESS can use 'projectile''s - project root and it does so when - 'ess-gen-proc-buffer-name-function' is set to - 'ess-gen-proc-buffer-name:projectile-or-simple' as by default, or - to another value beginning with - 'ess-gen-proc-buffer-name:projectile-*'. - - Changes and New Features in 15.03-1: - * ESS[R]: An indentation bug has been fixed (github issue 163) - * ESS[R]: On windows, if 'ess-prefer-higher-bit' is non-nil (the - default), then R-newest will try to run a 64 bit (rather than 32 - bit) version of R. - - Changes and New Features in 15.03: - * ESS[R]: Full native support for 'company-mode'. - * ESS[R]: More efficient caching algorithm for R completion. - * ESS: New offset variable 'ess-close-paren-offset' to control the - indentation of the closing parentheses. - * ESS[R]: Ask for CRAN mirror only once per emacs session. - * ESS[R]: Detect 'library' and 'require' calls for better completion - caching. - * Buffer display is now customizable ('ess-show-buffer-action'). - * Use 'y-or-n-p' instead of 'yes-or-no-p' throughout. - * More support for ODS in ess-sas-graph-view. - * Makefiles are now both UNIX and GNU friendly. - * ESS[R]: Simplify directory lookup in 'ess-developer' (#137). - * Make closed paren indentation consistent - - Bug Fixes in 15.03: - * Fix open brace indentation bug (#27 in ess/R-ESS-bugs.R). - * Fix git version lookup - * Don't check directory modtime in R dialect. - * Declare all ess macros for edebug. - * Add 'ess-smart-comma' to eldoc message functions. - * Inform users when retrieving RDA aliases. - * Line ending in '~' is also a continuation line. - * Filing roxy paragraphs works as expected now. - * In 'ess-developer-add-package', remove incorrect 'wait' argument - from 'ess-get-words-from-vector' call. - * Fix #96, #117, #120, #125, #134, #137. - * Fix ess-quit-r. Call base::q() even if it is masked. - * Fix 'ess-show-buffer' to always display the buffer in another - window. - * Makefile: Fix cd bug for directories with spaces in them - * 'ess-kill-buffer-and-go' modified to not restart R - - Changes / Selected Bug Fixes in 14.09: - * ESS[Julia]: Executable is changed to 'julia'. - * ESS[Julia]: Completion and help system was adjusted to Julia - v.0.3.0. Julia v.0.2.x is no more supported. - * ESS[R]: Running R with 'gdb' debugger now works as expected - * iESS: Inferior ESS buffers are now derived from 'comint-mode' - * ESS[R]: 'ess-execute-screen-options' uses correct screen width in - terminal sessions - * ESS: 'ess-build-tags-for-directory' works when no TAGS file name - was provided - * ESS: 'ess-offset-statement-continued' is now respected everywhere - except inside of the 'if' test condition. - * ESS: New variable 'ess-offset-statement-first-continued' for - indentation of the first line in multiline statements. - * ESSR: Starting ',' in multiline statements indentation is now - ignored to achieve a more pleasant alignment. - * ESSR: Improved behavior of 'RET' in roxygen blocks. - * ESS[R]: command cleaning with 'C-u C-u C-y' was broken with lines - containing " + " - * ESS[R]: fixed "empty watch window bug" - * ESS[R]: don't ask for help location on ac-quick-help (request of - github #81) - * ESS[R]: "importClassesFrom" and "importMethodsFrom" were added to - the list of two-parameter roxygen commands - * ESS[R]: fix vignetes display and hyperlinks (were broken in - 13.09-1) - * ESS[Julia]: recognize function names ending with ! - * ESS[Julia]: fix indentation of "for" comprehension syntax within - brackets. - - Changes / Selected Bug Fixes in 13.09-1: - * ess-remote and TRAMP: R support code is now downloaded in binary - form instead of being injected from local machine. The R code is - stored in '~/.config/ESSR/' directory on the remote machine - * TRAMP: PAGER environment variable is now correctly set to - 'inferior-ess-pager' - * retrieval of help topics on remote machines is fixed - * org-babel: source references of R code executed from org files - correctly point to source references in original org files (version - 8.2.1 or higher of org-mode is required for this feature) - * 'ess-execute' is now bound to 'C-c C-e C-e' in 'ess-extra-map'. - * completion works again in 'ess-execute' - * ESS[R]: 'head' and 'tail' methods were replaced by '.ess_htsummary' - in 'ess-R-describe-object-at-point-commands' - * ESS[roxygen]: evaluation commands now work in roxygen blocks. - Leading comments are automatically removed before the evaluation - * ESS[transcript]: 'Clean Region' now works with multiline - statements; 'ess-transcript-clean-region' etc. correctly treat - multiline statements, i.e., no longer forgets the lines typically - preceded by '+' - * ESS[SAS]: Three features/fixes with special thanks to Matthew - Fidler https://github.com/emacs-ess/ESS/pulls/mlf176f2 - (https://github.com/emacs-ess/ESS/pulls/mlf176f2). Turn on SAS log - mode when appropriate. Indent comments and CARDS statement more - appropriately. - * ESS[SAS]: 'ess-sas-edit-keys-toggle' default returns to 'nil' - * ESS[R]: support for 'prettify-symbols-mode': contribution from - Rudiger Sonderfeld - * ESS[SWV]: knitr now evaluates in the current frame - * ESS[developer]: ess-developer doesn't kill open DESCRIPTION files - anymore - * ESS[roxygen]: 'ess-roxy-preview-HTML' is now on 'C-c C-o C-w' and - 'ess-roxy-preview-text' is now on 'C-c C-o C-t' - * ESS: installation with 'make install' was simplified and should - work out of the box on most *nix systems - * ESS installation instructions simplified - * fixed font-lock bug introduced in 13.09 that was causing very slow - process output - - Changes/New Features in 13.09: - * font-lock in process buffers doesn't "spill" over prompts. Missing - closing string delimiters should not cause wrong fontification of - the following command input. - * ESS[julia]: full features M-TAB completion and auto-complete - support, which now works for modules, structures and data types. - * ESS[julia]: a much better eldoc showing arguments of methods and - data type constructors - * ESS-developer: - - ESS-developer work-flow pattern has been streamlined: - ESS-developer is now automatically activated on per-file basis - if the file is part of a developed package - 'ess-developer-packages'. The old behavior (activation on - per-process basis) is still available on 'M-x ess-developer' - in a process buffer. - - integration with 'devtools' package. New command - 'ess-developer-load-package' calls 'load_all' on the package - containing current file. 'ess-developer-add-package' now - offers IDO menu completions with available loading methods, - currently 'library', and 'load_all'. Loading command can be - customized with 'ess-developer-load-on-add-commands'. - * 'TAB' now indents region if region is active (a contribution of - Matthew Fidler in pull #41) - * 'M-x ess-version' now reports full loading path and recognizes git - and ELPA versions. - * warning and error keyword are now highlighted with - 'font-lock-warning-face' as they should be, (for quite some time - these keywords have been hijacked by compilation mode - fontification). - * eldoc: Eldoc now recognizes multiple processes. If current process - is busy, or current buffer is not associated with a process, eldoc - picks its completions from the first available free process. - * org-babel: evaluation is now org-friendly - * help: new help buffers now try to reuse ess-help buffers. This - behavior is controlled by 'ess-help-reuse-window' custom variable. - * help: ?foo pops IDO menu on multiple help files (so far it worked - only for 'C-c C-v') - * remote evaluation is considerably faster now on slow connections - * ESS[R] tracebug R source references regular expressions are - (mostly) language agnostic. - * 'ess-function-call-face' inherits from - 'font-lock-function-name-face' rather than - 'font-lock-builtin-face'. - * 'ess-inject-source' now accepts 'function-and-buffer' option. - * Documentation: The "New Features" section (and 'NEWS') now - represent recent changes: within the last year or so. All changes - can be found in the new news.html (news.html) (or 'NEWS' and - 'ONEWS'). - * ESS[R] 'ess-rep-regexp' should no longer inf.loop (rarely!), and - hence 'M-x ess-fix-miscellaneous' should neither. - - Changes/New Features in 13.05: - * ESS[gretl]: Support for 'gretl' (both editing and sub-process - interaction). A contribution of Ahmadou Dicko. - * ESS: process output display is 4-10 times faster due to new caching - and only occasional emacs re-display (for the moment this - functionality is available only when 'ess-tracebug' is active). - * ESS: 'C-c `' is now bound to 'ess-show-traceback' and 'C-c ~' is - bound to 'ess-show-call-stack'. - * ESS[R]: ESS stores function in 'ESSR' environment to avoid kludging - users' global environment and accidental deletion. - * ESS[R]: new variable 'ess-swv-processing-command' to control - weaving and tangling. - * ESS[R]: 'ess-default-style' has been changed (from 'DEFAULT') to - 'RRR'. Use something like '(setq ess-default-style 'DEFAULT)' or - '(setq ess-indent-level 2)' in your '~/.emacs' equivalent _before_ - loading ESS, if you do not like this new "incompatible" default - style. - * ESS[julia]: ESS stores its functions in 'ESS' module. - * ESS[julia]: Eldoc is now supported in julia modes - * ESS[julia]: Adjusted error reference detection and interactive help - to julia internal changes - * ESS[R]: 'ess-use-tracebug''s default has been changed to 't'. Set - it to nil if you want to keep the previous behavior. - * ESS[tracebug]: Electric debug keys have been removed [breaking - change] The functionality was replaced with 'ess-debug-minor-mode' - and 'ess-debug-minor-mode-map'. - * ESS[tracebug]: 'ess-tracebug-map' is an alias to 'ess-dev-map' 'C-c - C-t'. - * ESS[tracebug]: 'ess-bp-toggle-state' ('C-c C-t o') can now be used - during the debug session to toggle breakpoints on the fly - (suggestion by Ross Boylan). - * ESS[tracebug]: 'ess-debug-flag-for-debugging' and - 'ess-debug-unflag-for-debugging' work correctly from the debugging - contexts. These commands also recognize non-exported functions for - the packages listed in 'ess-developer-packages' ('C-c C-t C-a'). - - * ESS[R]: Eldoc (activated by 'ess-use-eldoc') has become more - sophisticated, and hence also more intruding in the interface - between the Statistics softare, e.g., R, and the user. - - Note that you can turn off ElDoc, by placing '(setq ess-use-eldoc - nil)' in your '~/.emacs' file, prior to loading ESS, - - * ESS[SAS]: long over-looked 'SAS-mode-hook' appears! - * ESS[SAS]: 'ess-sas-edit-keys-toggle' now defaults to 't' since - 'sas-indent-line' is still broken, i.e. 'TAB' is now bound to - 'ess-sas-tab-to-tab-stop' by default - - Changes/Bug Fixes in 12.09-2: - * ESS: new 'ess-switch-to-end-of-proc-buffer' variable that controls - whether 'C-c C-z' switches to the end of process buffer. The - default is 't'. You can use prefix argument to 'C-c C-z' to toggle - this variable. - * ESS: fix in 'ess-eval-linewise' that was causing emacs to hang - during R debugging with 'ess-eval-visibly' equal to 't'. - * ESS: fix in 'ess-eval-linewise' that was causing emacs to recenter - the prompt in visible window - * ESS[tracebug]: A better handling of "Selection" prompts and debug - related singlekey commands. - * ESS: fix a bug in 'ess-switch-process' that was causing '*new*' - selection to fail. - * ESS[R]: Solve missing 'ess-local-process-name' bug in R-dired. - * ESS[SWV]: 'ess-swv-PDF' doesn't ask for a command to run if there - is only one command in 'ess-swv-pdflatex-commands'. - * ESS[SWV]: 'ess-swv-weave' gained an universal argument to allow for - an interactive choice between available weavers (sweave, knitr). - * ESS: 'ess-eval-*-and-step' functions go to next empty line at eob, - instead of staying at the last line. - - Changes/New Features in 12.09-1: - * ESS _Breaking Changes in Keys_: - - - New keymaps: 'ess-doc-map' bound to 'C-c C-d'; 'ess-extra-map' - bound to 'C-c C-e'; 'ess-dump-object-into-edit-buffer' was - moved on 'C-c C-e C-d' - - roxygen map was moved on 'C-c C-o' and 'ess-roxy-update-entry' - now resides on 'C-c C-o C-o' - - ess-handy-commands is not bound anymore - - 'ess-dev-map' (including 'ess-tracebug' and 'ess-developer') - moved on 'C-c C-t' - - 'C-c C-y' is deprecated in favor of 'C-c C-z C-z' - * ESS[R] new command 'ess-describe-object-at-point' bound to 'C-c C-d - C-e' (repeat 'C-e' or 'e' to cycle). It was inspired by Erik - Iverson's 'ess-R-object-tooltip'. Customize - 'ess-describe-at-point-method' to use tooltip instead of an - electric buffer. - * ESS: New command 'ess-build-tags-for-directory' bound to 'C-c C-e - C-t' for building dialect specific tag tables. After building tags - use 'M-.' to navigate to function and objects definitions. By - default 'C-c C-e C-t' builds tags based on imenu regular - expressions and also include other common languages '.c, .o, .cpp' - etc. But it relies on external 'find' and 'etags' commands. If - 'ess-build-tags-command' is defined (for 'R'), the inferior process - is asked to build tags instead. - * ESS: 'ess-switch-process' offers '*new*' alternative to start a new - process instead of switching to one of the currently running - processes. - * ESS: Switching between processes ('C-c C-s') uses buffer names - instead of the internal process names. Use 'M-x rename-buffer' - command to conveniently rename your process buffers. - * ESS: Process buffers can be automatically named on process creation - according to user specified scheme. Default schemes are *proc*, - *proc:dir* and *proc:abbr-long-dir* where 'proc' stands for the - internal process name and 'dir' stands for the directory where the - process was started in. The default is *proc*. For customization - see 'ess-gen-proc-buffer-name-function'. - * ESS: 'ess-eval-visibly-p' is deprecated in favor of - 'ess-eval-visibly'. - * ESS: New evaluation pattern 'nowait'. In addition to old 'nil' and - 't' values, 'ess-eval-visibly' accepts 'nowait' for a visible - evaluation with no waiting for the process. See 'ess-eval-visibly' - for details on evaluation patterns. - * ESS: New "Process" menu entry with process related commands and - configuration - * iESS: Process buffer is now automatically shown on errors - * ESS: New 'ess-switch-to-inferior-or-script-buffer' command bound to - 'C-c C-z' in both script and process buffers. If invoked form - process buffer it switches to the most recent buffer of the same - dialect. It is a single key command. - * ESSR-help: On multiple help pages with the same name, 'C-c C-v' now - asks for user resolution directly in emacs. - * ESS[R] ess-roxy: new variable 'ess-roxy-re' for fontification of - cases where the number of leading '#' differs from 'ess-roxy-str'. - * ESS[R] Eldoc was considerably enhanced. It now finds hidden - default S3 methods and displays non-default methods' arguments - after trailing ||. - * ESS[R]: New 'ess-display-demos' command bound to 'C-c C-d o' and - 'C-c C-d C-o' - * ESS: New 'ess-help-web-search' command bound to 'C-c C-d w' and - 'C-c C-d C-w' to facilitate interactive search of web resources. - Implemented for 'R', 'Stata' and 'Julia'. See also - 'ess-help-web-search-command'. - * ESS: ess-pdf-viewer-pref accepts now command line arguments - * ESS[Rnw]: Add knitr support. Customize 'ess-swv-processor' for the - default processor. - * ESS[Rnw]: More thorough renaming of remaining 'noweb-*' to - 'ess-noweb-*'. - * ESS[Rnw] new commands 'ess-eval-chunk-and-step' and - 'ess-eval-chunk' bound to 'M-n C-c' and 'M-n C-M-x' to mirror - standard ess commands in C-c map. - * ESS[R] Auto-completion: new variable 'ess-ac-R-argument-suffix' to - customize the insertion of trailing "=". Defaults to " = ". - * ESS[Julia]: Added index, apropos and web-search to julia. - * ESS help: More evaluation commands were added to ess-help mode - ('C-c C-c', 'C-M-x' etc) - - Bug Fixes in 12.09-1: - * iESShelp: Multiple help pages with the same name are properly - handled on 'C-c C-v' - * iESSremote: Evaluation with ESS remote no longer freezes emacs. - * iESS: 'comint-previous-prompt' 'C-c C-p' no longer stops on - secondary prompt "+". - * iESS[R], iESS(Sqpe) [S] on Windows: The 'options("editor")' is now - initialized to 'emacsclient' instead of the previous 'gnuclient'. - The user may need to add the line '(server-start)' to the emacs - initialization file. 'emacsclient' has been included with emacs - since GNU Emacs 22.1. - * ESS[Rnw] Fixed "connection to R" bug (in 12.09 only). - * ESS[Rnw] Explicit 'ess-swv-stangle' and 'ess-swv-sweave' functions. - * ESS[Rnw] Fixed completion and smart underscore problems cause by - unmatched "\"' - * ESS[R] is more careful with the 'R' code injection. It now happens - only once at the start of the session. - * ESS[R]: Fixed auto-scrolling the comint buffer on evaluation. - * ESS[Julia]: Solve several indentation and word navigation problems. - * ESS[Julia]: Help system works again. - - Changes/New Features in 12.09: - - * Due to XEmacs lacking some features that ESS requires, ESS support - of XEmacs ends with ESS 12.04-4. This decision will be re-visited - in the future as XEmacs continues to sync with GNU Emacs. - - * ESS[R]: On Windows, there is now a new customizable variable - (currently called 'ess-directory-containing-R') to tell ESS where - to look for the 'Rterm.exe' executables. The name of the variable - and the values it can take are both in beta and subject to change. - Prior to this variable, ESS searched only in the default - installation directory. Setting this variable now tells ESS how to - find 'Rterm.exe' executables when they are installed somewhere - else. - - * ESS[julia]: _new_ mode for editing julia code ('*.jl'). Start with - 'M-x julia'. - - Full interaction interface, imenu and basic error referencing are - available. - - * ESS[R] noweb: 'noweb-mode' and 'noweb-font-lock-mode' have been - renamed to 'ess-noweb-mode' and 'ess-noweb-font-lock-mode' to avoid - conflicts with the "real" 'noweb-mode'. - - * ESS[R] noweb: The long standing font-lock bug has been solved in - 'ess-noweb' interface. - - * ESS: Basic evaluation keys are now bound to 'ess-eval-region-*-' - functions: - - - 'C-M-x' is bound to 'ess-eval-region-or-function-or-paragraph' - - 'C-c C-c' is bound to - 'ess-eval-region-or-function-or-paragraph-and-step' - - 'C-RET' is bound to 'ess-eval-region-or-line-and-step' - - Each of these functions first evaluates the region whenever the - region is active. - - * ESS: 'C-M-a'/'C-M-e' now step to beginning/end of paragraph if no - function has been detected. - - * ESS: 'ess-eval-*-and-step' family of functions are now smarter, and - don't step to end of buffer or end of chunk code ('@') when at the - end of the code. - - * ESS: 'ess-handy-commands' function is bound to 'C-c h' - - * ESS: ESS is now _blinking_ the evaluated region. Set - 'ess-blink-region' to nil to deactivate; 'ess-blink-delay' gives - the duration of the blink. Evaluated region is "blinked" in - 'highlight' face. - - * ESS[R-help] New key 'a' for "apropos()" in help buffers. Also - available through 'C-c h'. - - * ESS[R-help] All R commands of type foo?bar and foo??bar are - recognized and redirected into appropriate *ESS-help* buffers. - - * ESS[R]: New customization interface for _font-lock_. - - ESS font-lock operates with predefined keywords. Default keywords - are listed in 'ess-R-font-lock-keywords' and - 'inferior-R-font-lock-keywords', which see. The user can easily - customize those by adding new keywords. These variables can also - be interactively accessed and saved through 'ESS/Font-lock' - submenu. - - Several new fontification keywords have been added. Most notably - the keywords for highlighting of function calls, numbers and - operators. - - * ESS[R]: auto-complete is now activated by default whenever - auto-complete package is detected. Set 'ess-use-auto-complete' to - nil to deactivate. - * ESS[R]: R AC sources are no longer auto-starting at 0 characters - but at the default 'ac-auto-start' characters. - * ESS no longer redefines default ac-sources, but only appends - 'ac-source-filename' to it. - * ESS: 'ac-source-R' now concatenates " = " to function arguments. - - * ESS: Menus for ESS and iESS have been reorganized and enriched with - _Tracebug_ and _Developer_ submenus. - - * ESS[R]: 'ess-developer' and 'ess-tracebug' commands are available - by default in 'ess-dev-map' which is bound to 'C-c d' in ESS and - iESS maps. - - * ESS[R]: 'eldoc' truncates long lines whenever - 'eldoc-echo-area-use-multiline-p' is non-nil (the default). Set - this variable to t if you insist on multiline eldoc. See also - 'ess-eldoc-abbreviation-style'. - - * ESS[R]: completion code pre-caches arguments of heavy generics such - as 'plot' and 'print' to eliminated the undesirable delay on first - request. - - * iESS: Prompts in inferior buffers are now highlighted uniformly - with 'comint-highlight-prompt' face. - - * ESS[R]: R process no longer wait for the completion of input in - inferior buffer. Thus, long running commands like 'Sys.sleep(5)' - no longer stall emacs. - - * ESS: [R, S, Stata, Julia] have specialized 'ess-X-post-run-hook's, - which are run at the end of subprocess initialization. - - * ESS[Stata]: All interactive evaluation commands work as expected. - On-line comments are removed before the evaluation and multiline - comments are skipped on 'C-c C-c' and other interactive commands. - - * ESS no longer auto-connects to a subprocess with a different - dialect than the current buffer's one. - - * ESS: 'ess-arg-function-offset-new-line' is now a list for all the - ESS indentation styles, which results in the following indentation - after an open "(": - - a <- some.function(other.function( - arg1, - arg2) - - * ESS[SAS]: Improved MS RTF support for GNU Emacs; try - 'ess-sas-rtf-portrait' and 'ess-sas-rtf-landscape'. - - Changes/Bug Fixes in 12.04-3: - * ESS: basic support for package.el compatibility - * ESS[R]: correct indentation of & and | continuation lines - * 'M-x ess-version' shows the svn revision even after 'make install' - * ESS[SAS]: improved XEmacs support - * iESS[R]: better finding of previous prompt - * ESS[Stata]: adjusted prompt for mata mode - * ESS[R]: resolved name clashes with cl.el - * ESS[R]: removed dependence on obsolete package assoc - * New 'make' target 'lisp', to build the lisp-only part, i.e., not - building the docs. - - Changes/New Features in 12.04-1: - * iESS[Stata]: New interactive help invocation. - * iESS[Stata]: New custom variable 'inferior-STA-start-file'. - * iESS[Stata]: 'inferior-STA-program-name' is now "stata" and can be - customized. - * ESS[Stata] New sections in stata help files Syntax('s-S'), - Remarks('r'), Title('t'). - - Bug Fixes in 12.04-1: - * ESS[R]: Better 'ess-tracebug' error handling. - * ESS[R]: Corrected 'ess-eldoc' help string filtering and improved - argument caching. - * ESS[R]: Indentation of non-block if/else/for/while lines fixed. - * 'M-x ess-version' should work better. - * ESS: Filename completion now again works inside strings. - * iESS[Stata]: Fixed prompt detection issue. - * ESS[Rd]: R is autostarted also from here, when needed. - - Changes/New Features in 12.04: - * ESS: Reverting new behavior of 12.03, 'TAB' in 'ess-mode' no longer - completes by default. If you want smart 'TAB' completion in R and - S scripts, similarly to iESS behavior, set the variable - 'ess-tab-complete-in-script' to 't'. Also see - 'ess-first-tab-never-complete' for how to customize where first - 'TAB' is allowed to complete. - * ESS: completion is consistently bound to 'M-TAB' (aka 'M-C-i') in - both Emacs23 and Emacs24. - * ESS: The variable 'ess-arg-function-offset-new-line' introduced in - ESS(12.03) now accepts a list with the first element a number to - indicate that the offset should be computed from the indent of the - previous line. For example setting it to '(2) results in: - - a <- some.function( - arg1, - arg2) - - Changes/New Features in 12.03: - * ESS indentation: new offset variable - 'ess-arg-function-offset-new-line' controlling for the indentation - of lines immediately following open '('. This is useful to shift - backwards function arguments after a long function call expression: - - a <- some.function( - arg1, - arg2) - - instead of the old - - a <- some.function( - arg1, - arg2) - - If '(' is not followed by new line the behavior is unchanged: - - a <- some.function(arg1, - arg2) - - This variable should be set as part of indentation style lists, or - in ess-mode hook. - * ESS[R]: 'C-c .' sets (indentation) style. - * ESS: In ESS buffers 'yank'('C-y') command accepts double argument - 'C-u C-u' to paste commands only. It deletes any lines not - beginning with a prompt, and then removes the prompt from those - lines that remain. Useful to paste code from emails, - documentation, inferior ESS buffers or transcript files. - * Documentation: ESS user manual has been rearranged and completed - with several new chapters and sections to reflect newly added - features ("Completion", "Developing with ESS", "ESS tracebug", "ESS - developer", "ESS ElDoc", "IDO Completion" and "Evaluating Code") - * RefCard: Reference card was updated to include new features. - * Eldoc: Eldoc was rewritten and is activated by default. See - 'ess-use-eldoc', 'ess-eldoc-show-on-symbol', - 'ess-eldoc-abbreviation-style' variables for how to change the - default behavior. _Note:_ 'skeleton-pair-insert-maybe' prohibits - eldoc display, on '(' insertion. - * ESS[R]: Eldoc shows arguments of a generic function whenever found. - * ESS: 'TAB' in 'ess-mode' now indents and completes, if there is - nothing to indent. Set 'ess-first-tab-never-completes-p' to 't' to - make 'TAB' never complete on first invocation. Completion - mechanism is similar to the completion in the 'inferior-ess-mode' - - a filename expansion is tried, if not found ESS completes the - symbol by querying the process. - * ESS for emacs version 24 or higher: ESS is fully compatible with - the emacs 24 completion scheme, i.e. all the completion is done by - 'completion-at-point'. Also in accordance with emacs conventions, - ESS doesn't bind 'M-TAB' for emacs 24 or higher. 'M-TAB' calls the - default 'complete-symbol'. - - * ESS[R]: Out of the box integration with 'Auto Completion' mode - http://cx4a.org/software/auto-complete - (http://cx4a.org/software/auto-complete) . Three AC sources - 'ac-source-R-args', 'ac-source-R-objects' and 'ac-source-R' are - provided. The last one combines the previous two and makes them - play nicely together. Set 'ess-use-auto-complete' to 't' to start - using it. Refer to documentation string of 'ac-use-auto-complete' - for further information. - * ESS[R]: New unified and fast argument completion system, comprised - of 'ess-funname.start', 'ess-function-arguments', - 'ess-get-object-at-point'. Eldoc and auto-completion integration - are using this system. - * ESS: 'ess-switch-to-end-of-ESS'('C-c C-z'), and - 'ess-switch-to-ESS'('C-c C-y'): Automatically start the process - whenever needed. - * ESS[R]: 'roxy' knows about previewing text version of the - documentation. Bound to 'C-c C-e t'. - * ESS[R]: Solved the "nil filename" bug in roxygen support. - * ESS[R]: 'ess-tracebug' is now part of ESS: - - New Features: - - - Source injection: Tracebug now can inject source references on - the fly during code evaluation, i.e. you don't have to source - your file, but just evaluate your code in normal fashion. - Variable 'ess-tracebug-inject-source-p' controls this behavior - - if t, always inject source reference, if ''function', inject - only for functions (this is the default), if 'nil', never - inject. - - During the source injection the value of 'ess-eval-visibly' is - ignored. - - Org-mode support: Visual debugger is now aware of the - temporary org source editing buffer ('C-c '') and jumps - through this buffers if still alive, or in original org buffer - otherwise. - - New keys in watch mode: '?' and 'd' - - Two new hooks: ess-tracebug-enter-hook and - ess-tracebug-exit-hook - - * ESS[R]: New package 'ess-developer' to evaluate 'R' code directly - in the package environment and namespace. It can be toggled on and - off with 'C-c d t'. When 'ess-developer' is on all ESS evaluation - commands are redefined to evaluate code in appropriate - environments. Add package names to the list of your development - packages with 'C-d a', and remove with 'C-d r'. Source the current - file with 'C-d s'.Evaluation function which depend on - '`ess-eval-region'' ask for the package to source the code into, - 'ess-eval-function' and alternatives search for the function name - in the development packages' environment and namespace and insert - the definition accordingly. See the documentation section - "Developing with ESS/ESS developer" for more details. - - * ESS[R] help system: - - New Features: - - - 'q' quits window instead of calling - 'ess-switch-to-end-of-ESS'. This is consistent with emacs - behavior help and other special buffers (_breaking change_). - - 'k' kills window without asking for the name (pointed by Sam - Steingold) - - Help map inherits from 'special-mode-map' as sugested by Sam - Steingold. - - Package index: new function 'ess-display-index' bound to 'i' - in help mode map. - - Package vignettes: new function 'ess-display-vignettes' bound - to 'v' in help mode map. - - Display help in HTML browser: new function - 'ess-display-help-in-browser' bound to 'w' in help mode map. - It depends on 'R''s 'browser' option. - - New custom variable 'ess-help-pop-to-buffer': if non-nil ESS - help buffers are given focus on display. The default is 't' - (_breaking change_). - - New menu entries for the above functions. - - Bogus help buffers are no longer generated by default, i.e. - buffers of the form "No documentation for 'foo' in specified - packages and libraries: you could try '??foo' ". - 'ess-help-kill-bogus-buffers' now defaults to 't'. Beware, - there may be instances where the default is unsatisfactory - such as debugging and/or during R development. Thanks to Ross - Boylan for making the suggestion, Sam Steingold for reminding - us of this variable and Martin Maechler for the warning. - * ESS now uses 'IDO' completing read functionality for all the - interactive requests. It uses ido completion mechanism whenever - available, and falls back on classical completing-read otherwise. - You can set 'ess-use-ido' to nil if you don't want the IDO - completion. See the documentation string of 'ess-use-ido' for more - information about 'IDO' and ESS configuration. - - * ESS[S]: "','" is bound to ess-smart-comma: If comma is invoked at - the process marker of an ESS inferior buffer, request and execute a - command from '`ess-handy-commands'' list. If - 'ess-R-smart-operators' is t '`ess-smart-comma' also inserts " " - after comma. - * ESS[S], notably 'R': Variable '`ess-handy-commands'' stores an - alist of useful commands which are called by 'ess-smart-comma' in - the inferior buffer. - - Currently containing: - - change-directory - 'ess-change-directory' - help-index - 'ess-display-index' - help-object - 'ess-display-help-on-object' - vignettes - 'ess-display-vignettes' - objects[ls] - 'ess-execute-objects' - search - 'ess-execute-search' - set-width - 'ess-execute-screen-options' - install.packages - 'ess-install.packages' - library - 'ess-library' - setRepos - 'ess-setRepositories' - sos - 'ess-sos' - - Handy commands: 'ess-library', 'ess-install.packages', etc - ask - for item with completion and execute the correspond command. - 'ess-sos' is a interface to 'findFn' function in package 'sos'. If - package 'sos' is not found, ask user for interactive install. - - * ESS: New dynamic mode line indicator: Process status is - automatically reflected in all mode-lines of associated with the - process buffers. Particularly useful for displaying debug status - of 'ess-tracebug' and developer status of 'ess-developer' in all - associated buffers. - - * ESS: New 'ess-completing-read' mechanism: ESS uses 'ido' - completions whenever possible. Variable 'ess-use-ido' controls - whether to use ido completion or not. Active by default. - - * ESS now supports comint fields for output and input detection. - This feature is not used by default, but might be useful in the - future. - - * ESS[S]: New custom variable 'inferior-ess-S-prompt' to customize - prompt detection regular expression in the inferior ESS buffers. - You can customize this variable to enhance comint navigation - ('comint-previous-prompt' and 'comint-next-prompt') the inferior - buffers. - - * ESS[R]: Internal 'R' completion retrieval - ('ess-R-complete-object-name') was rewritten and is faster now. - - * ESS is using process plist to store process specific variables, as - opposed to buffer local variables as it was using before. The use - of buffer local variables to store process variables is - discouraged. - - * ESS: new functions to manipulate process plists: 'ess-process-get' - and 'ess-process-set'. - - * ESS: Internal process waiting mechanism was completely rewritten. - ESS no more relies on prompt regular expressions for the prompt - detection. The only requirement on the primary process prompt is - to end in '> '. This could be overwritten by setting - 'inferor-ess-primary-prompt'. - - * ESS[S], notably 'R': Saved command history: ESS-HISTORY-FILE now - accepts 't' (default), 'nil', or a file name. By setting it to - 'nil' no command line history is saved anymore. - ESS-HISTORY-DIRECTORY now allows to have the history all saved in - one "central" file. - * ESS[R]: more Roxygen improvements. - * ESS[R]: 'C-c .' to set (indentation) style. - - * ESS[R]: Functions with non-standard names (for example - 'aaa-bbb:cc') are properly handled by font-lock and evaluation - routines. - * ESS[R]:Several regexp bugs (described in etc/R-ESS-bugs.el) were - fixed in 'ess-get-words-from-vector' and 'ess-command'. - - Changes/New Features in 5.14: - * ESS[BUGS/JAGS]: Batch BUGS is back! For recent OpenBUGS versions, - 3.0.8+, a batch BUGS script is once again available, but for Linux - only. Therefore, since it seems that BUGS and JAGS must co-exist - (rather than a transition from BUGS to JAGS), .bug files are now in - ESS[BUGS] mode and .jag files are in ESS[JAGS] mode. ESS[BUGS] now - works like ESS[JAGS] rather than the original mode ESS[BUGS] mode - which was difficult to maintain. Although, ESS[BUGS] appears to - work, there still may be some features missing as well as bugs. - - * ESS[R]: New customizable variable 'ess-swv-plug-into-AUCTeX-p' - Commands to Sweave current file and LaTeX the result are now - available to AUCTeX users, if this variable is set to 't'. - - * ESS[S]: 'C-c C-c' ('ess-eval-function-or-paragraph-and-step') is - now skipping over comments as the other paragraph functions do. It - (and similar functions) should no longer wrongly find 'function()' - beginnings inside comments or strings. - - * ESS[SAS]: improved by better support for GNU Emacs - - Changes/New Features in 5.13: - * ESS[R]: On Windows, for R 2.12.0 and later, the Rterm executables - (in subdirectories i386 / x64) now are found as well as for earlier - R versions. - * ESS[S+]: on Windows, both 32- and 64-bit versions of S+ ("S-PLUS") - are found now and made available on the menu. - * ESS[R]: When prompting for a starting directory, the R version is - (always?) correct now. - * ESS[R]: on non-Windows platforms, the 'use-dialog-box' variable is - no longer temporarily changed (to 'nil' for R-x.y.z version - functions and to 't' for 'R' itself), but rather the user - customization is obeyed. - * ESS[R]: more Roxygen improvements. - * 'Rd-preview-help' now generates preview buffers with navigation - facilities the same as regular help buffers. - * ESS: New functions and keys C-c [up] / [down] for evaluating the - buffer "from beginning till here". - - Changes/New Features in 5.12: - * ESS[SAS] Font-locking: update of PROCs keywords (up to SAS 9.22); - error/warnings. - * ESS[R]: Roxygen improvements: S4 classes; also optionally keep - spaces when filling arguments - * ESS[Rd]: support new keywords: section-name \subsection plus a - dozen "new" keywords; should match R 2.12.x now. - * 'ess-display-help-on-object' ('C-c C-v') now _caches_ the list of - topics, thus speeding up the improvement feature introduced in 5.9. - - Changes/New Features in 5.11: - * Filename completion within buffers now adds only trailing - characters to complete the filename, rather than expanding to an - absolute file path. This filename completion is bound to the TAB - key. - - * 'M-n P' in Sweave buffers now prompts for the command to run - instead of using 'pdflatex' unconditionally, offering completion - from customizable collection 'ess-swv-pdflatex-commands', the first - of which is taken as default and that defaults to 'texi2pdf'. - * 'M-RET' is now also bound in S language (R and S+) buffers to - 'ess-use-this-dir'. It sends 'setwd(..)' to the S process to set - the working directory to the one of the source file. - - Changes/New Features in 5.10: - * 'M-RET' in *S* buffers is now bound to 'ess-dirs'. This function - will set Emacs's current directory to be the same as the *S* - process. This is useful if you use 'setwd()' within a *S* process. - - Changes/New Features in 5.9: - * Toolbar: The toolbar now has an icon for starting Splus. - * Indentation: New documentation and code has been added to make it - easier to change how ESS indents code. In particular, see - 'ess-default-style', 'ess-own-style-list' and the documention - subsection "Changing indentation styles". - * 'ess-display-help-on-object' ('C-c C-v') now offers completion - candidates for help file aliases, in addition to object names. - * Font locking: is now turned on even without 'window-system' is - 'nil', whenever ESS-FONT-LOCK-MODE is non-nil, i.e., by default. - * ESS script editing: ess-eval-deactivate-mark default is now t, as - suggested by Leo Alekseyev and subsequent "unanimous" ESS-help - discussion. - * ESS[R]: Editing support for "#!" (Rscript / littler) editing, - thanks to Jeffrey Arnold. - * ESS[R]: Now finds all R versions, both 64-bit and 32-bit, on some - 64-bit Windows machines. Please report back to ess-core success or - failure on your 64-bit Windows machine. - * ESS Manual now more visually pleasing; - - * ESS[R]: Roxygen on XEmacs no longer font locks for now (as it - required missing features and hence broke ESS startup, there). - * ESS[R]: Roxygen has a sub-menu on the [ESS] menu. - * ESS[R]: Function 'ess-rutils-htmldocs' in 'ess-rutils.el' offers an - alternative to 'help.start()' for navigating R documentation, using - the 'browse-url' Emacs function. - - Changes/New Features in 5.8: - * ESS[R]: New 'ess-rutils.el' with utilities for listing, loading, - installing, and updating packages, as well as object manipulation - (listing, viewing, and deleting). It also provides an alternative - to 'RSiteSearch()' that uses the 'browse-url' function, so results - can be viewed in an Emacs web browser. - * ESS[R]: much more extensive Roxygen interface, via ess-roxy.el from - Henning Redestig. Ess-roxy supports filling of roxygen fields, - generation and updating roxygen templates, completion of roxygen - tags, basic navigation (marking and moving between entries), - folding using hs-minor-mode and preview of the Rd file. - * Emacs lisp files have got better names (partly, for now). - - Changes/New Features in 5.7: - * ESS[R]: loading a source file ('C-c C-l') now works in Windows, - similarly to other platforms; (further; it had accidentally been - broken in ESS 5.6 on all platforms) - - Changes/New Features in 5.6: - * ESS[R]: help() calls have to differ from old default, with newer - versions of R; currently via .help.ESS <- function(...) hack. - - Changes/New Features in 5.4: - * ESS[SAS]: The long overdue change from 'make-regexp' to - 'regexp-opt' for font-locking is complete. The new 'regexp-opt' is - now the default since it is better than the old code in many ways - (and especially more maintainable). However, there are certainly - some special cases missed (bug reports and patches welcome!). - Setting 'ess-sas-run-regexp-opt' to 'nil' will result in the old - code being used. - * ESS[BUGS] and ESS[JAGS]: typing '=' now results in '<-'. - * ESS[R] function arguments "show" '(ess-r-args-show)' now uses the - new '(tooltip-show-at-point)' contributed by Erik Iverson. - * Toolbar icons now also work in (beta) Emacs 23. - * ESS[S]: New function 'ess-change-directory' for setting both emacs' - current directory and the directory of an *R* or *S* buffer. - * ESS[S] when transient-mark-mode is true, the mark is now kept, - rather than deactivated, thanks to a patch from David Reitter. - - Changes/New Features in 5.3.11: - * ESS[SAS]: work around bug in Emacs 22.2 & 22.3 which fails to set - case-fold fontification automatically. - * Rd mode: support new keyword 'Rdversion' - * ESS[R]: now again works with Emacs 21.x - - Changes/New Features in 5.3.10: - * Fixed noweb-mode bug accidentally introduced into 5.3.9 - * In noweb-mode, e.g., Rnw-mode, electric "<" also inserts closing - "@". Further, the code chunk boundaries are better kept - up-to-date, such that code[R] <-> text[LaTeX] minor mode switching - should happen more reliably. - * In noweb-mode, fix a buglet in rare [Enter] or [Tab] behavior; - further, by default disable the former '[[' .. ']]' - code-protection-when-filling behavior which has been found to be - buggy. - - Changes/New Features in 5.3.9: - * ESS[SAS]: evince PDF viewer now supported as well; search order: - evince, Xpdf, Adobe/Acrobat Reader - * ESS[R]: added support for Roxygen, potentially to be extended. - * ESS[S] (and R): inferior ('*R*') and transcript modes no longer - fontify language keywords (such as 'for', 'in', etc). - * iESS[Stata]: Customize the 'ess-sta-delimiter-friendly' setting to - 't' to convert embedded semi-colons to newlines for Stata - processing. - * Sweave fix for embedded blanks in PDF reader and PDF files - * Several fixes for Major Mode Convention violations in 'ess-mode' - and 'noweb-mode'. - * ESS[JAGS]: 'M-x comment-region' now available! - * ESS[S] The 'ess-swv-*' commands (and keybindings) are now in a - submenu of the "Noweb" menu, when editing Sweave files. - - Changes/New Features in 5.3.8: - * ESS[JAGS]: more separation from ESS[BUGS] (as much as is currently - planned); now 'C-c C-c' on an empty '.jmd' creates a template as it - should; symbolic links are created for CODA output so BOA is happy: - from 'index.txt' to '.ind' and 'chain#.txt' to '#.out' - * ESS[SAS]: buffer-local 'ess-sas-submit-command' and - 'ess-sas-submit-command-options' now recognized by - 'ess-sas-submit-region' - * ESS[S]: When trying to evaluate code in an S language buffer and - there is no associated process, now start R automatically instead - of signalling an error. Also, restart R if there is an associated - process which is not running. However, do not start R just via the - "electric" '(' ('ess-r-args-auto-show'). - * ESS[S]: For (one-line) functions withOUT '{ .. }' bodys, the end - of function is now correctly found more often. This notably - improves 'C-c C-c' ('ess-eval-function-or-paragraph-and-step'). - * ESS[JAGS]: cleanup/re-organization of elisp code; symbolic links - for CODA output are now only created by the new JAGS 'system' - command in version 1.0.3; specify whether this command is available - via 'ess-jags-system'; if not present, then no links are created so - that the '*shell*' buffer does not become unresponsive during the - batch run - - Changes/New Features in 5.3.7: - * ESS: 'ess-default-style' now *is* customizable, i.e., changing its - value in '~/.emacs' now does have the desired effect. - * ESS: 'ess-font-lock-mode' is a new variable (default: t) which - controls whether font-locking is enabled in ESS buffers. - * ESS[R]: for XEmacs on Windows; another tweak to find R versions - * ESS[SAS]: font-locking updated for ODS and SAS Bayesian Procedures; - a more consistent handling of SAS options by - 'ess-sas-submit-command-options' which is buffer-local; portable - snooze for MS Windows via customize-able 'ess-sleep-for' (floats - welcome); Xpdf now supported as a PDF viewer - * ESS[Rnw]: now also works with "emacs -nw" and Emacs 22. - * ESS[JAGS]: now requires JAGS 1.0 (see the new ESS for JAGS help - section for more information): both need work; suggestions welcome - * ESS[R]: [TAB] completion now uses the R-internal completion - mechanism (for R >= 2.5.0). - * ESS[R] ([S]): interpretation of "_" as assignment has been removed - in 'ess-continued-statement-p' for R and S. - * several internal code cleanups. - * ESS[R]: An experimental version of a new command 'Rgui' on MS - Windows to send lines directly from emacs to 'Rgui' is available in - file 'lisp/essd-rgui.el'. Preliminary documentation is in file - 'doc/rgui-doc.txt'. - - Changes/New Features in 5.3.6: - * ESS: for XEmacs, using "gnuclient" (without a "-q") works for - things like fix() after M-x gnuserv-start has been done. - * ESS[R]: M-x R-newest should now work in more situations on MS - Windows, e.g., when R has been installed in a non-default - "ProgramFiles" directory tree. In these cases, there's no need to - specify the name (and full path) of the R program anymore. - * ESS[R]: For XEmacs, startup (with new tooltip code) works again. - - Changes/New Features in 5.3.5: - * ESS[R] a new defun is available, 'M-x R-newest', which will start - the newest version of R that it can find on your system. - * ESS[R] add Sven Hartenstein's "R function arguments tips" - functionality, via new file '../lisp/essd-r-args.el'. Note that - this includes an "electric "("" behavior inside 'R-mode' which is - _active by default_ and can be customized via - 'ess-r-args-electric-paren'; i.e., use '(setq - ess-r-args-electric-paren nil)' to turn it off. Further, - 'ess-r-args-show-as' allows to switch to the "tooltip" mode. - * ESS: functions 'ess-get-pdf-viewer' and *-ps-viewer; built on new - customizable variables 'ess-pdf-viewer-pref' and - 'ess-ps-viewer-pref'; currently used in 'ess-swv-PDF' and '*-PS'. - * ESS[R] Improved 'ess-swv-PDF' to run pdf viewer only if pdflatex - was ok - * ESS[R] Improved 'ess-swv-weave' to start R automatically if none is - running. - * ESS: Do no longer ask _which_ ESS process to use if there is only - one. - - Changes/New Features in 5.3.4: - * ESS[R] now better work with options(error=recover); and the new - default of CHM help files on windows. - * ESS[R] some more cleanup in the "sweave" functions - * miscellaneous fixes - - Changes/New Features in 5.3.3: - * ESS[S] fix buglet (5.3.2 only) which left command prompt in - "execute buffer" and hence help files. - * new customizable variable 'ess-display-buffer-reuse-frames' set to - true (which changes default behavior) such that execution or help - *frames* are reused. - - Changes/New Features in 5.3.2: - * Classic BUGS now supported by '(require 'essd-bugs)' with ESS[BUGS] - and JAGS by '(require 'essd-jags)' with ESS[JAGS]. But, only one - of them can be used at a time since they don't play nice together. - Also, 'C-c C-c' is now bound to the function 'ess-bugs-next-action' - ('F12' has been retired). And finally, note that 'essl-bug.el' is - deprecated and the replacement is 'essl-bugs.el'. - * ESS[R] Improved some of the "Sweave-make" functions (yet scarcely - documented) in 'ess-swv.el'. - * ESS[S] No longer mess with .Last.value (nor in other "languages"). - - Changes/New Features in 5.3.1: - * See the docs for 2 ways to install ESS for XEmacs - 1. by uncommenting the XEmacs part of Section 1 of 'Makeconf' and - performing 'make install' - 2. by unpacking either 'ess-5.3.1.tgz' or 'ess-5.3.1.zip' into - 'PREFIX/lib/xemacs/site-packages' on unix or - 'PREFIX\XEmacs\site-packages' on windows - * ESS[R]: fixed bugs so that Rterm.exe can be found by XEmacs - * ESS[S]: 'ess-toggle-S-assign-key' is slightly changed; in - particular, the default 'ess-assign-key' is now 'C-x ='. - * ESS[R]: 'M-x R-site-search' is a new (slightly experimental) - utility similar to R's 'RSiteSearch(..)' but with the advantage of - using Emacs' preferred browser, see 'browse-url-browser-function' - - Changes/New Features in 5.3.0: - * ESS[BUGS]: sanely re-format statistical output, '.bog', from - scientific notation to numbers rounded with 4 decimal places with - 'M-x ess-bugs-sci-round-to-4-dp'. - * The keys for navigating among section headings in help buffers - worked, but only for one language per session; they should now work - for multiple languages. (They were also broken on Windows - machines.) - * ESS[S] long standing buglets in the internal logic for loading lisp - code on Windows. Particularly fixed behavior in help mode with - S-plus GUI. - * New variable, 'ess-use-inferior-program-name-in-buffer-name', which - enables using the executable name instead of the dialect name for - R. Feature request. - * ESS[S] 'ess-execute-screen-options' now also works correctly when - there is more than one window *side-by-side* in the same frame and - runs in the correct buffer also when there is more than one S - buffer. - * iESS[S] new functions 'ess-eval-paragraph-and-step' and - 'ess-eval-function-or-paragraph-and-step' are bound to keys 'C-c - C-p' and 'C-c C-c' respectively and to the menu in ESS-mode; also - bound in the help mode (for evaluating examples). - * ESS[S] new function 'ess-toggle-S-assign-key' allows to assign the - " <- " insertion to an arbitrary key. - - Changes/New Features in 5.2.12: - * ESS[SAS]: 'M-;' fixed, but the XEmacs function 'comment-dwim' may - be broken, if so, use 'M-x comment-region' and 'M-x - uncomment-region' instead; only valid PROCs are fontified which is - very helpful finding syntax errors (currently supported: BASE, ETS, - FSP, GRAPH, IML, INSIGHT and STAT); the "feature" where 'F'-keys - take you to an empty buffer when the requested destination is a - file that does not exist has been fixed, now the request results in - a no-op. Further, sas-mode now also works in simple terminals. - * Rterm/Cygwin combination works under Microsoft Windows. - * ESS[R]: internal calls use baseenv() instead of NULL and define - 'baseenv' where needed. - * New experimental support for installing ESS. See the file - 'lisp/ess-install.el'. - - Changes/New Features in 5.2.11: - * ESS Info entry and 'dir' handled more effectively for GNU Emacs - users - * ESS[SAS]: temporary files created for batch submission of a region - are now named based on the current file; see 'ess-sas-file-root' - for details; all 'lag' and 'dif' functions now fontified correctly - * iESS[SAS]: fixed a few nagging bugs, however, still does not appear - to work at this time; please let us know if you have any ideas. - * ESS[S]: Support for running other versions of Splus has been added - for unix. Two new variables, 'ess-s-versions' and - 'ess-s-versions-list', are used to tell ESS what other versions of - Splus you would like to run. - - Changes/New Features in 5.2.10: - * ESS[R]: ess-r-versions can no longer be customized (since the - customization was not taking effect unless customizations were - loaded before ESS). Its value has been changed so that it will also - find R executables beginning "R-devel" and "R-patched". If you - wish to change this variable, it must be set in your '.emacs' - before ESS is loaded. - * Installation with GNU Make enhanced: unix and unix-like operating - systems will now be able to install ESS for all users in either a - GNU Emacs site-lisp or an XEmacs package configuration by editing - 'lisp/ess-site.el' and 'Makeconf' accordingly, then issuing 'make - install' - * ESS[S]: Filename completion (inside strings) now also works in - XEmacs for R and S-plus. - - Changes/New Features in 5.2.9: - * ESS[R] for Windows: the \ directory character bug with respect to - ess-load-file has been eradicated. - * iESS[SAS]: 'C-c C-r' and 'C-c C-b' once again work as intended and - documented. - * ESS[S]: M-x ess-fix-EQ-assign is a bit more agressive. - * ESS[S]: Imenu now also shows setAs(), etc. - * ESS[R]: R function pattern enhanced with underlying code such that - 'M-C-a' ('ess-beginning-of-function') etc now work for many more - cases, including S4 method definitions. - * iESS[R]: myOwnhelp(1) no longer wrongly triggers help(1). - * ESS[R]: Improved detection of bogus help buffers: valid help - buffers containing with the string "no documentation"(e.g. - contour) were being treated as bogus. - * ESS[R]: In R help buffers, if 'options("help.try.all.packages" = - TRUE)' then '?rlm' will list which packages rlm is defined in. - This help buffer is not bogus, but instead is now relabelled - "*help[R](rlm in packages)*". - * ESS[STA]: add "//" as comment starting character to syntax-table. - - Changes/New Features in 5.2.8: - * iESS: [Tab] completes *file* names "inside string" as in earlier - (<= 5.2.3) ESS versions. - - Changes/New Features in 5.2.7: - * If you use Custom to change the variable ess-toolbar-items, the new - toolbar is used in all subsequent ESS buffers. - * ESS[SAS]: new feature: if ess-sas-log-max >0 and your .log grows to - more than ess-sas-log-max bytes, just the first ess-sas-log-max - bytes are refreshed; this is helpful when your .sas program - generates lots of error messages and gets too big for emacs to - display - * ESS[R/S]: 'M-;' in R/S editing modes will now indent with either - one or two hashes depending on context. - * ESS[R]: David Whiting's Sweave extensions (to 'noweb') are now - available (from ess-swv.el loaded by default). - - Changes/New Features in 5.2.6: - * Removed non-ASCII characters in a few files. - * ESS[R]: now works better when UTF-8 locale is active; in - particular, you get correct directional quotes in R's startup - message for R-devel (unstable development version of R 2.1.0) when - using environment variables LANGUAGE=en@quot LC_ALL=en_US.UTF-8 - * ESS[SAS]: toggling of .log mode improved ('F10'); toggling of .lst - mode now also available ('C-F10'); killing all buffers associated - with .sas program no longer bound to 'C-F10' since its a bit - overzealous. - * S-Plus 7 for Windows is now recognized. - * ESS[S] (incl. R): in auto-fill mode, strings are not wrapped - anymore. - * ESS[S] (incl. R): font-lock now correctly differs between R and S, - e.g., for "_"; both now fontify warning(.) and S does terminate() - additionally. - * Support for 'bell' aka 'beep' aka 'ding' aka 'alarm' in all - inferior modes: When \a is output "to the the console" at the - beginning of a line, the bell is rung. - - Changes/New Features in 5.2.5: - * ESS[R]: 'C-c C-q' or 'Quit S' from the menu now should work (again - and less klunkily) and do not append '-exited' to the buffer name. - Further, the behavior of '(ess-cleanup)', called from ess-quit, now - depends on the new customizable variable - 'ess-S-quit-kill-buffers-p' which defaults to 'nil'. Consequently, - the question _"Delete all buffers associated with ..?"_ will not - be asked anymore by default. - * ESS[SAS] - ess-ebcdic-to-ascii-search-and-replace will now work - with the 'recode' application as well which is available on many - platforms - * ESS[S] (incl. R): Name completion for slots of S4 objects now - works! - - Changes/New Features in 5.2.4: - * The documentation now includes an overview of how to use the emacs - TAGS facility for S functions. (The distribution also used to - contain a directory 'etc/other/Tags' where a ~1990 version of - 'etags.c' was distributed; this is no longer relevant and so has - been deleted.) - * ESS[SAS] - When you are working with EBCDIC files on an ASCII - platform, .log NOTEs may display as gibberish since the EBCDIC - characters are not converted to ASCII prior to their display. So, - the function ess-ebcdic-to-ascii-search-and-replace is provided for - convenience and is bound to 'C-F11'. This function requires the - 'dd' command (only available on unix or unix-like platforms). - * ESS: Completion of object names is now always done dynamically - rather than allowing the option of using a pre-computed database - (by 'ess-create-object-name-db') since modern computers seem fast - enough for dynamic completion. (We expect few users, if any, have - been using the pre-computed database method.) - * ESS: object completion in iESS buffers running on Windows was very - slow (for GNU Emacs, but not XEmacs) and has now been fixed. - Further, it was more or less broken for all versions of S-plus 6.x, - and has been fixed to work everywhere but with the Windows' GUI of - S-plus. The list of objects now shows unique names also when an - object appears more than once in the search path. - * ESS[R]: Completion of object names now also includes those starting - with ".". - - Changes/New Features in 5.2.3: - * ESS: When new inferior ESS processes are created, by default they - will replace the current buffer (this restores behavior from pre - 5.2.0). If you wish new ESS processes to start in another window - of the current frame, set inferior-ess-same-window to nil. - * New variables inferior-Splus-args and inferior-R-args provide a way - to pass command line arguments to starting S and R processes. - - Changes/New Features in 5.2.2: - * bug-fixes for 5.2.1 (require 'executable), html docs, etc. - * ess-lisp-directory/../doc/info added to Info-directory-list if - ess-info not found by info - * ESS[R]: If you have other versions of R on your exec-path, such as - "R-1.8.1" with Unix or "rw1081" with Windows, ESS will find them - and create appropriate functions, such as 'M-x R-1.8.1' or 'M-x - rw1081', for calling them. By default only Unix programs beginning - "R-1" and "R-2" and Windows programs parallel to the version of R - in your exec-path will be found, but see ess-r-versions and - ess-rterm-versions for ways to find other versions of R. - * ESS[R]: Other versions of R, such as "R-1.8.1" on Unix and "rw1081" - on Windows, are added to the "ESS / Start Process / Other" menu. - * ESS[S]: If you have other versions of S-Plus on your Windows - computer, such as S-Plus 6.1 or S-Plus 4.5, ESS will find them and - create appropriate functions, such as 'M-x splus61', for calling - the console version (Sqpe) inside an emacs buffer. By default only - programs installed in the default location will be found, but see - ess-SHOME-versions for ways to find other versions of S-Plus. - * ESS[S]: Other versions of Sqpe on Windows, such as "splus61", are - added to the "ESS / Start Process / Other" menu. - * ESS[R]: (bug fix) ess-quit (bound to 'C-c C-q') should now quit the - inferior R process, when issued from either the inferior buffer, or - from a .R buffer. - - Changes/New Features in 5.2.1: - * ESS[S] (R and S-plus): now have toolbar support with icons to - evaluate code in the inferior process or to switch there. This - code is experimental and likely to change as XEmacs/Emacs issues - get resolved. The toolbar should be enabled if your Emacs displays - images, but can be disabled with the variable ess-use-toolbar. - Thanks to David Smith from Insightful for the S-plus logo. - * ESS[SAS]: ess-sas-graph-view ('F12') enhanced; you can specify - external file viewers for each graphics file type via the alist - ess-sas-graph-view-viewer-alist; also .jpg/.gif are now handled by - image-mode on XEmacs, if available, otherwise by graphics - primitives as before - - Changes/New Features in 5.2.0: - * ESS[BUGS]: new info documentation! now supports interactive - processing thanks to Aki Vehtari (mailto:Aki.Vehtari@hut.fi); new - architecture-independent unix support as well as support for BUGS - v. 0.5 - * ESS[SAS]: convert .log to .sas with ess-sas-transcript; info - documentation improved; Local Variable bug fixes; SAS/IML - statements/functions now highlighted; files edited remotely by - ange-ftp/EFS/tramp are recognized and pressing SUBMIT opens a - buffer on the remote host via the local variable - ess-sas-shell-buffer-remote-init which defaults to "ssh"; changed - the definition of the variable ess-sas-edit-keys-toggle to boolean - rather than 0/1; added the function ess-electric-run-semicolon - which automatically reverse indents lines containing only "run;"; - 'C-F1' creates MS RTF portrait from the current buffer; 'C-F2' - creates MS RTF landscape from the current buffer; 'C-F9' opens a - SAS DATASET with PROC INSIGHT rather than PROC FSVIEW; "inferior" - aliases for SAS batch: 'C-c C-r' for submit region, 'C-c C-b' for - submit buffer, 'C-c C-x' for goto .log; 'C-c C-y' for goto .lst - * ESS[S]: Pressing underscore ("_") once inserts " <- " (as before); - pressing underscore twice inserts a literal underscore. To stop - this smart behaviour, add "(ess-toggle-underscore nil)" to your - .emacs after ess-site has been loaded; - ess-dump-filename-template-proto (new name!) now can be customized - successfully (for S language dialects); Support for Imenu has been - improved; set ess-imenu-use-S to non-nil to get an "Imenu-S" item - on your menubar; ess-help: Now using nice underlines (instead of - 'nuke-* ^H_') - * ESS[R]: After (require 'essa-r), 'M-x ess-r-var' allows to load - numbers from any Emacs buffer into an existing *R* process; 'M-x - ess-rdired' gives a "directory editor" of R objects; fixed - ess-retr-lastvalue-command, i.e. .Last.value bug (thanks to David - Brahm) - * ESS: Support for creating new window frames has been added to ESS. - Inferior ESS processes can be created in dedicated frames by - setting inferior-ess-own-frame to t. ESS help buffers can also - open in new frames; see the documentation for ess-help-own-frame - for details. (Thanks to Kevin Rodgers for contributing code.) - - Changes/New Features in 5.1.24: - * The version number is now correct even inside ESS/Emacs - - Changes/New Features in 5.1.23: - * Minor more Makefile clean up. - - Changes/New Features in 5.1.22: - * Besides info documentation, PDF and HTML documentation are also - provided (instead of built using "make") and available on the web - as well; see ESS web page (https://ess.r-project.org/) and StatLib - (http://lib.stat.cmu.edu/general/ESS/doc) - * Now that info documentation is available, the README.* files are no - longer supported. However, they are still distributed for what - it's worth. - * ESS is now an XEmacs package! See XEmacs Installation HOWTO - (https://www.xemacs.org/Install/index.html) for details - (specifically, items 10-15). - * ESS[SAS]: more user-friendly enhancements for remote SAS batch jobs - with Kermit file transfers (LOG and OUTPUT function key features - now supported). Multiple shells now supported so you can run SAS - on different computers from different buffers by setting the - buffer-local variable ess-sas-shell-buffer to unique buffer names. - * Major re-vamping of Makefile/Makeconf. - - Changes/New Features in 5.1.21: - * ESS[SAS]: info documentation now available!, see ESS->Help for SAS; - 'F12' opens GSASFILE nearest point for viewing either within emacs, - when available, or via an external viewer; more syntax highlighting - keywords; more enhancements for remote SAS batch jobs with Kermit; - new framework for remote SAS interactive jobs, see ess-remote - * ESS[S]: info documentation now available!, see ESS->Help for the S - family - * Makefile: tag now independent of rel; info files made by - doc/Makefile and installed in new info sub-directory - - Changes/New Features in 5.1.20: - * New 'options()$STERM' in the S dialects (S, S-Plus, R). The S - program can determine the environment in which it is currently - running. ESS sets the option to 'iESS' or 'ddeESS' when it starts - an S language process. We recommend other specific values for S - language processes that ESS does not start. - * New 'ess-mouse-me' function, assigned to S-mouse-3 by default. - User may click on a word or region and then choose from the menu to - display the item, or a summary, or a plot, etc. This feature is - still under development. - * GNU Emacs 21.1 is now supported (fixed for S dialects, SAS & BUGS), - (some from Stephen Eglen). - * XEmacs 21.x is now supported (fixed w32-using-nt bug) - * XEmacs on Win (NT) is better supported. - * Workaround for bug in Sqpe+6 (S-PLUS 6 for Win). - * should now work even when imenu is not available (for old - XEmacsen). - * ESS[SAS]: XEmacs-Imenu fix; 'C-TAB' is globalized along with your - function-key definitions, if specified; you can specify your SAS - library definitions outside of autoexec.sas for ess-sas-data-view - with SAS code placed in the variable ess-sas-data-view-libname, - also the dataset name is defaulted to the nearest permanent dataset - to point; Speedbar support now works for permanent datasets, please - ignore first./last.; new font-locking is now the default with more - improvements for font-locking PROCs, macro statements, * ; and %* ; - comments; you can toggle sas-log-mode with 'F10' which will - font-lock your .log (if it isn't too big); submit remote .sas files - accessed with ange-ftp, EFS or Tramp (Kermit is experimental) by - setting ess-sas-submit-method to 'sh; ess-sas-submit-command and - ess-sas-submit-command-options are buffer-local so you can have - local file variable sections at the end of your .sas files to - request different executables or specify special options and the - local file variables are re-read at submit instead of only at file - open so that if you make a change it is picked up immediately; - * ESS[BUGS]: font-lock with 'in' fixed. - * for STATA: font-lock bug fixed. - * for Rd mode: 'C-c C-v' and 'switch-process' in menu. further, 'C-c - C-f' prefix (Rd-font) for inserting or surrounding a word by things - such as \code{.}, \code{\link{.}}, \emph{.} etc. - * new functions (ess-directory-function) and (ess-narrow-to-defun) - ess-directory <-> default-directory logic (Jeff Mincy). - * Re-organized Makefile and fixed a few bugs. - - Changes/New Features in 5.1.19: - * S+6 now supported (Tony Rossini (Unix) and Rich Heiberger - (Windows)) - * New BUGS support through ESS[BUGS] mode (Rodney Sparapani) - Templates assist you in writing .bug and .cmd code (.cmd and .log - are replaced by .bmd and .bog to avoid emacs extension collisions). - Substitution" parameters facilitate "automagic" generation of - data...in" and "init...in" filenames, "const N=" from your data - file and "monitor()/stats()" commands. Activated by pressing - 'F12'. - * Fixes for 'ess-smart-underscore' SAS breakage (Rich Heiberger) - * You can change between PC and Unix, local and global SAS - function-key definitions interactively (Rich Heiberger) - * 'C-Submit' a highlighted region to SAS batch (Rodney Sparapani) - * New and improved SAS syntax highlighting (Rodney Sparapani) To get - the new functionality, set ess-sas-run-make-regexp to nil. Also - available in .log files via 'F10'. - * Open a permanent SAS dataset for viewing via 'F9' (Rodney - Sparapani) You must have the library defined in autoexec.sas for it - to work. - * User-friendly defaults for 'sas-program', - 'ess-sas-batch-pre-command' and 'ess-sas-batch-post-command' as - well Customize support for these and other ESS[SAS] variables - (Rodney Sparapani) - * 'ess-sas-suffix-2' now defaults to .dat via 'F11' (Rodney - Sparapani) - * Emacs/XEmacs, Unix/Windows issues collectively handled in - ess-emcs.el - * defadvice solves problem of missing *ESS* (thanks to Jeff Mincy) - * Improved manual a bit by including things that were only in - 'README'. - - Changes/New Features in 5.1.18: - * New 'ess-smart-underscore' function, now assigned to "_" by - default. Inserts 'ess-S-assign' (customizable " <- "), unless - inside string and comments where plain "_" is used instead. (MM) - * Fixes for longstanding interactive SAS breakage (RMH) - - Changes/New Features in 5.1.17: - * Documentation for Windows Installation (Rich Heiberger) - * removal of ess-vars, finalization of customize support (in the - sense that there is no more use of ess-vars, but that we need to - fix ess-cust) (AJ Rossini) - * Many small (and large) fixes/contributions (MMaechler) - * addition of the "S-equal" variable and provide 'M-x - ess-add-MM-keys' a way to remap "_" to 'ess-S-assign', typically " - <- ", but customizable. (MMaechler) - - Changes/New Features in 5.1.16: - * BUG FIXES - * Better SAS support - - Changes/New Features in 5.1.15: - * BUG FIXES - - Changes/New Features in 5.1.14: - * Yet more fixes to SAS mode, (Rich Heiberger and Rodney Sparapani) - * Customize support (for most Emacsen which support it) (AJRossini) - * ARC and ViSta support out of the box, and fixes for XLispStat - (AJRossini) - - Changes/New Features in 5.1.13: - * Version numbering finally all depending on the ./VERSION file, - thanks to Martin Maechler. - * Yet more fixes to SAS mode, thanks to Rich Heiberger. - - Changes/New Features in 5.1.12: - * Splus 5.1 stabilized, thanks to Martin Maechler, Bill Venables, - Chuck Taylor, and others. - * More fixes to SAS mode, thanks to Rodney Sparapani and Rich - Heiberger. - - Changes/New Features in 5.1.11: - * More fixes to Stata mode, thanks to Brendan Halpin - (mailto:brendan@essex.ac.uk). - * fixed bugs in ESS-elsewhere, thanks to many testers - * README.SPLUS4WIN has DETAILED instructions for S-PLUS 2000, thanks - to David Brahm (mailto:brahm@alum.mit.edu). - * Fixes to SAS mode, thanks to Rodney Sparapani - - Changes/New Features in 5.1.10: - * More fixes to Stata mode - * primitive generic version of ESS-elsewhere - * Small fixes to SAS/Stata. - - Changes/New Features in 5.1.9: - * Stata mode works - * Literate Data Analysis using Noweb works - - Changes/New Features in 5.1.8: - * Bug fixes - * R documentation mode defaults changed - - Changes/New Features in 5.1.2: - * able to use inferior iESS mode to communicate directly with a - running S-Plus 4.x process using the Microsoft DDE protocol. We - use the familiar (from Unix ESS) 'C-c C-n' and related key - sequences to send lines from the S-mode file to the inferior S - process. We continue to edit S input files in ESS[S] mode and - transcripts of previous S sessions in ESS Transcript mode. All - three modes know the S language, syntax, and indentation patterns - and provide the syntactic highlighting that eases the programming - tasks. - - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/announc.info b/elpa/ess-20191014.1343/announc.info deleted file mode 100644 index d2d23aef..00000000 --- a/elpa/ess-20191014.1343/announc.info +++ /dev/null @@ -1,735 +0,0 @@ -This is announc.info, produced by makeinfo version 6.5 from -announc.texi. - - -File: announc.info, Node: Announce - -1 ANNOUNCING ESS -**************** - -The ESS Developers proudly announce the release of ESS 18.10.3snapshot - - Emacs Speaks Statistics (ESS) provides an intelligent, consistent -interface between the user and the software. ESS interfaces with -R/S-PLUS, SAS, BUGS/JAGS, Stata and other statistical analysis packages -under the UNIX, GNU Linux, Microsoft Windows, macOS and other operating -systems. ESS is a package for the GNU Emacs text editor whose features -ESS uses to streamline the creation and use of statistical software. -ESS knows the syntax and grammar of statistical analysis packages and -provides consistent display and editing features based on that -knowledge. ESS assists in interactive and batch execution of statements -written in these statistical analysis languages. - - ESS is freely available under the GNU General Public License (GPL). -Please read the file COPYING which comes with the distribution, for more -information about the license. For more detailed information, please -read the README files that come with ESS. - -* Menu: - -* Latest Version:: -* Current Features:: -* Requirements:: -* Mailing List:: -* Reporting Bugs:: -* Authors:: -* License:: -* New Features:: - - -File: announc.info, Node: Latest Version, Next: Current Features, Prev: Announce, Up: Announce - -1.1 Getting the Latest Version -============================== - -ESS supports GNU Emacs versions 25.1 and newer. - - ESS is most likely to work with current/recent versions of the -following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. - - To build the PDF documentation, you will need a version of TeX Live -or texinfo that includes texi2dvi. - - There are two main methods used for installing ESS. You may install -from a third-party repository or from source code. Once you install it, -you must also activate or load ESS in each Emacs session, though -installation from a third-party repository likely takes care of that for -you. See *note Activating and Loading ESS:: for more details. - -* Menu: - -* Installing from a third-party repository:: -* Installing from source:: -* Activating and Loading ESS:: -* Check Installation:: - - -File: announc.info, Node: Installing from a third-party repository, Next: Installing from source - -1.2 Installing from a third-party repository -============================================ - -ESS is packaged by many third party repositories. Many GNU/Linux -distributions package it, usually with the name "emacs-ess" or similar. - - ESS is also available through Milkypostman’s Emacs Lisp Package -Archive (MELPA), a popular repository for Emacs packages. Instructions -on how to do so are found on MELPA's website (https://melpa.org/). -MELPA also hosts MELPA-stable with stable ESS builds. You may choose -between MELPA with the latest and greatest features (and bugs) or -MELPA-stable, which may lag a bit behind but should be more stable. - - After installing, users should make sure ESS is activated or loaded -in each Emacs session. See *note Activating and Loading ESS::. -Depending on install method, this may be taken care of automatically. - - -File: announc.info, Node: Installing from source, Next: Activating and Loading ESS, Prev: Installing from a third-party repository - -1.3 Installing from source -========================== - -Stable versions of ESS are available at the ESS web page -(https://ess.r-project.org) as a .tgz file or .zip file. ESS releases -are GPG-signed, you should check the signature by downloading the -accompanying '.sig' file and doing: - - gpg --verify ess-18.10.tgz.sig - - Alternatively, you may download the git repository. ESS is currently -hosted on GitHub: . 'git clone -https://github.com/emacs-ess/ESS.git' will download it to a new -directory 'ESS' in the current working directory. - - We will refer to the location of the ESS source files as -'/path/to/ESS/' hereafter. - - After installing, users should make sure they activate or load ESS in -each Emacs session, see *note Activating and Loading ESS:: - - Optionally, compile elisp files, build the documentation, and the -autoloads: - cd /path/to/ESS/ - make - Without this step the documentation, reference card, and autoloads -will not be available. Uncompiled ESS will also run slower. - - Optionally, you may make ESS available to all users of a machine by -installing it site-wide. To do so, run 'make install'. You might need -administrative privileges: - - make install - - The files are installed into '/usr/share/emacs' directory. For this -step to run correctly on macOS, you will need to adjust the 'PREFIX' -path in 'Makeconf'. The necessary code and instructions are commented -in that file. - - -File: announc.info, Node: Activating and Loading ESS, Next: Check Installation, Prev: Installing from source - -1.4 Activating and Loading ESS -============================== - -After installing ESS, you must activate or load it each Emacs session. -ESS can be autoloaded, and if you used a third-party repository (such as -your Linux distribution or MELPA) to install, you can likely skip this -section and proceed directly to *note Check Installation:: - - Otherwise, you may need to add the path to ESS to 'load-path' with: - - (add-to-list 'load-path "/path/to/ESS/lisp") - - You then need to decide whether to take advantage of deferred loading -(which will result in a faster Emacs startup time) or require ESS when -Emacs is loaded. To autoload ESS when needed (note that if installed -from source, you must have run 'make'): - - (load "ess-autoloads") - - To require ESS on startup, you can either put - - (require 'ess-site) - - or - - (require 'ess-r-mode) - - In your configuration file, depending on whether you want all ESS -features or only R related features. - - -File: announc.info, Node: Check Installation, Prev: Activating and Loading ESS - -1.5 Check Installation -====================== - -Restart Emacs and check that ESS was loaded from a correct location with -'M-x ess-version'. - - -File: announc.info, Node: Current Features, Next: Requirements, Prev: Latest Version, Up: Announce - -1.6 Current Features -==================== - - * Languages Supported: - * S family (R, S, and S+ AKA S-PLUS) - * SAS - * BUGS/JAGS - * Stata - * Julia - * Editing source code (S family, SAS, BUGS/JAGS, Stata, Julia) - * Syntactic indentation and highlighting of source code - * Partial evaluation of code - * Loading and error-checking of code - * Source code revision maintenance - * Batch execution (SAS, BUGS/JAGS) - * Use of imenu to provide links to appropriate functions - * Interacting with the process (S family, SAS, Stata, Julia) - * Command-line editing - * Searchable Command history - * Command-line completion of S family object names and file - names - * Quick access to object lists and search lists - * Transcript recording - * Interface to the help system - * Transcript manipulation (S family, Stata) - * Recording and saving transcript files - * Manipulating and editing saved transcripts - * Re-evaluating commands from transcript files - * Interaction with Help Pages and other Documentation (R) - * Fast Navigation - * Sending Examples to running ESS process. - * Fast Transfer to Further Help Pages - * Help File Editing (R) - * Syntactic indentation and highlighting of source code. - * Sending Examples to running ESS process. - * Previewing - - -File: announc.info, Node: Requirements, Next: Mailing List, Prev: Current Features, Up: Announce - -1.7 Requirements -================ - -ESS supports GNU Emacs versions 25.1 and newer. - - ESS is most likely to work with current/recent versions of the -following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. - - To build the PDF documentation, you will need a version of TeX Live -or texinfo that includes texi2dvi. - - -File: announc.info, Node: Mailing List, Next: Reporting Bugs, Prev: Requirements, Up: Announce - -1.8 Mailing List -================ - -There is a mailing list for discussions and announcements relating to -ESS. Join the list by sending an e-mail with "subscribe ess-help" (or -"help") in the body to ; contributions -to the list may be mailed to . Rest assured, -this is a fairly low-volume mailing list. - - The purposes of the mailing list include - - * helping users of ESS to get along with it. - * discussing aspects of using ESS. - * suggestions for improvements. - * announcements of new releases of ESS. - * posting small patches to ESS. - - -File: announc.info, Node: Reporting Bugs, Next: Authors, Prev: Mailing List, Up: Announce - -1.9 Reporting Bugs -================== - -Please send bug reports, suggestions etc. to , -or post them on our github issue tracker -(https://github.com/emacs-ess/ESS/issues) - - The easiest way to do this is within Emacs by typing - - 'M-x ess-submit-bug-report' - - This also gives the maintainers valuable information about your -installation which may help us to identify or even fix the bug. - - If Emacs reports an error, backtraces can help us debug the problem. -Type "M-x set-variable RET debug-on-error RET t RET". Then run the -command that causes the error and you should see a *Backtrace* buffer -containing debug information; send us that buffer. - - Note that comments, suggestions, words of praise and large cash -donations are also more than welcome. - - -File: announc.info, Node: Authors, Next: License, Prev: Reporting Bugs, Up: Announce - -1.10 Authors -============ - - * A.J. Rossini (mailto:blindglobe@gmail.com) - * Richard M. Heiberger (mailto:rmh@temple.edu) - * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) - * Martin Maechler (mailto:maechler@stat.math.ethz.ch) - * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) - * Stephen Eglen (mailto:stephen@gnu.org) - * Sebastian P. Luque (mailto:spluque@gmail.com) - * Henning Redestig (mailto:henning.red@googlemail.com) - * Vitalie Spinu (mailto:spinuvit@gmail.com) - * Lionel Henry (mailto:lionel.hry@gmail.com) - * J. Alexander Branham (mailto:alex.branham@gmail.com) - - -File: announc.info, Node: License, Next: New Features, Prev: Authors, Up: Announce - -1.11 License -============ - -The source and documentation of ESS is free software. You can -redistribute it and/or modify it under the terms of the GNU General -Public License as published by the Free Software Foundation; either -version 2, or (at your option) any later version. - - ESS is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License in -the file COPYING in the same directory as this file for more details. - - -File: announc.info, Node: New Features, Prev: License, Up: Announce - -1.12 New Features -================= - -Changes and New Features in 19.04 (unreleased): - - * ESS[R]: There is a new menu entry for reloading the R process. It - is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same - process name and start arguments that were used to start the - process. - - * iESS: Process runners now return the inferior buffer. Note that - callers of inferior runners should not assume that the current - buffer has been set to the inferior buffer. Instead, use - 'with-current-buffer' with the return value of the inferior. - - * iESS[SAS]: The SAS keymap was only set in iESS buffers called - '*SAS*'. This is now fixed. - - * ESS[R]: Fixed longstanding indentation issues involving '::' and - ':::' operators. - - * Implement a more reliable check for the process busy state. - Background actions such as completion and directory synchronization - should not block the process and should not cause printing of the - extraneous output to the interpreter. - - * Activate 'goto-address-mode' for url and email highlighting in - inferior buffers. - - * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. - Users who liked the previous behavior (i.e. underscore inserting - "<-") should bind 'ess-insert-assign' to the underscore in their - Emacs initialization file. For example, '(define-key - ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key - inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it - in all ESS R buffers. - - * ESS major modes are now defined using 'define-derived-mode'. This - makes ESS major modes respect modern conventions such as having - -mode-hook and -mode-map. Users are encouraged - to place customizations under the appropriate mode. - - * New option ess-auto-width controls setting the width option on - window changes. Users can change it to 'frame, 'window, or an - integer. See the documentation for details. - 'ess-auto-width-visible' controls visibility. - - * ESS now respects 'display-buffer-alist'. Users can now use - 'display-buffer-alist' to manage how and where windows appear. See - *Note (ess)Controlling buffer display:: for more information and - examples. - - * 'ess-roxy-mode' can now be enabled in non-R buffers. This is - primarily intended to support roxygen documentation for cpp - buffers. Preview functionality is not supported outside R buffers. - - * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. - - * 'ess-style' now has effects when set as a file or directory local - variable. - - * 'ess-default-style' is now obsolete, use 'ess-style' instead. - - * Options for 'ess-gen-proc-buffer-name-function' have been renamed. - ess-gen-proc-buffer-name:projectile-or-simple was renamed to - ess-gen-proc-buffer-name:project-or-simple and - ess-gen-proc-buffer-name:projectile-or-directory was renamed to - ess-gen-proc-buffer-name:project-or-directory. As the name - suggests, these now rely on project.el (included with Emacs) rather - than projectile.el, which is a third-party package. - - * ESS[R]: devtools commands ask about saving modified buffers before - running. Users can disable the questioning with - 'ess-save-silently'. - - * ESS[R] help pages now provide links to other help topics. This is - similar with what you would see with, for example - 'options(help_type = ``html'')' but works with the plain-text - version as well. This only works with 'options(useFancyQuotes = - TRUE)' (the default). - - * 'ess-rdired' buffers now derive from tabulated-list-mode. They - should look better and be a bit faster overall. The size column - now displays object sizes in bytes. - - * 'ess-rdired' buffers now auto-update. The frequency is governed by - the new option 'ess-rdired-auto-update-interval'. - - * ESS[R]: 'electric-layout-mode' is now supported. This - automatically inserts a newline after an opening curly brace in R - buffers. To enable it, customize 'ess-r-mode-hook'. - - * ESS[R]: imenu now supports assignment with the equals sign. - - * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. - - * ESS removed support for many unused languages. This includes old - versions of S+, ARC, OMG, VST, and XLS. - - The following have been made obsolete or removed, see their -documentation for more detail: - - * Libraries for literate data analysis are obsolete and not loaded by - default. This includes 'ess-noweb', 'ess-swv', and related - functionality like 'Rnw-mode'. Users are encouraged to switch to - one of several other packages that deal with these modes. For - example, polymode , - , or markdown-mode with edit-indirect - . - - * Support for 'auto-complete' is obsolete. The 'auto-complete' - package is unmaintained and so ESS support is now obsolete. Users - are encouraged to switch to 'company-mode' instead. - - * User options for controlling display of buffers. This includes - 'ess-show-buffer-action', 'inferior-ess-same-window', - 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See - above about ESS respecting 'display-buffer-alist'. - - * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. - Use the Emacs-wide setting of 'tab-always-indent' instead. - - * 'inferior-ess-*-start-file' variables. All modes except Stata did - not respect customization of this variable. In order to load a - file on startup, you should put a function on - 'ess-*-post-run-hook'. - - Bug Fixes in 18.10.3: - * More 'Makefile' fixes, notably installing '*.el's. - - Bug Fixes in 18.10.2: - * ESS[R] Fix namespace evaluation in non-installed packages. - Evaluation is directed into GlobalEnv as originally intended. - * 'Makefile' fixes, notably for 'make install' and including full - docs in the tarballs. - - Bug Fixes in 18.10-1: - * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and - 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave - as the old versions of 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step'. - - Changes and New Features in 18.10: - - * This is the last release to support Emacs older than 25.1. Going - forward, only GNU Emacs 25.1 and newer will be supported. Soon - after this release, support for older Emacs versions will be - dropped from the git master branch. Note that MELPA uses the git - master branch to produce ESS snapshots, so if you are using Emacs < - 25.1 from MELPA and are unable to upgrade, you should switch to - MELPA-stable. - - * ESS now displays the language dialect in the mode-line. So, for - example, R buffers will now show ESS[R] rather than ESS[S]. - - * The ESS manual has been updated and revised. - - * The ESS initialization process has been further streamlined. If - you update the autoloads (which installation from 'package-install' - does), you should not need to '(require 'ess-site)' at all, as - autoloads should automatically load ESS when it is needed (e.g. - the first time an R buffer is opened). In order to defer loading - your ESS config, you may want to do something like - '(with-require-after-load "ess" )' in your Emacs - init file. Users of the popular 'use-package' Emacs package can - now do '(use-package ess :defer t)' to take advantage of this - behavior. *Note (ess)Activating and Loading ESS:: for more - information on this feature. - - * ESS now respects Emacs conventions for keybindings. This means - that The 'C-c [letter]' bindings have been removed. This affects - 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in - 'sas-mode-local-map'; 'C-c f', which was bound to - 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', - which was bound to 'ess-handy-commands' in 'Rd-mode-map', - 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' - - * Functions 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step' now behave consistently with - other evaluation function inside a package. - - * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets - the working directory to the root of the current package including - for example C or C++ files within '/src'). - - * ESS[R]: Long + + prompts in the inferior no longer offset output. - - * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This - strips the entire + + sequence. - - * ESS modes now inherit from 'prog-mode'. In the next release, ESS - modes will use 'define-derived-mode' so that each mode will have - (for example) its own hooks and keymaps. - - * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. - Users need to install the 'lintr' package to use it. Customizable - options include 'ess-use-flymake', 'ess-r-flymake-linters', and - 'ess-r-flymake-lintr-cache'. - - * ESS[R]: Gained support for xref in Emacs 25+. *Note (emacs)Xref:: - - * ESS[R]: The startup screen is cleaner. It also displays the - startup directory with an explicit 'setwd()'. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[R]: 'Makevars' files open with 'makefile-mode'. - - * New variable 'ess-write-to-dribble'. This allows users to disable - the dribble ('*ESS*') buffer if they wish. - - * All of the '*-program-name' variables have been renamed to - '*-program'. Users who previously customized e.g. - 'inferior-ess-R-program-name' will need to update their - customization to 'inferior-ess-R-program'. These variables are - treated as risky variables. - - * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It - provides similar functionality but for any keybinding, not just - '_'. For instance if you bind it to ';', repeated invocations - cycle through between assignment and inserting ';'. - - * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the - documentation for details. New user customization option - 'ess-assign-list' controls which assignment operators are cycled. - - * ESS[R] In remote sessions, the ESSR package is now fetched from - GitHub. - - * Commands that send the region to the inferior process now deal with - rectangular regions. See the documentation of 'ess-eval-region' - for details. This only works on Emacs 25.1 and newer. - - * ESS[R]: Improvements to interacting with iESS in non-R files. - Interaction with inferior process in non-R files within packages - (for instance C or C++ files) has been improved. This is a work in - progress. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in - JAGS mode. - - Many improvements to fontification: - - * Improved customization for faces. ESS now provides custom faces - for (nearly) all faces used and places face customization options - into their own group. Users can customize these options using 'M-x - customize-group RET ess-faces'. - - * Many new keywords were added to 'ess-R-keywords' and - 'ess-R-modifiers'. See the documentation for details. - - * ESS[R]: 'in' is now only fontified when inside a 'for' construct. - This avoids spurious fontification, especially in the output buffer - where 'in' is a common English word. - - * ESS: Font-lock keywords are now generated lazily. That means you - can now add or remove keywords from variables like 'ess-R-keywords' - in your Emacs configuration file after loading ESS (i.e. in the - ':config' section for 'use-package' users). - - * ESS[R]: Fontification of roxygen '@param' keywords now supports - comma-separated parameters. - - * ESS[R]: Certain keywords are only fontified if followed by a - parenthesis. Function-like keywords such as 'if ()' or 'stop()' - are no longer fontified as keyword if not followed by an opening - parenthesis. The same holds for search path modifiers like - 'library()' or 'require()'. - - * ESS[R]: Fixed fontification toggling. Especially certain syntactic - elements such as '%op%' operators and backquoted function - definitions. - - * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. - This command asks with completion for a font-lock group to toggle. - This functionality is equivalent to the font-lock menu. - - Notable bug fixes: - - * 'prettify-symbols-mode' no longer breaks indentation. This is - accomplished by having the pretty symbols occupy the same number of - characters as their non-pretty cousins. You may customize the new - variable 'ess-r-prettify-symbols' to control this behavior. - - * ESS: Inferior process buffers are now always displayed on startup. - Additionally, they don't hang Emacs on failures. - - Obsolete libraries, functions, and variables: - - * The 'ess-r-args.el' library has been obsoleted and will be removed - in the next release. Use 'eldoc-mode' instead, which is on by - default. - - * Functions and options dealing with the smart assign key are - obsolete. The following functions have been made obsolete and will - be removed in the next release of ESS: 'ess-smart-S-assign', - 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', - 'ess-disable-smart-S-assign'. - - The variable 'ess-smart-S-assign-key' is now deprecated and will be - removed in the next release. If you would like to continue using - '_' for inserting assign in future releases, please bind - 'ess-insert-assign' in 'ess-mode-map' the normal way. - - * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. - Use 'ess-s-versions' instead. You may pass arguments by starting - the inferior process with the universal argument. - - Changes and New Features in 17.11: - - * The ESS initialization process has been streamlined. You can now - load the R and Stata modes independently from the rest of ESS. Just - put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your - init file. This is for experienced Emacs users as this requires - setting up autoloads for '.R' files manually. We will keep - maintaining 'ess-site' for easy loading of all ESS features. - - * Reloading and quitting the process is now more robust. If no - process is attached, ESS now switches automatically to one - (prompting you for selection if there are several running). - Reloading and quitting will now work during a debug session or when - R is prompting for input (for instance after a crash). Finally, - the window configuration is saved and restored after reloading to - prevent the buffer of the new process from capturing the cursor. - - * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working - directory of the current process to the current package directory. - - * ESS[R] Lookup for references in inferior buffers has been improved. - New variable 'ess-r-package-source-roots' contains package - sub-directories which are searched recursively during the file - lookup point. Directories in 'ess-tracebug-search-path' are now - also searched recursively. - - * ESS[R] Namespaced evaluation is now automatically enabled only in - the 'R/' directory. This way ESS will not attempt to update - function definitions from a package if you are working from e.g. a - test file. - - Changes and New Features in 16.10: - - * ESS[R]: Syntax highlighting is now more consistent. Backquoted - names are not fontified as strings (since they really are - identifiers). Furthermore they are now correctly recognized when - they are function definitions or function calls. - * ESS[R]: Backquoted names and '%op%' operators are recognized as - sexp. This is useful for code navigation, e.g. with 'C-M-f' and - 'C-M-b'. - * ESS[R]: Integration of outline mode with roxygen examples fields. - You can use outline mode's code folding commands to fold the - examples field. This is especially nice to use with well - documented packages with long examples set. Set - 'ess-roxy-fold-examples' to non-nil to automatically fold the - examples field when you open a buffer. - * ESS[R]: New experimental feature: syntax highlighting in roxygen - examples fields. This is turned off by default. Set - 'ess-roxy-fontify-examples' to non-nil to try it out. - * ESS[R]: New package development command 'ess-r-devtools-ask' bound - to 'C-c C-w C-a'. It asks with completion for any devtools command - that takes 'pkg' as argument. - * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. - Currently only implemented for R. The R method runs - 'inferior-ess-r-reload-hook' on reloading. - * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers - as well. - - Bug fixes in 16.10: - * ESS[R]: Fix broken (un)flagging for debugging inside packages - * ESS[R]: Fixes (and improvements) in Package development - * ESS[R]: Completion no longer produces '...=' inside 'list( )'. - * ESS[R]: Better debugging and tracing in packages. - * ESS[R]: Better detection of symbols at point. - * ESS[R]: No more spurious warnings on deletion of temporary files. - * ESS[julia]: help and completion work (better) - * ESS[julia]: available via 'ess-remote' - - Changes and New Features in 16.04: - - * ESS[R]: 'developer' functionality has been refactored. The new - user interface consists of a single command - 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once - an evaluation environment has been set with, all subsequent ESS - evaluation will source the code into that environment. By default, - for file within R packages the evaluation environment is set to the - package environment. Set 'ess-r-package-auto-set-evaluation-env' - to 'nil' to disable this. - * ESS[R]: New 'ess-r-package-mode' This development mode provides - features to make package development easier. Currently, most of - the commands are based on the 'devtools' packages and are - accessible with 'C-c C-w' prefix. See the documentation of - 'ess-r-package-mode' function for all available commands. With - 'C-u' prefix each command asks for extra arguments to the - underlying devtools function. This mode is automatically enabled - in all files within R packages and is indicated with '[pkg:NAME]' - in the mode-line. - * ESS[R]: Help lookup has been improved. It is now possible to get - help for namespaced objects such as pkg::foobar. Furthermore, ESS - recognizes more reliably when you change 'options('html_type')'. - * ESS[R]: New specialized breakpoints for debugging magrittr pipes - * ESS: ESS now implements a simple message passing interface to - communicate between ESS and inferior process. - - Bug fixes in 16.04: - * ESS[R]: Roxygen blocks with backtics are now correctly filled - * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' - * ESS[R]: Error highlighting now understands 'testthat' type errors - * ESS[Julia]: Added getwd and setwd generic commands - - - -Tag Table: -Node: Announce75 -Node: Latest Version1298 -Node: Installing from a third-party repository2241 -Node: Installing from source3192 -Node: Activating and Loading ESS4788 -Node: Check Installation5866 -Node: Current Features6090 -Node: Requirements7633 -Node: Mailing List8068 -Node: Reporting Bugs8774 -Node: Authors9654 -Node: License10338 -Node: New Features10988 - -End Tag Table diff --git a/elpa/ess-20191014.1343/authors.info b/elpa/ess-20191014.1343/authors.info deleted file mode 100644 index 9db52814..00000000 --- a/elpa/ess-20191014.1343/authors.info +++ /dev/null @@ -1,19 +0,0 @@ -This is authors.info, produced by makeinfo version 6.5 from -authors.texi. - - * A.J. Rossini (mailto:blindglobe@gmail.com) - * Richard M. Heiberger (mailto:rmh@temple.edu) - * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) - * Martin Maechler (mailto:maechler@stat.math.ethz.ch) - * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) - * Stephen Eglen (mailto:stephen@gnu.org) - * Sebastian P. Luque (mailto:spluque@gmail.com) - * Henning Redestig (mailto:henning.red@googlemail.com) - * Vitalie Spinu (mailto:spinuvit@gmail.com) - * Lionel Henry (mailto:lionel.hry@gmail.com) - * J. Alexander Branham (mailto:alex.branham@gmail.com) - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/bugrept.info b/elpa/ess-20191014.1343/bugrept.info deleted file mode 100644 index 0da6c159..00000000 --- a/elpa/ess-20191014.1343/bugrept.info +++ /dev/null @@ -1,26 +0,0 @@ -This is bugrept.info, produced by makeinfo version 6.5 from -bugrept.texi. - -Please send bug reports, suggestions etc. to , -or post them on our github issue tracker -(https://github.com/emacs-ess/ESS/issues) - - The easiest way to do this is within Emacs by typing - - 'M-x ess-submit-bug-report' - - This also gives the maintainers valuable information about your -installation which may help us to identify or even fix the bug. - - If Emacs reports an error, backtraces can help us debug the problem. -Type "M-x set-variable RET debug-on-error RET t RET". Then run the -command that causes the error and you should see a *Backtrace* buffer -containing debug information; send us that buffer. - - Note that comments, suggestions, words of praise and large cash -donations are also more than welcome. - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/credits.info b/elpa/ess-20191014.1343/credits.info deleted file mode 100644 index 254e77f4..00000000 --- a/elpa/ess-20191014.1343/credits.info +++ /dev/null @@ -1,81 +0,0 @@ -This is credits.info, produced by makeinfo version 6.5 from -credits.texi. - -The ESS environment is built on the open-source projects of many -contributors, dating back to 1989 where Doug Bates and Ed Kademan wrote -S-mode to edit S and Splus files in GNU Emacs. Frank Ritter and Mike -Meyer added features, creating version 2. Meyer and David Smith made -further contributions, creating version 3. For version 4, David Smith -provided significant enhancements to allow for powerful process -interaction. - - John Sall wrote GNU Emacs macros for SAS source code around 1990. -Tom Cook added functions to submit jobs, review listing and log files, -and produce basic views of a dataset, thus creating a SAS-mode which was -distributed in 1994. - - In 1994, A.J. Rossini extended S-mode to support XEmacs. Together -with extensions written by Martin Maechler, this became version 4.7 and -supported S, Splus, and R. In 1995, Rossini extended SAS-mode to work -with XEmacs. - - In 1997, Rossini merged S-mode and SAS-mode into a single Emacs -package for statistical programming; the product of this marriage was -called ESS version 5. Richard M. Heiberger designed the inferior mode -for interactive SAS and SAS-mode was further integrated into ESS. Thomas -Lumley's Stata mode, written around 1996, was also folded into ESS. More -changes were made to support additional statistical languages, -particularly XLispStat. - - ESS initially worked only with Unix statistics packages that used -standard-input and standard-output for both the command-line interface -and batch processing. ESS could not communicate with statistical -packages that did not use this protocol. This changed in 1998 when -Brian Ripley demonstrated use of the Windows Dynamic Data Exchange (DDE) -protocol with ESS. Heiberger then used DDE to provide interactive -interfaces for Windows versions of Splus. In 1999, Rodney A. Sparapani -and Heiberger implemented SAS batch for ESS relying on files, rather -than standard-input/standard-output, for Unix, Windows and Mac. In -2001, Sparapani added BUGS batch file processing to ESS for Unix and -Windows. - - * The multiple process code, and the idea for - 'ess-eval-line-and-next-line' are by Rod Ball. - - * Thanks to Doug Bates for many useful suggestions. - - * Thanks to Martin Maechler for reporting and fixing bugs, providing - many useful comments and suggestions, and for maintaining the ESS - mailing lists. - - * Thanks to Frank Ritter for updates, particularly the menu code, and - invaluable comments on the manual. - - * Thanks to Ken'ichi Shibayama for his excellent indenting code, and - many comments and suggestions. - - * Thanks to Aki Vehtari for adding interactive BUGS support. - - * Thanks to Brendan Halpin for bug-fixes and updates to Stata-mode. - - * Last, but definitely not least, thanks to the many ESS users and - contributors to the ESS mailing lists. - - _ESS_ is being developed and currently maintained by - - * A.J. Rossini (mailto:blindglobe@gmail.com) - * Richard M. Heiberger (mailto:rmh@temple.edu) - * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) - * Martin Maechler (mailto:maechler@stat.math.ethz.ch) - * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) - * Stephen Eglen (mailto:stephen@gnu.org) - * Sebastian P. Luque (mailto:spluque@gmail.com) - * Henning Redestig (mailto:henning.red@googlemail.com) - * Vitalie Spinu (mailto:spinuvit@gmail.com) - * Lionel Henry (mailto:lionel.hry@gmail.com) - * J. Alexander Branham (mailto:alex.branham@gmail.com) - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/currfeat.info b/elpa/ess-20191014.1343/currfeat.info deleted file mode 100644 index 63300d7c..00000000 --- a/elpa/ess-20191014.1343/currfeat.info +++ /dev/null @@ -1,42 +0,0 @@ -This is currfeat.info, produced by makeinfo version 6.5 from -currfeat.texi. - - * Languages Supported: - * S family (R, S, and S+ AKA S-PLUS) - * SAS - * BUGS/JAGS - * Stata - * Julia - * Editing source code (S family, SAS, BUGS/JAGS, Stata, Julia) - * Syntactic indentation and highlighting of source code - * Partial evaluation of code - * Loading and error-checking of code - * Source code revision maintenance - * Batch execution (SAS, BUGS/JAGS) - * Use of imenu to provide links to appropriate functions - * Interacting with the process (S family, SAS, Stata, Julia) - * Command-line editing - * Searchable Command history - * Command-line completion of S family object names and file - names - * Quick access to object lists and search lists - * Transcript recording - * Interface to the help system - * Transcript manipulation (S family, Stata) - * Recording and saving transcript files - * Manipulating and editing saved transcripts - * Re-evaluating commands from transcript files - * Interaction with Help Pages and other Documentation (R) - * Fast Navigation - * Sending Examples to running ESS process. - * Fast Transfer to Further Help Pages - * Help File Editing (R) - * Syntactic indentation and highlighting of source code. - * Sending Examples to running ESS process. - * Previewing - - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/dir b/elpa/ess-20191014.1343/dir deleted file mode 100644 index 3623cfa5..00000000 --- a/elpa/ess-20191014.1343/dir +++ /dev/null @@ -1,19 +0,0 @@ -This is the file .../info/dir, which contains the -topmost node of the Info hierarchy, called (dir)Top. -The first time you invoke Info you start off looking at this node. - -File: dir, Node: Top, This is the top of the INFO tree - - This (the Directory node) gives a menu of major topics. - Typing "q" exits, "?" lists all Info commands, "d" returns here, - "h" gives a primer for first-timers, - "mEmacs" visits the Emacs manual, etc. - - In Emacs, you can click mouse button 2 on a menu item or cross reference - to select it. - -* Menu: - -Emacs -* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, - BUGS/JAGS and Stata). diff --git a/elpa/ess-20191014.1343/ess-autoloads.el b/elpa/ess-20191014.1343/ess-autoloads.el deleted file mode 100644 index 7de8a602..00000000 --- a/elpa/ess-20191014.1343/ess-autoloads.el +++ /dev/null @@ -1,405 +0,0 @@ -;;; ess-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) - -;;;### (autoloads nil "ess" "ess.el" (23994 46764 990680 902000)) -;;; Generated autoloads from ess.el - -(autoload 'ess-version "ess" "\ -Return a string with ESS version information. - -\(fn)" t nil) - -(autoload 'ess-submit-bug-report "ess" "\ -Submit a bug report to the ESS maintainers. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-bugs-d" "ess-bugs-d.el" (23994 46764 917667 -;;;;;; 161000)) -;;; Generated autoloads from ess-bugs-d.el - -(autoload 'ess-bugs-mode "ess-bugs-d" "\ -Major mode for BUGS. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.[Bb][Uu][Gg]\\'" . ess-bugs-mode)) - -(add-to-list 'auto-mode-alist '("\\.[Bb][Oo][Gg]\\'" . ess-bugs-mode)) - -(add-to-list 'auto-mode-alist '("\\.[Bb][Mm][Dd]\\'" . ess-bugs-mode)) - -;;;*** - -;;;### (autoloads nil "ess-custom" "ess-custom.el" (23994 46764 953959 -;;;;;; 908000)) -;;; Generated autoloads from ess-custom.el - -(defvar ess-lisp-directory (file-name-directory (or load-file-name buffer-file-name)) "\ -Directory containing ess-site.el(c) and other ESS Lisp files.") - -(custom-autoload 'ess-lisp-directory "ess-custom" t) - -(add-to-list 'load-path ess-lisp-directory) - -(add-to-list 'load-path (file-name-as-directory (expand-file-name "obsolete" ess-lisp-directory))) - -(put 'ess-indent-offset 'safe-local-variable #'numberp) - -(put 'ess-style 'safe-local-variable #'symbolp) - -;;;*** - -;;;### (autoloads nil "ess-gretl" "ess-gretl.el" (23994 46764 949104 -;;;;;; 258000)) -;;; Generated autoloads from ess-gretl.el - -(autoload 'ess-gretl-mode "ess-gretl" "\ -Major mode for editing gretl source. See `ess-mode' for more help. - -\(fn)" t nil) - -(autoload 'gretl "ess-gretl" "\ -Call 'gretl', -Optional prefix (C-u) allows to set command line arguments, such as ---vsize. This should be OS agnostic. -If you have certain command line arguments that should always be passed -to gretl, put them in the variable `inferior-gretl-args'. - -\(fn &optional START-ARGS)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-inf" "ess-inf.el" (23994 46764 956265 -;;;;;; 802000)) -;;; Generated autoloads from ess-inf.el - -(autoload 'ess-load-file "ess-inf" "\ -Load FILENAME into an inferior ESS process. -This handles Tramp when working on a remote. - -\(fn &optional FILENAME)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-jags-d" "ess-jags-d.el" (23994 46764 989659 -;;;;;; 375000)) -;;; Generated autoloads from ess-jags-d.el - -(autoload 'ess-jags-mode "ess-jags-d" "\ -Major mode for JAGS. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.[Jj][Aa][Gg]\\'" . ess-jags-mode)) - -;;;*** - -;;;### (autoloads nil "ess-julia" "ess-julia.el" (23994 46764 987711 -;;;;;; 280000)) -;;; Generated autoloads from ess-julia.el - -(autoload 'ess-julia-mode "ess-julia" "\ -Major mode for julia files. - -\(fn)" t nil) - -(autoload 'run-ess-julia "ess-julia" "\ -Start an inferior julia process. -Optional prefix START-ARGS (\\[universal-argument]) allows to set -command line arguments, such as --load=. This should be OS -agnostic. If you have certain command line arguments that should -always be passed to julia, put them in the variable -`inferior-julia-args'. - -\(fn &optional START-ARGS)" t nil) - -(defalias 'julia #'run-ess-julia) - -;;;*** - -;;;### (autoloads nil "ess-mode" "ess-mode.el" (23994 46764 952949 -;;;;;; 668000)) -;;; Generated autoloads from ess-mode.el - -(autoload 'ess-mode "ess-mode" "\ -Major mode for editing ESS source. -Optional arg ALIST describes how to customize the editing mode. -Optional arg PROC-NAME is name of associated inferior process. - -\\{ess-mode-map} - -You can send text to the inferior ESS process from other buffers containing -ESS source. - `ess-eval-region' sends the current region to the ESS process. - `ess-eval-buffer' sends the current buffer to the ESS process. - `ess-eval-function' sends the current function to the ESS process. - `ess-eval-line' sends the current line to the ESS process. - `ess-switch-to-ESS' switches the current buffer to the ESS process buffer. - `ess-switch-to-end-of-ESS' switches the current buffer to the ESS process - buffer and puts point at the end of it. - - `ess-eval-region-and-go', `ess-eval-buffer-and-go', - `ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S - process buffer after sending their text. - - `ess-load-file' sources a file of commands to the ESS process. - -\\[ess-indent-command] indents for ESS code. -\\[backward-delete-char-untabify] converts tabs to spaces as it moves back. -Comments are indented in a similar way to Emacs-lisp mode: - `###' beginning of line - `##' the same level of indentation as the code - `#' the same column on the right, or to the right of such a - column if that is not possible.(default value 40). - \\[indent-for-comment] command automatically inserts such a - `#' in the right place, or aligns such a comment if it is - already inserted. -\\[ess-indent-exp] command indents each line of the syntactic unit following point. - -Variables controlling indentation style: - `ess-indent-offset' - Indentation of ESS statements within surrounding block. - The surrounding block's indentation is the indentation of the line on - which the open-brace appears. - `ess-offset-block' - Indentation of blocks opened with curly braces or anonymous parentheses. - `ess-offset-arguments' - Indentation of function arguments or bracket indices. - `ess-offset-arguments-newline' - Indentation of function arguments or bracket indices when the opening - delimiter is immediately followed by a newline. - `ess-offset-continued' - Indentation style for continued statements. - `ess-align-nested-calls' - Functions whose nested calls should be aligned. - `ess-align-arguments-in-calls' - Calls in which arguments should be aligned. - `ess-align-continuations-in-calls' - Whether ignore indentation after an operator in calls - `ess-align-blocks' - Blocks that should always be aligned vertically. - `ess-indent-from-lhs' - Whether function calls given as argument should be indented from the - parameter name. - `ess-indent-from-chain-start' - Whether to indent arguments from the first of several consecutive calls. - `ess-indent-with-fancy-comments' - Non-nil means distinguish between #, ##, and ### for indentation. - -Furthermore, \\[ess-set-style] command enables you to set up predefined ess-mode -indentation style. See `ess-style-alist' for predefined styles. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-r-mode" "ess-r-mode.el" (23994 46764 919684 -;;;;;; 960000)) -;;; Generated autoloads from ess-r-mode.el - -(autoload 'run-ess-r "ess-r-mode" "\ -Call 'R', the 'GNU S' system from the R Foundation. -Optional prefix (\\[universal-argument]) allows to set command line arguments, such as ---vsize. This should be OS agnostic. -If you have certain command line arguments that should always be passed -to R, put them in the variable `inferior-R-args'. - -START-ARGS can be a string representing an argument, a list of -such strings, or any other non-nil value. In the latter case, you -will be prompted to enter arguments interactively. - -\(fn &optional START-ARGS)" t nil) - -(defalias 'R #'run-ess-r) - -(autoload 'ess-r-mode "ess-r-mode" "\ -Major mode for editing R source. See `ess-mode' for more help. - -\(fn)" t nil) - -(defalias 'R-mode 'ess-r-mode) - -(defalias 'r-mode 'ess-r-mode) - -(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . ess-r-mode)) - -(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . ess-r-mode)) - -(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . ess-r-mode)) - -(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . ess-r-mode)) - -(add-to-list 'auto-mode-alist '("CITATION\\'" . ess-r-mode)) - -(autoload 'ess-r-transcript-mode "ess-r-mode" "\ -A Major mode for R transcript files. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.[Rr]out" . ess-r-transcript-mode)) - -(add-to-list 'interpreter-mode-alist '("Rscript" . ess-r-mode)) - -(add-to-list 'interpreter-mode-alist '("r" . ess-r-mode)) - -(add-to-list 'auto-mode-alist '("/Makevars\\(\\.win\\)?$" . makefile-mode)) - -(add-to-list 'auto-mode-alist '("DESCRIPTION$" . conf-colon-mode)) - -;;;*** - -;;;### (autoloads nil "ess-rd" "ess-rd.el" (23994 46764 952078 13000)) -;;; Generated autoloads from ess-rd.el - -(autoload 'Rd-mode "ess-rd" "\ -Major mode for editing R documentation source files. - -Type \\[list-abbrevs] to display the built-in abbrevs for Rd -keywords.To automatically turn on the abbrev(iate) features, add -the following to your Emacs configuration file: - - (add-hook 'Rd-mode-hook #'abbrev-mode) - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode)) - -;;;*** - -;;;### (autoloads nil "ess-rdired" "ess-rdired.el" (23994 46764 947244 -;;;;;; 10000)) -;;; Generated autoloads from ess-rdired.el - -(autoload 'ess-rdired "ess-rdired" "\ -Show R objects from the global environment in a separate buffer. -You may interact with these objects, see `ess-rdired-mode' for -details. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-roxy" "ess-roxy.el" (23994 46764 944362 -;;;;;; 342000)) -;;; Generated autoloads from ess-roxy.el - -(autoload 'ess-roxy-mode "ess-roxy" "\ -Minor mode for editing ROxygen documentation. - -\(fn &optional ARG)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-s-lang" "ess-s-lang.el" (23994 46764 906213 -;;;;;; 450000)) -;;; Generated autoloads from ess-s-lang.el - -(add-to-list 'auto-mode-alist '("\\.[Ss]t\\'" . S-transcript-mode)) - -(add-to-list 'auto-mode-alist '("\\.Sout" . S-transcript-mode)) - -;;;*** - -;;;### (autoloads nil "ess-sas-d" "ess-sas-d.el" (23994 46764 991721 -;;;;;; 22000)) -;;; Generated autoloads from ess-sas-d.el - -(autoload 'SAS-mode "ess-sas-d" "\ -Major mode for editing SAS source. See `ess-mode' for more help. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode)) - -;;;*** - -;;;### (autoloads nil "ess-sp6-d" "ess-sp6-d.el" (23994 46764 922686 -;;;;;; 856000)) -;;; Generated autoloads from ess-sp6-d.el - -(autoload 'S+-mode "ess-sp6-d" "\ -Major mode for editing S+ source. See `ess-mode' for more help. - -\(fn &optional PROC-NAME)" t nil) - -;;;*** - -;;;### (autoloads nil "ess-stata-mode" "ess-stata-mode.el" (23994 -;;;;;; 46764 927433 996000)) -;;; Generated autoloads from ess-stata-mode.el - -(autoload 'ess-stata-mode "ess-stata-mode" "\ -Major mode for editing Stata source. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.do\\'" . ess-stata-mode)) - -(add-to-list 'auto-mode-alist '("\\.ado\\'" . ess-stata-mode)) - -;;;*** - -;;;### (autoloads nil "ess-trns" "ess-trns.el" (23994 46764 942470 -;;;;;; 496000)) -;;; Generated autoloads from ess-trns.el - -(autoload 'ess-transcript-mode "ess-trns" "\ -Major mode for transcript files. - -Type \\[ess-transcript-send-command] to send a command in the -transcript to the current inferior process. \\[ess-transcript-copy-command] -copies the command but does not execute it, allowing you to edit it in -the process buffer first. - -Type \\[ess-transcript-clean-region] to delete all outputs and prompts -in the region, leaving only the commands. - -\(fn)" t nil) - -;;;*** - -;;;### (autoloads nil "essd-els" "essd-els.el" (23994 46764 908205 -;;;;;; 460000)) -;;; Generated autoloads from essd-els.el - -(autoload 'ess-remote "essd-els" "\ -Execute this command from within a buffer running a process. -It runs `ess-add-ess-process' to add the PROC-NAME to -`ess-process-name-alist' and to make it the -`ess-current-process-name'. It then prompts the user for an ESS -language and sets the editing characteristics appropriately. - -To use this command, first start a process on a remote computer by -manual use of telnet, rlogin, ssh, or some other protocol. Start the -relevant program (\"S\" or \"R\" or \"sas -stdio\") in that buffer. Once -you are talking to S or R or SAS, then do \\[ess-remote] to make -the current buffer an inferior-ess buffer with the right behavior for -the language you are currently working with. With S and R, use C-c -C-n to send lines over. With SAS, use C-c i -`ess-eval-line-and-step-invisibly' to send lines over invisibly. - -DIALECT is the desired ess-dialect. If nil, ask for dialect - -\(fn &optional PROC-NAME DIALECT)" t nil) - -;;;*** - -;;;### (autoloads nil nil ("ess-bugs-l.el" "ess-help.el" "ess-pkg.el" -;;;;;; "ess-r-completion.el" "ess-r-flymake.el" "ess-r-package.el" -;;;;;; "ess-r-syntax.el" "ess-r-xref.el" "ess-sas-a.el" "ess-sas-l.el" -;;;;;; "ess-site.el" "ess-stata-lang.el" "ess-toolbar.el" "ess-tracebug.el" -;;;;;; "ess-utils.el" "make-regexp.el") (23994 46764 993654 130000)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; ess-autoloads.el ends here diff --git a/elpa/ess-20191014.1343/ess-bugs-d.el b/elpa/ess-20191014.1343/ess-bugs-d.el deleted file mode 100644 index 9ae86d1d..00000000 --- a/elpa/ess-20191014.1343/ess-bugs-d.el +++ /dev/null @@ -1,296 +0,0 @@ -;;; ess-bugs-d.el --- ESS[BUGS] dialect -*- lexical-binding: t; -*- - -;; Copyright (C) 2008-2011 Rodney Sparapani - -;; Author: Rodney Sparapani -;; Created: 13 March 2008 -;; Maintainer: ESS-help - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Code: - -(require 'ess-bugs-l) -(require 'ess-utils) -(require 'ess-inf) -(require 'ess-mode) - -(defvar ess-bugs-command "OpenBUGS" "Default BUGS program in PATH.") -(make-local-variable 'ess-bugs-command) - -(defvar ess-bugs-monitor '("") "Default list of variables to monitor.") -(make-local-variable 'ess-bugs-monitor) - -(defvar ess-bugs-thin 1 "Default thinning parameter.") -(make-local-variable 'ess-bugs-thin) - -(defvar ess-bugs-chains 1 "Default number of chains.") -(make-local-variable 'ess-bugs-chains) - -(defvar ess-bugs-burnin 10000 "Default burn-in.") -(make-local-variable 'ess-bugs-burnin) - -(defvar ess-bugs-update 10000 "Default number of updates after burnin.") -(make-local-variable 'ess-bugs-update) - -(defvar ess-bugs-system nil "Default whether BUGS recognizes the system command.") - -(defvar ess-bugs-font-lock-keywords - (list - ;; .bug files - (cons "#.*\n" font-lock-comment-face) - - (cons "^[ \t]*\\(model\\|var\\)\\>" - font-lock-keyword-face) - - (cons (concat "\\ " ess-bugs-file-root ".bog 2>&1 " - ;; ess-bugs-batch-post-command "' > " ess-bugs-file-root ".bsh") - ;; (comint-send-input) - - ;; (insert "at -f " ess-bugs-file-root ".bsh now") - - ;; (comint-send-input) - - (insert "echo '" - ess-bugs-batch-pre-command " " bugs-command " < " - ess-bugs-file-root ".bmd > " ess-bugs-file-root ".bog 2>&1 " - ess-bugs-batch-post-command "' | at now") - - (comint-send-input) - )) - -(defun ess-bugs-na-bug () - "ESS[BUGS]: Perform Next-Action for .bug" - - (if (equal 0 (buffer-size)) (ess-bugs-switch-to-suffix ".bug") - ;else - (ess-save-and-set-local-variables) - (ess-bugs-switch-to-suffix ".bmd" - ess-bugs-chains ess-bugs-monitor ess-bugs-thin ess-bugs-burnin ess-bugs-update)) - ) - -;;;###autoload -(define-derived-mode ess-bugs-mode ess-mode "ESS[BUGS]" - "Major mode for BUGS." - (setq-local comment-start "#") - (setq font-lock-defaults '(ess-bugs-font-lock-keywords nil t)) - (setq ess-language "S") ; mimic S for ess-smart-underscore - (unless (when (fboundp 'w32-shell-dos-semantics) - (w32-shell-dos-semantics)) - (add-hook 'comint-output-filter-functions 'ess-bugs-exit-notify-sh))) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Bb][Uu][Gg]\\'" . ess-bugs-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Bb][Oo][Gg]\\'" . ess-bugs-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Bb][Mm][Dd]\\'" . ess-bugs-mode)) - -(defun ess-sci-to-dec () - "For BUGS/S family: Express +/-0.000E+/-0 or +/-0.0e+/-00 as a decimal." - (interactive) - (setq buffer-read-only nil) - (save-excursion (goto-char 0) - (save-match-data (let ((ess-temp-replacement-string nil) - (ess-temp-replacement-9 0) - (ess-temp-replacement-diff 0)) - (while (search-forward-regexp "-?[0-9][.][0-9][0-9]?[0-9]?[Ee][+-][0-9][0-9]?" nil t) - (setq ess-temp-replacement-string - (int-to-string (string-to-number (match-string 0)))) - (setq ess-temp-replacement-diff (- (match-end 0) (match-beginning 0))) - (save-match-data - (setq ess-temp-replacement-9 - (string-match "99999999999$" ess-temp-replacement-string)) - - (if (not ess-temp-replacement-9) - (setq ess-temp-replacement-9 - (string-match "000000000001$" ess-temp-replacement-string)))) - - (if ess-temp-replacement-9 - (setq ess-temp-replacement-string - (substring ess-temp-replacement-string 0 ess-temp-replacement-9))) - - (setq ess-temp-replacement-diff - (- ess-temp-replacement-diff (string-width ess-temp-replacement-string))) - - (while (> ess-temp-replacement-diff 0) - (setq ess-temp-replacement-string (concat ess-temp-replacement-string " ")) - (setq ess-temp-replacement-diff (- ess-temp-replacement-diff 1))) - - (replace-match ess-temp-replacement-string)))))) - -(provide 'ess-bugs-d) - -;;; ess-bugs-d.el ends here diff --git a/elpa/ess-20191014.1343/ess-bugs-l.el b/elpa/ess-20191014.1343/ess-bugs-l.el deleted file mode 100644 index dc886c26..00000000 --- a/elpa/ess-20191014.1343/ess-bugs-l.el +++ /dev/null @@ -1,289 +0,0 @@ -;;; ess-bugs-l.el --- ESS[BUGS] languages -*- lexical-binding: t; -*- - -;; Copyright (C) 2006-2011 Rodney Sparapani - -;; Author: Rodney Sparapani -;; Created: 16 August 2006 -;; Maintainer: ESS-help - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - - -;;; Code: - -(require 'shell) -(require 'ess-utils) -(defvar ess-bugs-command) -(defvar ess-bugs-chains) -(defvar ess-jags-command) -(defvar ess-jags-chains) -(defvar ess-bugs-default-bins) - -(declare-function ess-bugs-na-bug "ess-bugs-d") -(declare-function ess-jags-na-bug "ess-jags-d") -(declare-function ess-bugs-na-bmd "ess-bugs-d") -(declare-function ess-jags-na-jmd "ess-jags-d") - -(defgroup ess-bugs nil - "ESS: BUGS." - :group 'ess - :prefix "ess-") - -(defcustom ess-bugs-batch-method - (if (and ess-microsoft-p - (fboundp 'w32-shell-dos-semantics) - (w32-shell-dos-semantics)) - 'dos - 'sh) - "Method used by `ess-bugs-batch'. -The default is based on the value of the Emacs variable `system-type' -and, on Windows machines, the function `w32-shell-dos-semantics'. -'sh if *shell* runs a Bourne-like or a C-like Unix shell -'dos if *shell* runs a DOS-like Windows shell - -Unix users will get 'sh by default. - -Windows users running a DOS-like *shell* will get 'dos by default, -while those running a Unix-like *shell* will get 'sh by default. - -Users whose default is not 'sh, but are accessing a remote machine with -`telnet' or `ssh', should have the following in their init file: - (setq-default ess-bugs-batch-method 'sh)" - :group 'ess-bugs - :type '(choice (const 'sh :tag "Bourne/C-like Unix Shell") - (const 'dos :tag "DOS-like Windows shell"))) - -(defcustom ess-bugs-batch-post-command - (if (equal ess-bugs-batch-method 'sh) "&" " ") - "ESS[BUGS]: Modifiers at the end of the batch BUGS command line." - :group 'ess-bugs - :type 'string - ) - -(defcustom ess-bugs-batch-pre-command - (if (equal ess-bugs-batch-method 'sh) "nohup nice time" - (if ess-microsoft-p "start")) - "ESS[BUGS]: Modifiers at the beginning of the batch BUGS command line." - :group 'ess-bugs - :type 'string - ) - - -(defcustom ess-bugs-default-burn-in "500" - "ESS[BUGS]: Burn-in iterations to discard." - :group 'ess-bugs - :type 'string - ) - -(defcustom ess-bugs-default-update "1000" - "ESS[BUGS]: Iterations to store." - :group 'ess-bugs - :type 'string - ) - -(defvar ess-bugs-batch-command ";" - "ESS[BUGS]: The name of the command to run BUGS in batch mode." - ) - -(defvar ess-bugs-file "." - "ESS[BUGS]: BUGS file with PATH.") - -(defvar ess-bugs-file-root "." - "ESS[BUGS]: Root of BUGS file.") - -(defvar ess-bugs-file-suffix "." - "ESS[BUGS]: Suffix of BUGS file.") - -(defvar ess-bugs-file-dir "." - "ESS[BUGS]: Directory of BUGS file.") - -(defvar ess-bugs-file-data "..." - "ESS[BUGS]: BUGS data file.") - -(defcustom ess-bugs-inits-suffix ".in" - "ESS[BUGS]: BUGS init file suffix." - :group 'ess-bugs - :type 'string - ) - -(defcustom ess-bugs-data-suffix ".dat" - "ESS[BUGS]: BUGS data file suffix." - :group 'ess-bugs - :type 'string - ) - -(defcustom ess-bugs-mode-hook nil - "ESS[BUGS]: List of functions to call upon entering mode." - :group 'ess-bugs - :type 'hook) - -(defvar ess-bugs-monitor-vars " " - "ESS[BUGS]: List of BUGS variables to be written out to a file.") - -(defvar ess-bugs-stats-vars " " - "ESS[BUGS]: List of BUGS variables to be summarized with statistics.") - -(defvar ess-bugs-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (quote [f2]) #'ess-revert-wisely) - (define-key map "\C-c\C-c" #'ess-bugs-next-action) - (define-key map "=" #'ess-bugs-hot-arrow) - (define-key map "_" #'ess-bugs-hot-arrow) - map) - "ESS[BUGS]: Keymap for mode.") - -(defvar ess-bugs-syntax-table - (let ((table (make-syntax-table))) - (modify-syntax-entry ?\\ "." table) - (modify-syntax-entry ?# "<" table) - (modify-syntax-entry ?\n ">" table) - (modify-syntax-entry ?\( "()" table) - (modify-syntax-entry ?\) ")(" table) - (modify-syntax-entry ?. "w" table) - table) - "ESS[BUGS]: Syntax table for mode.") - -(defun ess-bugs-file () - "ESS[BUGS]: Set internal variables dealing with BUGS files. -Set `ess-bugs-file', `ess-bugs-file-root', `ess-bugs-file-suffix' -and `ess-bugs-file-dir'." - (let ((ess-bugs-temp-string (buffer-name))) - (setq ess-bugs-file (expand-file-name ess-bugs-temp-string)) - (setq ess-bugs-file-dir - (convert-standard-filename (file-name-directory ess-bugs-file))) - (setq ess-bugs-file-root - (file-name-nondirectory (file-name-sans-extension ess-bugs-file))) - - (if (fboundp 'file-name-extension) - (setq ess-bugs-file-suffix (file-name-extension ess-bugs-temp-string)) - ;;else - (setq ess-bugs-file-suffix (car (last (split-string ess-bugs-temp-string "[.]"))))) - - (setq ess-bugs-file-suffix - (downcase (car (split-string (concat "." ess-bugs-file-suffix) "[<]")))) - - (setq ess-bugs-file (concat ess-bugs-file-dir ess-bugs-file-root ess-bugs-file-suffix)) - ) - ) - -(defun ess-bugs-exit-notify-sh (string) - "ESS[BUGS]: Detect completion or failure of submitted job and notify the user." - (let* ((exit-done "\\[[0-9]+\\] *\\+* *\\(Exit\\|Done\\)[^\r\n]*") - (beg (string-match exit-done string))) - (if beg (message "%s" (substring string beg (match-end 0)))))) - -(defun ess-bugs-hot-arrow () - "ESS[BUGS]: Substitute <- for = key press" - (interactive) - (insert " <- ")) - -(defun ess-bugs-next-action () - "ESS[BUGS/JAGS]: Perform the appropriate next action." - (interactive) - (ess-bugs-file) - - (cond ((equal ".bug" ess-bugs-file-suffix) (ess-bugs-na-bug)) - ((equal ".jag" ess-bugs-file-suffix) (ess-jags-na-bug)) - ((equal ".bmd" ess-bugs-file-suffix) - (ess-save-and-set-local-variables) - (ess-bugs-na-bmd ess-bugs-command ess-bugs-chains)) - ((equal ".jmd" ess-bugs-file-suffix) - (ess-save-and-set-local-variables) - (ess-jags-na-jmd ess-jags-command ess-jags-chains))) - ) - -(defun ess-bugs-sci-to-round-4-dp () - "ESS[BUGS]: round output from +/-0.000E+/-0 to 4 decimal places." - (interactive) - (setq buffer-read-only nil) - (save-excursion (goto-char 0) - (save-match-data (let ((ess-bugs-replacement-string nil) - (ess-bugs-replacement-9 0) - (ess-bugs-replacement-diff 0)) - (while (search-forward-regexp "-?[0-9][.][0-9][0-9][0-9]E[+-][0-9]" nil t) - (setq ess-bugs-replacement-string - (int-to-string (string-to-number (match-string 0)))) - (setq ess-bugs-replacement-diff (- (match-end 0) (match-beginning 0))) - (save-match-data - (setq ess-bugs-replacement-9 - (string-match "99999999999$" ess-bugs-replacement-string)) - - (if (not ess-bugs-replacement-9) - (setq ess-bugs-replacement-9 - (string-match "000000000001$" ess-bugs-replacement-string)))) - - (if ess-bugs-replacement-9 - (setq ess-bugs-replacement-string - (substring ess-bugs-replacement-string 0 ess-bugs-replacement-9))) - - (setq ess-bugs-replacement-diff - (- ess-bugs-replacement-diff (string-width ess-bugs-replacement-string))) - - (while (> ess-bugs-replacement-diff 0) - (setq ess-bugs-replacement-string (concat ess-bugs-replacement-string " ")) - (setq ess-bugs-replacement-diff (- ess-bugs-replacement-diff 1))) - - (replace-match ess-bugs-replacement-string)))))) - -;;; ESS[BUGS-Shell] for running BUGS interactively -(defgroup ess-bugs-shell nil - "ESS: BUGS-Shell." - :group 'ess-bugs - :prefix "ess-") - -(defcustom ess-bugs-shell-buffer-name "BUGS" - "ESS[BUGS-Shell]: The name of the BUGS-Shell buffer." - :group 'ess-bugs-shell - :type 'string) - -(defcustom ess-bugs-shell-command "OpenBUGS" - "ESS[BUGS-Shell]: The name of the command to run BUGS interactively. - -Set to the name of the batch BUGS script that comes with ESS or -to the name of BUGS command. Make sure it is in your PATH or -add path to the command name." - :group 'ess-bugs-shell - :type 'string) - -(defcustom ess-bugs-shell-default-output-file-root "bugs" - "ESS[BUGS-Shell]: Default value for the root of output files." - :group 'ess-bugs-shell - :type 'string) - -(defcustom ess-bugs-shell-mode-hook nil - "ESS[BUGS-Shell]: List of functions to call upon entering mode." - :group 'ess-bugs-shell - :type 'hook) - -(defun ess-bugs-shell () - "Create a buffer with BUGS running as a subprocess." - (interactive) - (pop-to-buffer-same-window (concat "*" ess-bugs-shell-buffer-name "*")) - (make-comint ess-bugs-shell-buffer-name ess-bugs-shell-command nil - ess-bugs-default-bins ess-bugs-shell-default-output-file-root) - (comint-mode) - (setq shell-dirtrackp t - major-mode 'bugs-shell-mode - mode-name "ESS[BUGS-Shell]" - comint-prompt-regexp "^Bugs> *") - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults '(ess-bugs-font-lock-keywords nil t)) - (run-mode-hooks 'ess-bugs-shell-mode-hook) - ) - -(provide 'ess-bugs-l) - -;;; ess-bugs-l.el ends here diff --git a/elpa/ess-20191014.1343/ess-custom.el b/elpa/ess-20191014.1343/ess-custom.el deleted file mode 100644 index c07f24ae..00000000 --- a/elpa/ess-20191014.1343/ess-custom.el +++ /dev/null @@ -1,2477 +0,0 @@ -;;; ess-custom.el --- Customize variables for ESS -*- lexical-binding: t; -*- - -;; Copyright (C) 1997--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2015 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: A.J. Rossini -;; Created: 05 June 2000 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - - -;;; Commentary: -;; This file holds defcustoms for ESS. It is required by ess-utils.el, -;; which in turn is required by almost every other ESS file. - -;;; Code: -(require 'comint) - -;; FIXME: When Emacs is started from Cygwin shell in Windows, -;; we have (equal window-system 'x) -and should use "--ess" in *d-r.el -(defvar ess-microsoft-p (memq system-type '(ms-dos windows-nt)) - "Value is t if the OS is one of Microsoft's, nil otherwise.") - -;; Customization Groups - -(defgroup ess nil - "ESS: Emacs Speaks Statistics." - :group 'languages - :link '(info-link "(ESS)") - :link '(url-link "https://ess.r-project.org/")) - -(defgroup ess-edit nil - "ESS: editing behavior, including comments/indentation." - :group 'ess - :prefix "ess-") - -(defgroup ess-proc nil - "ESS: process control." - :group 'ess - :prefix "ess-") - -(defgroup ess-command nil - "ESS: Commands for various things." - :group 'ess - :prefix "ess-") - -(defgroup ess-help nil - "ESS: help functions." - :group 'ess - :prefix "ess-") - -(defgroup ess-hooks nil - "ESS: hooks for customization." - :group 'ess - :prefix "ess-") - -(defgroup ess-S nil - "ESS: S Languages." - :group 'ess - :prefix "ess-") - -(defgroup ess-SPLUS nil - "ESS: S-PLUS Dialect of S." - :group 'ess-S - :prefix "ess-") - -(defgroup ess-R nil - "ESS: R Dialect of S." - :group 'ess-S - :prefix "ess-") - -(defgroup ess-Julia nil - "ESS: Julia." - :group 'ess - :prefix "julia-") - -(defgroup ess-sas nil - "ESS: SAS." - :group 'ess - :prefix "ess-") - -(defgroup ess-Stata nil - "ESS: Stata." - :group 'ess - :prefix "ess-") - -(defgroup ess-roxy nil - "Mode for editing in-code Roxygen documentation." - :group 'ess - :group 'convenience - :group 'ess-extras - :prefix "ess-" - :group 'tools) - -(defgroup ess-extras nil - "Extra utilities for ESS" - :group 'ess - :prefix "ess-") - -(defgroup ess-faces nil - "Faces and face options for ESS modes." - :group 'ess - :group 'faces - :prefix "ess-") - - - ; User changeable variables - -;;*;; Options and Initialization - -;;;###autoload -(defcustom ess-lisp-directory - (file-name-directory - (or load-file-name - buffer-file-name)) - "Directory containing ess-site.el(c) and other ESS Lisp files." - :group 'ess - :type 'directory - :package-version '(ess . "19.04")) - -(defcustom ess-etc-directory - ;; Try to detect the `etc' folder only if not already set up by distribution - (let (dir) - (dolist (d '("./etc/" "../../etc/ess/" "../etc/" "../etc/ess/")) - (setq d (expand-file-name d ess-lisp-directory)) - (when (file-directory-p d) - (setq dir d))) - dir) - "Location of the ESS etc/ directory. -The ESS etc directory stores various auxiliary files that are useful -for ESS, such as icons." - :group 'ess - :type 'directory - :package-version '(ess . "19.04")) - -;; Depending on how ESS is loaded the `load-path' might not contain -;; the `lisp' directory. For this reason we need to add it before we -;; start requiring ESS files -;;;###autoload -(add-to-list 'load-path ess-lisp-directory) -;; Add ess-lisp-directory/obsolete to load-path; files here will -;; automatically warn that they are obsolete when loaded. -;;;###autoload -(add-to-list 'load-path (file-name-as-directory (expand-file-name "obsolete" ess-lisp-directory))) - -(unless (file-directory-p ess-etc-directory) - (display-warning 'ess (format "Could not find directory `ess-etc-directory': %s" - ess-etc-directory) :error)) - -;; Menus and pulldowns. - -(defcustom ess-imenu-use-p (fboundp 'imenu) - "Non-nil means use imenu facility. -This value can be overridden by mode-specific variables, such -as `ess-imenu-use-S'." - :group 'ess - :type 'boolean) - -(defcustom ess-imenu-use-S ess-imenu-use-p - "Non-nil means include an Imenu menu item in S buffers." - :group 'ess - :type 'boolean) - -(defcustom ess-auto-width-visible nil - "When non-nil, echo width setting in the inferior buffer. -See `ess-auto-width'. Be warned that ESS can set the width a -lot." - :group 'ess - :type 'boolean - :package-version '(ess . "19.04")) - -(defcustom ess-auto-width nil - "When non-nil, set the width option when the window configuration changes. -When 'frame, set the width to the frame width. When 'window, set -the width to the window width. If an integer, set the width to -that integer. Anything else is treated as 'window." - :group 'ess - :type '(choice (const :tag "Do nothing" :value nil) - (const :tag "Frame width" :value frame) - (const :tag "Window width" :value window) - (integer :tag "Integer value")) - :package-version '(ess . "19.04")) - -(defcustom ess-handy-commands '(("change-directory" . ess-change-directory) - ("install.packages" . ess-install-library) - ("library" . ess-library) - ("objects[ls]" . ess-execute-objects) - ("help-apropos" . ess-display-help-apropos) - ("help-index" . ess-display-package-index) - ("help-object" . ess-display-help-on-object) - ("search" . ess-execute-search) - ("set-width" . ess-execute-screen-options) - ("setRepos" . ess-setRepositories) - ("sos" . ess-sos) - ("vignettes" . ess-display-vignettes) - ) - "An alist of custom ESS commands. -These are available for call by function `ess-handy-commands' and -`ess-smart-comma' function." - :group 'ess - :type 'alist) - -(defvar-local ess--local-handy-commands nil - "Store handy commands locally.") - -(defcustom ess-describe-at-point-method nil - "Whether `ess-describe-object-at-point' should use a tooltip. -If nil display in an electric buffer. If 'tooltip display in -a tooltip. - -See also `tooltip-hide-delay' and variable `tooltip-delay'." - :group 'ess-utils - :type '(choice (const :tag "buffer" :value nil ) (const tooltip))) - -(defvaralias - 'ess-R-describe-object-at-point-commands - 'ess-r-describe-object-at-point-commands) -(defcustom ess-r-describe-object-at-point-commands - '(("str(%s)") - (".ess_htsummary(%s, hlength = 20, tlength = 20)") - ("summary(%s, maxsum = 20)")) - "A list of commands cycled by `ess-describe-object-at-point'. -%s is substituted with the name at point. - -The value of each element is nil and is not used in current -implementation." - :group 'ess-R - :type 'alist) - -(defcustom ess-S-describe-object-at-point-commands - ess-R-describe-object-at-point-commands - "An alist of commands cycled by `ess-describe-object-at-point'. -%s is substitute with the name at point. The value is not used as - yet." - :group 'S+ - :type 'alist) - - -(defcustom ess-can-eval-in-background t - "If non-nil ESS can perform caching and other background activities. -This allows ESS to call the subprocess on idle time." - :group 'ess - :type 'boolean) - -(defcustom ess-user-full-name (user-full-name) - "The full name of the user." - :group 'ess - :type 'string) - -(defcustom ess-blink-region t - "If t evaluated region is highlighted for a shortwhile. -See also `ess-blink-delay'" - :group 'ess - :type 'boolean) - -(defcustom ess-blink-delay .3 - "Number of seconds to highlight the evaluated region." - :group 'ess - :type 'number) - -(defcustom ess-ask-for-ess-directory t - "Non-nil means request the process directory each time S is run." - :group 'ess - :type 'boolean) - -(defcustom ess-ask-about-transfile nil - "Non-nil means ask about a transcript file before running ESS." - :group 'ess - :type 'boolean) - -(defcustom ess-display-buffer-reuse-frames t - "Non-nil means \\[display-buffer] reuses existing frames. -See `display-buffer-reuse-frames'." - :group 'ess - :type 'boolean) - -(defvar-local ess-language nil - "Determines the language to use for the current buffer. -See also `ess-dialect'.") - -(defvar-local ess-dialect nil - "String version of the dialect being run for the inferior process. -This, plus `ess-language', should be able to determine the exact -version of the statistical package being executed in the particular -buffer.") - -(defcustom ess-directory-function nil - "Function to return the directory that ESS is run from. -If nil or if the function returns nil then you get `ess-startup-directory'." - :group 'ess - :type '(choice (const nil) function)) - -(defcustom ess-setup-directory-function nil - "Function to setup the directory that ESS is run from. -This function can be called to set environment variables or to create -a workspace." - :group 'ess - :type '(choice (const nil) function)) - -(defvaralias 'ess-directory 'ess-startup-directory) -(defcustom ess-startup-directory nil - "The directory ESS is run from. It must end in a slash. -Provided as a default if `ess-ask-for-ess-directory' is non-nil. -A nil value means use the current buffer's default directory." - :group 'ess - :type '(choice (const nil) directory)) - - -(defcustom ess-history-directory nil - "Directory to pick up `ess-history-file' from. -If this is nil, the history file is relative to the startup -directory of the inferior process (see `ess-startup-directory')." - :group 'ess - :type '(choice (const nil) directory)) - -(defcustom ess-history-file t - "File to pick up history from. nil means *no* history is read or written. -t means something like \".Rhistory\". -If this is a relative file name, it is relative to `ess-history-directory'. -Consequently, if that is set explicitly, you will have one history file -for all projects." - :group 'ess - :type '(choice (const :tag "Off" nil) - (const :tag "On" t) - file)) - -(defcustom ess-plain-first-buffername t - "When non-nil, the first process buffer created does not have a number. -In other words, it is R:foo rather than R:1:foo. Subsequent -processes buffers are always numbered (e.g. R:2:foo." - :group 'ess - :type 'boolean) - - -(define-obsolete-variable-alias - 'ess-use-inferior-program-name-in-buffer-name - 'ess-use-inferior-program-in-buffer-name "ESS 18.10") -(defcustom ess-use-inferior-program-in-buffer-name nil - "For R, use e.g., 'R-2.1.0' or 'R-devel' (the program name) for buffer name. -Avoids the plain dialect name." - :group 'ess - :type 'boolean) - -(defcustom ess-use-ido t - "If t ess will try to use ido completion whenever possible. - -By default ESS uses enables IDO flex matching. See -`ido-enable-flex-matching' for details on flex matching and -`ess-ido-flex-matching' on how to disable it for ESS, if you -don't want it. - -See info node `(ido) Top' for more information about how ido -works." - :group 'ess - :require 'ido - :type 'boolean) - - -(defcustom ess-tab-complete-in-script nil - "If non-nil, TAB tries to complete if it does not indent in script buffers. -See also `ess-first-tab-never-complete'." - :group 'ess - :type 'boolean) -(make-obsolete-variable 'ess-tab-complete-in-script 'tab-always-indent "ESS 19.04" 'set) - -(define-obsolete-variable-alias 'ess-first-tab-never-completes-p - 'ess-first-tab-never-complete "ESS 19.04") -(defcustom ess-first-tab-never-complete 'symbol - "If t, first TAB never tries to complete in `ess-mode'. -If 'symbol first TAB doesn't try to complete if next char is a -valid symbol constituent. - -If 'symbol-or-paren don't complete if next char is closed paren -)}] or symbol character. - -If 'symbol-or-paren-or-punct don't complete if next char is -punctuation +-=% etc, or closed paren or symbol. - -If 'unless-eol - first TAB completes only at end of line. - -If nil first TAB always tries to complete (this might be too -aggressive and dangerous)." - :group 'ess - :type '(choice (const nil) - (const symbol) - (const symbol-or-paren) - (const symbol-or-paren-or-punct) - (const unless-eol) - (const t))) - -(defcustom ess-use-eldoc t - "If t, activate eldoc in `ess-mode' and `inferior-ess-mode' buffers. -If 'script-only activate in `ess-mode' buffers only. - -See also `ess-eldoc-show-on-symbol'." - :group 'ess-extras - :type '(choice (const t) (const script-only) (const nil))) - - -(defcustom ess-eldoc-show-on-symbol nil - "If non-nil, show help string whenever the point is on a symbol. -If nil show only when the point is in a function call, i.e. after (." - :group 'ess-extras - :type 'boolean) - -(defcustom ess-eldoc-abbreviation-style 'normal - "Controls how `eldoc' displays information that does not fit on a line. - -A symbol which can be - -- nil: do nothing -- mild: Replace TRUE, FALSE with T,F -- normal: Try mild + shorten the default values longer than 10 - characters. -- strong: Try normal + completely remove default values except - =F,=T,=d where d is a digit. -- aggressive (or t): Try strong + truncate the doc string to fit - into minibuffer. - -The default style is 'normal. - -Ess-eldoc also honors the value of -`eldoc-echo-area-use-multiline-p'. If this variable is not t (the -default), doc strings are truncated to fit into minibufer. This -allows the use of different abbreviation styles with the -truncation." - :group 'ess - :type '(choice (const nil) (const mild) (const normal) (const strong) (const aggressive) (const t))) - -(defcustom ess-use-flymake t - "If non-nil activate flymake in `ess-mode' buffers. -If 'process, only check if the buffer has an inferior process." - :group 'ess - :type '(choice (const :tag "Always" t) - (const :tag "With running inferior process" process) - (const :tag "Never" nil)) - :package-version '(ess . "18.10")) - -(defcustom ess-use-auto-complete t - "If non-nil, activate auto-complete support. -If t, activate auto-complete support in `ess-mode' and -`inferior-ess-mode' buffers. If 'script-only activate in `ess-mode' -buffers only. - -If non-nil add `ac-source-R' and `ac-source-filename' to the -`ac-sources' buffer local variable. - -ESS defines three AC sources `ac-source-R',`ac-source-R-objects' -and `ac-source-R-args'. See auto-complete package -documentation (http://cx4a.org/software/auto-complete/) for how -to install your custom sources." - :group 'ess-extras - :type '(choice (const t) (const script-only) (const nil))) -(make-obsolete-variable 'ess-use-auto-complete "Auto-complete is unmaintained; use company-mode instead" - "ESS 19.04" 'set) - -(defcustom ess-use-company t - "If t, activate company support in `ess-mode' and `inferior-ess-mode' buffers. -If non-nil add `company-R-args' and `company-R-objects' to the -`company-backends'. If 'script-only activate in `ess-mode' buffers -only." - :group 'ess-extras - :type '(choice (const t) (const script-only) (const nil))) - -(defcustom ess-company-arg-prefix-length nil - "Minimum prefix for ess company function argument completion." - :group 'ess-extras - :type '(choice (const :tag "Default" nil) - integer)) - -(defcustom ess-use-tracebug t - "If t, load `ess-tracebug' when R process starts." - :group 'ess-extras - :type 'boolean) - -(defcustom ess-ido-flex-matching t - "If t, ido for ESS completion uses flex matching. -See `ido-enable-flex-matching' for details. -If you have an old computer, or you load lot of packages, you -might want to set this to nil." - :group 'ess - :type 'boolean) - -(defvar ess--completing-hist nil - "Variable to store completion history. -Used by `ess-completion-read' command.") - -(defvar-local ess-smart-operators () - "List of smart operators to be used in ESS and IESS modes. -Not to be set by users. It is redefined by mode specific -settings, such as `ess-r-smart-operators'.") - -(defvaralias 'ess-R-smart-operators 'ess-r-smart-operators) -(defvar ess-r-smart-operators nil - "If nil, don't use any of smart operators. -If t, use all. If an explicit list of operators, use only those -operators. - -In current version of ESS, it controls the behavior of -`ess-smart-comma' only, but will be enriched in the near future.") - - -(defvar ess-no-skip-regexp "[ \t\n]*\\'" - "If `ess-next-code-line' sees this line, it doesn't jump over. - -Used to avoid annoying jumping by ess-eval.*-and-step to end of -buffer or end chunks etc.") - -(make-obsolete-variable 'ess-smart-S-assign-key nil "ESS 18.10") - -(defcustom ess-assign-list (cons (or (bound-and-true-p ess-S-assign) " <- ") - '(" <<- " " = " " -> " " ->> ")) - "List of assignment operators. -`ess-cycle-assign' uses this list. These strings must -contain spaces on either side." - ;; Note that spaces on either side is not strictly true (as in the - ;; function won't error), but matching <-/<<- is broken without - ;; them. - :type '(repeat string) - :group 'ess - :package-version '(ess "18.10")) -(defvar ess-S-assign) -(make-obsolete-variable 'ess-S-assign 'ess-assign-list "ESS 18.10") - -(defcustom ess-r-prettify-symbols - '(("<-" . (?\s (Br . Bl) ?\s (Bc . Bc) ?←)) - ("->" . (?\s (Br . Bl) ?\s (Bc . Bc) ?→)) - ("->>" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s - (Bl . Bl) ?- (Bc . Br) ?- (Bc . Bc) ?> - (Bc . Bl) ?- (Br . Br) ?>)) - ("<<-" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s - (Bl . Bl) ?< (Bc . Br) ?- (Bc . Bc) ?- - (Bc . Bl) ?< (Br . Br) ?-))) - ;; Setup prettify-symbols-alist to show "pretty" arrows, but make - ;; sure that they arrows use the same amount of spacing as <- and - ;; <<- to ensure indentation does not change when - ;; prettify-symbols-mode is turned on/off. - "Alist of symbols prettifications, see `prettify-symbols-alist'. -This gets appended to `prettify-symbols-alist', so set it to nil -if you want to disable R specific prettification." - :group 'ess-R - :type '(alist :key-type string :value-type symbol) - :package-version '(ess . "18.10")) - -;;*;; Variables concerning editing behavior - -(defcustom ess-filenames-map t - "If non-nil, filenames and objects are the same in an attached directory. -This is not true for DOS and other OS's with limited filename -lengths. Even if this is set incorrectly, the right things will -probably still happen, however." - :group 'ess-edit - :type 'boolean) - -(defcustom ess-keep-dump-files t - "Variable controlling whether to delete dump files after a successful load. -If nil: always delete. If `ask', confirm to delete. If `check', confirm -to delete, except for files created with `ess-dump-object-into-edit-buffer'. -Anything else, never delete. This variable only affects the behavior -of `ess-load-file'. Dump files are never deleted if an error occurs -during the load." - :group 'ess-edit - :type '(choice (const :tag "Check" :value 'check) - (const :tag "Ask" :value 'ask) - (const :tag "Always keep" :value t) - (const :tag "Always delete" :value nil))) - -(defcustom ess-delete-dump-files nil - "Non-nil means delete dump files after they are created. -This applies to dump files created with -`ess-dump-object-into-edit-buffer', only. - -Boolean flag which determines what to do with the dump files -generated by \\[ess-dump-object-into-edit-buffer], as follows: - - If non-nil: dump files are deleted after each use, and so appear -only transiently. The one exception to this is when a loading error -occurs, in which case the file is retained until the error is -corrected and the file re-loaded. - - If nil: dump files are not deleted, and backups are kept -as usual. This provides a simple method for keeping an archive of S -functions in text-file form. - -Auto-save is always enabled in dump-file buffers to enable recovery -from crashes. - -This is useful to prevent source files being created for objects -you don't actually modify. Once the buffer is modified and saved -however, the file is not subsequently deleted unless -`ess-keep-dump-files' is nil, and the file is successfully loaded -back into S." - :group 'ess-edit - :type 'boolean) - -(defcustom ess-fill-calls t - "If non-nil, refilling inside a call arranges arguments. -In other words, refilling a paragraph inside a function or -indexing call will arrange the arguments according to -`fill-column' as in: - - fun_call(argument1, argument2, - argument3, argument4) - - -Refilling repeatedly cycles through different styles and -eventually to the original formatting. - - The second style formats according to one argument per line: - - fun_call(argument1, - argument2, - argument3, - argument4) - -When `ess-fill-calls-newlines' is t, the second style becomes: - - fun_call( - argument1, - argument2, - argument3, - argument4 - ) - - -Setting `ess-offset-arguments' to `prev-line' or `prev-call' -activates a third style. It keeps one argument per line except -for the first N arguments. N is controlled with a prefix. For -example, calling \\[fill-paragraph] three times sets N to 1 while -calling \\[fill-paragraph] twice then \\[universal-argument] 2 -\\[fill-paragraph] sets N to 2. Here what the default produces: - - fun_call(argument1, - argument2, - argument3, - argument4, - argument5 - ) - -This style is useful for refilling R6 or ggproto class -definitions. - - -The blinking of the refilled region can be disabled with -`ess-blink-refilling'." - :group 'ess-edit - :type 'boolean) - -(defcustom ess-fill-continuations t - "Controls filling of continuations. -If non-nil, refilling a paragraph inside a continuation of -statements (expressions separated by operators) will arrange all -its elements, never going past `fill-column'. - - lm(outcome ~ pred1 + pred2 + - pred3 + pred4, data) - -Refilling repeatedly cycles through different styles and -eventually to the original formatting. - -The second style lay out the statements according to one -expression per line: - - lm(outcome ~ - pred1 + - pred2 + - pred3 + - pred4, data) - -The blinking of the refilled region can be disabled with -`ess-blink-refilling'." - :group 'ess-edit - :type 'boolean) - -(defcustom ess-fill-calls-newlines nil - "When non-nil, refilling may place newlines before and after delimiters. -When non-nil, the second refilling style produces newlines -after and before the opening and closing delimiters. This is -intended for example for dplyr-style code: - - fun_call( - argument1, - argument2, - argument3, - argument4 - ) - -Note that this setting is temporary and likely to be replaced in -a future ESS version by a more comprehensive and flexible way to -set refill styles." - :group 'ess-edit - :type 'boolean) - -(defcustom ess-blink-refilling t - "When non-nil, refilling blinks the filling region." - :group 'ess-edit - :type 'boolean) - -(define-obsolete-variable-alias 'ess-mode-silently-save 'ess-save-silently "ESS 19.04") -(defcustom ess-save-silently 'auto - "If non-nil, possibly save buffers without asking. -If t, save without asking. If 'auto, save without asking if -either `compilation-ask-about-save' or variable `auto-save-visited-mode' -is non-nil. Affects `ess-save-file'." - :group 'ess-edit - :type '(choice (const :tag "Do not save without asking." :value nil) - (const :tag "Use compilation-ask-about-save and auto-save-visited-mode." - :value auto) - (const :tag "Save without asking." :value t)) - :package-version '(ess . "19.04")) - -;;*;; Variables controlling editing - -;;;*;;; Edit buffer processing -(defcustom ess-function-template " <- function( )\n{\n\n}\n" - "If non-nil, function template used when editing nonexistent objects. - -The edit buffer will contain the object name in quotes, followed by -this string. Point will be placed after the first parenthesis or -bracket." - :group 'ess-edit - :type 'string) - -;;;*;;; Indentation parameters - -(define-obsolete-variable-alias 'ess-tab-always-indent 'tab-always-indent "ESS 19.04") - -(define-obsolete-variable-alias 'ess-indent-level 'ess-indent-offset "15.09") -(defvar ess-indent-offset 2 - "Main indentation offset that is commonly inherited by other offsets. -See `ess-style-alist' for all available offsets.") -;;;###autoload -(put 'ess-indent-offset 'safe-local-variable #'numberp) - - -(defvar ess-offset-arguments 'open-delim - "Indent for arguments of function calls or indexing brackets. -This variables has an effect only when the ( or [ are not -directly followed by a new line. See -`ess-offset-arguments-newline' for indentation after closing -newline. - -When set to `open-delim', arguments are indented relative to the -opening parenthesis of the closest function call: - - object <- call(argument, other_call(argument, - other_argument)) - - -When set to `prev-call', arguments are indented relative to the -closest function call: - - object <- call(argument, other_call(argument, - other_argument)) - - -When set to `prev-line', arguments are indented relative to the -preceding line: - - object <- call(argument, other_call(argument, - other_argument)) - -This setting can also be set to a list containing the the offset -type and the offset size, such as `'(prev-call 2)'. Otherwise, -`ess-indent-offset' is used as a default. See `ess-style-alist' -for other offsets controlling indentation.") - -(define-obsolete-variable-alias 'ess-arg-function-offset-new-line 'ess-offset-arguments-newline "15.09") -(defvar ess-offset-arguments-newline 'prev-call - "Indent of arguments when ( or [ is followed by a new line. - -When set to `open-delim', arguments on a new line are indented -relative to the opening parenthesis of the closest function call: - - object <- call(argument, other_call( - argument, - other_argument - )) - - -When set to `prev-call', arguments on a new line are indented relative to -the closest function call: - - object <- call(argument, other_call( - argument, - other_argument - )) - -You can control the details of indentation at `prev-call' with -`ess-indent-from-lhs' and `ess-indent-from-chain-start'. - - -When set to `prev-line', arguments on a new line are indented -relative to the preceding line: - - object <- call(argument, other_call( - argument, - other_argument - )) - -This setting can also be set to a list containing the the offset -type and the offset size, such as `'(prev-call 2)'. Otherwise, -`ess-indent-offset' is used as a default. See `ess-style-alist' -for other offsets controlling indentation.") - -(defvar ess-offset-block 'prev-line - "Controls indentation for blocks. -A block is usually declared with braces but a statement wrapped -in anonymous parentheses is also considered a block. This offset -can be either `prev-call', `prev-line' or `open-delim'. - -When set to `open-delim', blocks are indented relative to the -opening parenthesis of the closest function call: - - call(argument, other_call(parameter = { - stuff - }, { - stuff - })) - - call(argument, lapply(data, function(x) { - body - })) - - -When set to `prev-call', blocks are indented relative to the -closest function call: - - call(argument, other_call(parameter = { - stuff - }, { - stuff - })) - - call(argument, lapply(data, function(x) { - body - })) - -You can control the details of indentation at `prev-call' with -`ess-indent-from-lhs' and `ess-indent-from-chain-start'. - - -When set to `prev-line', blocks are indented relative to the -preceding line: - - call(argument, other_call(parameter = { - stuff - }, { - stuff - })) - - call(argument, lapply(data, function(x) { - body - })) - -This setting can also be set to a list containing the the offset -type and the offset size, such as `'(prev-call 2)'. Otherwise, -`ess-indent-offset' is used as a default. See `ess-style-alist' -for other offsets controlling indentation.") - -(define-obsolete-variable-alias 'ess-first-continued-statement-offset 'ess-offset-continued "15.09") -(define-obsolete-variable-alias 'ess-continued-statement-offset 'ess-offset-continued "15.09") -(defvar ess-offset-continued 'straight - "This setting controls indentation of continued statements. -That is, consecutive statements separated by operators. - -When set to 'straight, continued statements are indented as follows: - - object %>% - some_function() %>% - other_function() - -When set to 'cascade: - - object %>% - some_function() %>% - other_function() - -The 'straight and 'cascade settings are actually equivalent to -'(straight . t) and '(cascade . t), where t represents the -base indent size. More generally, you can supply '(straight . N) -to control the size of indentation. - -See `ess-style-alist' for for an overview of ESS indentation.") - -(defvar ess-align-nested-calls '("ifelse") - "List of strings for which `ess-offset-arguments-newline' is ignored. -These calls will be vertically aligned instead. For example, if -`ifelse' is a member of the list, nested ifelse calls are -indented like this: - - object <- ifelse(condition1, out1, - ifelse(condition2, out2, out3)) - -See `ess-style-alist' for for an overview of ESS indentation.") - -(defvar ess-align-arguments-in-calls '("function[ \t]*(") - "A list of refexes where `ess-offset-arguments' is ignored. -List of regexes specifying the calls where `ess-offset-arguments' -should have no effect on function declarations. The arguments of -those calls will be aligned from the opening parenthesis. - -By default, function declarations are overridden. If for example -`ess-offset-arguments' is set to `prev-line', then function calls -are normally indented as in: - - some_function(argument1, - argument2, argument3 - ) - -However, the parameters of function declarations will be -vertically aligned: - - fun <- function(argument1, - argument2 - argument3) { - body - } - -See `ess-style-alist' for further details.") - -(defvar ess-align-continuations-in-calls t - "Whether continuations inside calls are indented from the opening delimiter. -This produces the following indentation: - - 10 + (1 + 2 + - 3 + 4) - object[variable1 + - variable2] - - if (test1 || test2 || - test3 || test4) { - any(test5 & - test6) - } - -instead of - - 10 + (1 + 2 + - 3 + 4) - object[variable1 + - variable2] - - if (test1 || test2 || - test3 || test4) { - any(test5 & - test6) - } - -Definition operators (`<-', `=', `:=' and `~') still trigger an -indentation in all cases. Also, operators at top level and in -curly brackets are not affected by this setting and always induce -an offset: - - { - var1 + - var2 - } - -See `ess-style-alist' for for an overview of ESS indentation.") - -(defvar ess-align-blocks '(control-flow) - "List of block types for which `ess-offset-blocks' is ignored. -The overridden blocks are vertically aligned. The list can -contain either or both of the symbols `control-flow' and -`fun-decl'. - -With `control-flow', if, else for and while blocks will always be -aligned vertically. With `fun-decl', the body of a function -declaration will always be aligned with the call to -`function'.") - -(define-obsolete-variable-alias 'ess-arg-function-offset 'ess-indent-from-lhs "15.09") -(defvar ess-indent-from-lhs '(arguments fun-decl-opening) - "List of elements that are indented from the left side of an assignment. -The list accepts the symbol `arguments' and `fun-decl-opening'. - -For arguments, this setting only has an effect for offsets set to -`prev-call'. When set, this indentation is produced: - - some_function(parameter = other_function( - argument - )) - - object <- some_function( - argument1, - argument2 - ) - -instead of: - - some_function(parameter = other_function( - argument - )) - - object <- some_function( - argument1, - argument2 - ) - - -`fun-decl-opening' refers to the opening curly following a function -declaration. Setting it produces: - - object <- - function(argument) - { - body - } - -instead of: - - object <- - function(argument) - { - body - } - -This is useful when (a) you have a long function name and want to -break a line after `<-' so that you have room to lay out the -arguments within `fill-column' characters; (b) you still want to -align the function body from the LHS to save horizontal space. - -See `ess-style-alist' for for an overview of ESS indentation.") - -(defvar ess-indent-from-chain-start t - "When non-nil, chained calls are treated as if they were one call. -Indentation will start from the first one. This setting only has -an effect for offsets set to `prev-call' or block offsets set to -`opening-delim'. - -If nil: - - some_function(other_function( - argument - )) - -If t: - - some_function(other_function( - argument - )) - -See `ess-style-alist' for for an overview of ESS indentation.") - -;;added rmh 2Nov97 at request of Terry Therneau -(define-obsolete-variable-alias 'ess-fancy-comments 'ess-indent-with-fancy-comments "15.09") -(defcustom ess-indent-with-fancy-comments t - "Non-nil means distinguish between #, ##, and ### for indentation. -See `ess-style-alist' for for an overview of ESS indentation." - :type 'boolean - :group 'ess-edit) - -;;;*;;; Editing styles - -(defvar ess-style-alist - `((BSD - (ess-indent-offset . 8) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . prev-call) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - (C++ - (ess-indent-offset . 4) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . prev-call) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . (arguments)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - ;; CLB added rmh 2Nov97 at request of Terry Therneau - (CLB - (ess-indent-offset . ,(default-value 'ess-indent-offset)) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . (straight 4)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - (GNU - (ess-indent-offset . ,(default-value 'ess-indent-offset)) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . (prev-call 4)) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - (K&R - (ess-indent-offset . 5) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . prev-call) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - ;; added ajr 17.Feb'04 to match "common R" use (== DEFAULT apart from offset = 4) - (RRR - (ess-indent-offset . 4) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - (RRR+ - (ess-indent-offset . 4) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . open-delim) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . (arguments)) - (ess-indent-from-chain-start . nil) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) - - (RStudio - (ess-indent-offset . ,(default-value 'ess-indent-offset)) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . prev-line) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . nil) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . nil) - (ess-align-blocks . nil) - (ess-indent-from-lhs . (arguments)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . nil)) - - (RStudio- - (ess-indent-offset . ,(default-value 'ess-indent-offset)) - (ess-offset-arguments . prev-line) - (ess-offset-arguments-newline . prev-line) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . nil) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . nil) - (ess-align-blocks . nil) - (ess-indent-from-lhs . (arguments)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . nil)) - - (DEFAULT - (ess-indent-offset . ,(default-value 'ess-indent-offset)) - (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) - (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) - (ess-offset-block . ,(default-value 'ess-offset-block)) - (ess-offset-continued . ,(default-value 'ess-offset-continued)) - (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) - (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) - (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) - (ess-align-blocks . ,(default-value 'ess-align-blocks)) - (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) - (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) - (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments)))) - - "Predefined formatting styles for ESS code. -Use `ess-set-style' to apply a style in all R buffers. The values of -all styles except OWN are fixed. To change the value of variables -in the OWN group, customize the variable `ess-own-style-list'. -DEFAULT style picks default (aka global) values from ESS -indentation variables. In addition, ESS provides many indentation -styles, the most important being the RRR and the RStudio -variants. - -RRR is the common R style that adheres closely to R internal -standards. RRR+ is the same except it also aligns blocks in -function calls with the opening delimiter, producing more -indentation. The C++ style (named like this for historical -reasons rather than any resemblance to existing C++ indentation -schemes) is halfway between these two styles and indent block -arguments from the start of the surrounding function's name. - -The RStudio style closely mimics the indentation of the RStudio -editor. RStudio- is the same except it does not align arguments -in function calls, which corresponds to the settings of some -RStudio users. - -ESS indentation is fully specified by the following offsets and -variables. See the documentation of these variables for examples. - -Offsets: - - - `ess-indent-offset': main offset inherited by other settings - - - `ess-offset-arguments': offset type for function and bracket - arguments - - - `ess-offset-arguments-newline': offset type of arguments - when ( or [ is followed by a new line. - - - `ess-offset-block': offset type for brace and anonymous - parenthesis blocks - - - `ess-offset-continued': offset type for continuation lines in - multiline statements - - -Overrides (implies vertical alignment): - - - `ess-align-nested-calls': functions whose nested calls - should be aligned. - - - `ess-align-arguments-in-calls': calls where - `ess-offset-arguments' should be ignored - - - `ess-align-continuations-in-calls': whether to ignore - `ess-offset-continued' in calls. - - - `ess-align-blocks': whether to ignore `ess-offset-blocks' for - function declarations or control flow statements. - - -Control variables: - - - `ess-indent-from-lhs': whether to indent arguments from - left-hand side of an assignment or parameter declaration. - - - `ess-indent-from-chain-start': whether to indent arguments from - the first of several consecutive calls. - - - `ess-indent-with-fancy-comments': whether to indent #, ## and - ### comments distinctly.") - -(defun ess-add-style (key entries) - "Add a new style to `ess-style-list'. -The new style has KEY and ENTRIES. Remove any existing entry with -the same KEY before adding the new one." - (setq ess-style-alist (assq-delete-all key ess-style-alist)) - (add-to-list 'ess-style-alist (cons key entries))) - -(defcustom ess-own-style-list (cdr (assoc 'RRR ess-style-alist)) - "Indentation variables for your own style. -Set `ess-style' to 'OWN to use these values. To change -these values, use the customize interface. See the documentation -of each variable for its meaning." - :group 'ess-edit - :type 'alist - :initialize 'custom-initialize-set - :set (lambda (symbol value) - (set symbol value) - (ess-add-style 'OWN value))) - -;;;###autoload -(put 'ess-style 'safe-local-variable #'symbolp) - -(define-obsolete-variable-alias 'ess-default-style 'ess-style "ESS 19.04") -(defcustom ess-style 'RRR - "Current ESS indentation style, see `ess-style-alist' for more. -See the variable `ess-style-alist' for how these groups (RRR, -DEFAULT, GNU, BSD, ...) map onto different settings for -variables. OWN style is defined in `ess-own-style-list' and you -can customize it to your needs. DEFAULT style picks default (aka -global) values from ESS indentation variables. - -Prefer `ess-set-style' to set the current style. This variable -has an effect if set before a buffer is visited (e.g. in your -Emacs initialization file) or as a file or directory local -variable (see Info node `(Emacs) File Variables'." - :type '(choice (const OWN) - (const GNU) - (const BSD) - (const C++) - (const CLB) - (const K&R) - (const RRR) - (const RRR+) - (const RStudio) - (const RStudio-) - (const DEFAULT)) - :group 'ess-edit - :safe #'symbolp) - -;;*;; Variables controlling behavior of dump files - -(defcustom ess-source-directory - (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") temporary-file-directory) - "Directory in which to place dump files. -This can be a string (an absolute directory name ending in a slash) or -a lambda expression of no arguments which will return a suitable string -value. The lambda expression is evaluated with the process buffer as the -current buffer. - -This always dumps to a sub-directory (\".Src\") of the current ess -working directory (i.e. first elt of search list)." - :group 'ess-edit - :type 'directory - :package-version '(ess . "18.10")) - -(defvar ess-dump-filename-template nil - "Internal. Initialized by dialects.") - -(defcustom ess-dump-filename-template-proto (concat (user-login-name) ".%s.S") - "Prototype template for filenames of dumped objects. -The ending `S' is replaced by the current \\[ess-suffix], to give -`ess-dump-filename-template' when an inferior ESS process starts. - -By default, gives filenames like `user.foofun.S', so as not to clash with -other users if you are using a shared directory. Other alternatives: -\"%s.S\" ; Don't bother uniquifying if using your own directory(ies) -\"dumpdir\"; Always dump to a specific filename. This makes it impossible -to edit more than one object at a time, though. - (make-temp-name \"scr.\") ; Another way to uniquify" - ;; MM: The last 3-4 lines above suck (I don't understand them) -- FIXME -- - - :group 'ess-edit - :type 'string) - -(defcustom ess-pre-run-hook nil - "Hook to call before starting up ESS. -Good for setting up your directory." - :group 'ess-hooks - :type 'hook) - -(defcustom ess-post-run-hook nil - "Hook to call just after the ESS process starts up. -Good for evaluating ESS code." - :group 'ess-hooks - :type 'hook) - -(defcustom ess-send-input-hook nil - "Hook called just before line input is sent to the process." - :group 'ess-hooks - :type 'hook) - -;; ---- ./ess-roxy.el : ------------ - -(defcustom ess-roxy-package "roxygen2" - "The name of the R package to use for Roxygen." - :group 'ess-roxy - :type 'string) - -(defcustom ess-roxy-tags-noparam '("export" "noRd") - "The tags used in roxygen fields that can be used alone. -Used to decide highlighting and tag completion." - :group 'ess-roxy - :type '(repeat string)) - -(defcustom ess-roxy-tags-param '("author" "aliases" "concept" "details" - "examples" "format" "keywords" - "method" "exportMethod" - "name" "note" "param" - "include" "references" "return" - "seealso" "source" "docType" - "title" "TODO" "usage" "import" - "exportClass" "exportPattern" "S3method" - "inheritParams" - "importFrom" "importClassesFrom" - "importMethodsFrom" "useDynLib" - "rdname" "section" "slot" "description" - "md" "eval") - "The tags used in roxygen fields that require a parameter. -Used to decide highlighting and tag completion." - :group 'ess-roxy - :type '(repeat string)) - -(defcustom ess-roxy-template-alist - (list (cons "description" ".. content for \\description{} (no empty lines) ..") - (cons "details" ".. content for \\details{} ..") - (cons "title" "") - (cons "param" "") - (cons "return" "") - (cons "author" ess-user-full-name)) - "The tags and defaults to insert when creating empty templates. -Param is a place holder for where to enter -parameters. Description and details do not use @ tags, but are -instead placed at the beginning of the entry (and should -therefore also be at the beginning of this template to give -syntactically correct roxygen entries)" - :group 'ess-roxy - :type '(alist :key-type string :value-type string)) - -(defcustom ess-roxy-fill-param-p nil - "Non-nil causes parameter descriptions to be filled (word-wrapped) upon `ess-roxy-update-entry'." - :group 'ess-roxy - :type '(choice (const :tag "Off" nil) - (const :tag "On" t))) - -(defcustom ess-roxy-hide-show-p nil - "Non-nil means ess-roxy uses function `hs-minor-mode' for block hiding with TAB." - :group 'ess-roxy - :type '(choice (const :tag "Off" nil) - (const :tag "On" t))) - -(defcustom ess-roxy-start-hidden-p nil - "Non-nil means all blocks should be hidden from start." - :group 'ess-roxy - :type '(choice (const :tag "Off" nil) - (const :tag "On" t))) - -(defcustom ess-roxy-str "##'" - "Prefix string to insert before each line in new roxygen blocks. -In existing roxygen blocks, the prefix is taken from the line at -point" - :group 'ess-roxy - :type 'string) - -(defvar ess-roxy-insert-prefix-on-newline t - "When non-nil, `ess-roxy-newline-and-indent' makes newlines start with the roxy prefix.") - - ; System variables - -;; SJE -- this should not be defcustom - user does not set it. -(defvaralias 'ess-current-process-name 'ess-local-process-name) -(defvar-local ess-local-process-name nil - "The name of the ESS process associated with the current buffer.") -(put 'ess-local-process-name 'risky-local-variable t) -(put 'ess-local-process-name 'permanent-local t) - -(defcustom ess-switch-to-end-of-proc-buffer t - "If non-nil, `ess-switch-to-inferior-or-script-buffer' goes to the end of the process buffer." - :group 'ess - :type 'boolean) - -(defcustom ess-gen-proc-buffer-name-function 'ess-gen-proc-buffer-name:project-or-simple - "Function used for generation of the buffer name of the new ESS processes. -It should accept one argument PROC-NAME, a string specifying -internal process name (R, R:2, etc). - -Provided default options are: - -`ess-gen-proc-buffer-name:simple' - *proc* - -`ess-gen-proc-buffer-name:directory' - *proc:dir* -`ess-gen-proc-buffer-name:abbr-long-directory' - *proc:abbr-long-dir* -`ess-gen-proc-buffer-name:project-or-simple' - *proc:project-root* or *proc* -`ess-gen-proc-buffer-name:project-or-directory' - *proc:project-root* or *proc:dir* - -Strategies based on projects default to built-in strategies if -there is no project root in the current directory." - :group 'ess - :type '(choice (const :tag "*proc*" ess-gen-proc-buffer-name:simple) - (const :tag "*proc:dir*" ess-gen-proc-buffer-name:directory) - (const :tag "*proc:abbr-long-dir*" ess-gen-proc-buffer-name:abbr-long-directory) - (const :tag "*proc:project-root* or *proc*" ess-gen-proc-buffer-name:project-or-simple) - (const :tag "*proc:project-root* or *proc:dir*" ess-gen-proc-buffer-name:project-or-directory) - function) - :package-version '(ess . "19.04")) - - -(defcustom ess-kermit-command "gkermit -T" - "Kermit command invoked by `ess-kermit-get' and `ess-kermit-send'." - :group 'ess - :type 'string) - -(defcustom ess-kermit-prefix "#" - "String files must begin with to use kermit file transfer." - :group 'ess - :type 'string) - -(defcustom ess-kermit-remote-directory "." - "Buffer local variable that designates remote directory of file." - :group 'ess - :type 'string) -(make-variable-buffer-local 'ess-kermit-remote-directory) - -;;*;; Regular expressions - -;; -- Note: Some variables not-to-customize moved to ./ess-mode.el : -;; ess-r-set-function-start - -;; Fixme: the following is just for S dialects : -(defcustom ess-dumped-missing-re - "\\(<-\nDumped\n\\'\\)\\|\\(<-\\(\\s \\|\n\\)*\\'\\)" - "If a dumped object's buffer matches this re, then it is replaced by `ess-function-template'." - :group 'ess - :type 'regexp) - -(defcustom ess-dump-error-re - (if (string= ess-language "S") "\nDumped\n\\'" - "[Ee]rror") - "Regexp used to detect an error when loading a file." - :group 'ess - :type 'regexp) - - - ; ess-inf: variables for inferior-ess. - -(defvar inferior-ess-own-frame nil - "Non-nil means that inferior ESS buffers should start in their own frame. -This variable is deprecated. -please add an entry to `display-buffer-alist' instead. See Info -node `(ess)Customizing startup'. For example: - -\(add-to-list 'display-buffer-alist - '(\"*R\" - (display-buffer-reuse-window display-buffer-pop-up-frame)))") -(make-obsolete-variable 'inferior-ess-own-frame 'display-buffer-alist "ESS 19.04") -(make-obsolete-variable 'inferior-ess-frame-alist "It is ignored. Use `display-buffer-alist' and `pop-up-frame-alist' instead." "ESS 19.04") -(make-obsolete-variable 'inferior-ess-same-window 'display-buffer-alist "ESS 19.04") - -(defcustom inferior-ess-jit-lock-chunk-size 10000 - "Default for (buffer local) `jit-lock-chunk-size' in inferior ESS buffers." - :group 'ess-proc - :type 'integer) - - -(defvaralias 'inferior-R-program 'inferior-ess-r-program) -(define-obsolete-variable-alias 'inferior-R-program-name - 'inferior-ess-r-program "ESS 18.10") -(define-obsolete-variable-alias 'inferior-ess-r-program-name - 'inferior-ess-r-program "ESS 18.10") -(defcustom inferior-ess-r-program (if ess-microsoft-p - "Rterm" - "R") - "Program name for invoking an inferior ESS with \\[R]." - :group 'ess-R - :type '(choice (string) file)) - -(defcustom inferior-R-args "" - "String of arguments used when starting R. -See also `ess-R-readline'." - :group 'ess-R - :type 'string) - -(defcustom ess-R-readline nil - "When non-nil, use readline in R. -nil indicates that \"--no-readline \" should be used as argument -when starting R. This may very slightly speedup interaction. On -the other hand, readline is necessary for expansion of -\"~username/\" in paths. Note that readline interprets -tabs (tabular characters) in R source files as asking for file -name completion. This can mess up evaluation completely." - :group 'ess-R - :type 'boolean) - -(defcustom inferior-STA-start-args "" - "String of switches used when starting Stata. -Also see `inferior-STA-program'." - :group 'ess-Stata - :type 'string) - -(defvaralias 'inferior-R-objects-command 'inferior-ess-r-objects-command) -(defcustom inferior-ess-r-objects-command "print(objects(pos=%d, all.names=TRUE), max=1e6)\n" - "Format string for R command to get a list of objects at position %d. -Used in e.g., \\[ess-execute-objects] or \\[ess-display-help-on-object]." - :group 'ess-command - :type 'string) - -(defvar ess-getwd-command nil - "Command string retrieving the working directory from the process.") - -(defvar ess-setwd-command nil - "Command string to set working directory. -Should contain a formatting %s to be replaced by a -path (as in 'setwd(%s)\\n'.") - -(defcustom ess-program-files ;; 32 bit version - (if (and ess-microsoft-p - (fboundp 'w32-short-file-name)) - (if (getenv "ProgramW6432") - (w32-short-file-name (getenv "ProgramFiles(x86)"));; always 32 on 64 bit OS - (w32-short-file-name (getenv "ProgramFiles"))) ;; always 32 on 32 bit OS - nil) - "Safe (no embedded blanks) 8.3 name for 32-bit programs that works across internationalization." - :group 'ess - :type '(choice (string) (const nil))) - -(defcustom ess-program-files-64 ;; 64 bit version - (when (and ess-microsoft-p (fboundp 'w32-short-file-name) (getenv "ProgramW6432")) - (w32-short-file-name (getenv "ProgramW6432"))) - "Safe (no embedded blanks) 8.3 name for 64-bit programs that works across internationalization." - :group 'ess - :type '(choice (string) (const nil))) - -(defcustom ess-directory-containing-R nil - "When non-nil, a directory containing R. -nil means the search for all occurrences of R on the machine will -use the default location of the R directory - (inside \"c:/Program Files\" in English locale Windows systems). -Non-nil values mean use the specified location as the -directory in which \"R/\" is located. For example, setting -`ess-directory-containing-R' to \"c:\" will tell ESS to search -for R versions with path names of the form \"c:/R/R-x.y.z\". - -Currently only used when `ess-microsoft-p'. If you change the -value of this variable, you need to restart Emacs for it to take -effect. It also needs to be set before you load ess-site as its -value is used once only when ESS is loaded." - :group 'ess - :type '(choice (directory) (const nil))) - -(defcustom ess-rterm-version-paths nil - "Stores the full path file names of Rterm versions computed via \\[ess-find-rterm]. -If you have versions of R in locations other than in -../../R-*/bin/Rterm.exe or ../../rw*/bin/Rterm.exe, relative to -the directory in the variable `exec-path' containing your default -location of Rterm, you will need to redefine this variable with a -`custom-set-variables' statement in your site-start.el or .emacs -file." - :group 'ess-R - :type '(repeat string)) - -(define-obsolete-variable-alias 'inferior-S3-program-name - 'inferior-S3-program "ESS 18.10") -(defcustom inferior-S3-program "/disk05/s/S" - "Program name for invoking an inferior ESS with S3()." - :group 'ess-S - :type 'string) - -(define-obsolete-variable-alias - 'inferior-S-elsewhere-program-name - 'inferior-S-elsewhere-program "ESS 18.10") -(defcustom inferior-S-elsewhere-program "sh" - "Program name to invoke an inferior ESS with S on a different computer." - :group 'ess-proc - :type 'string) - -(defvaralias 'S+6-dialect-name 'S+-dialect-name) -(defcustom S+-dialect-name "S+" - "Name of 'dialect' for S-PLUS 6.x and later. -Easily changeable in a user's `.emacs'." - :group 'ess-SPLUS - :type 'string) - -(define-obsolete-variable-alias 'inferior-S+-program-name - 'inferior-S+-program "ESS 18.10") -(defcustom inferior-S+-program - (if ess-microsoft-p - (concat ess-program-files "/TIBCO/splus82/cmd/Splus.exe") - "Splus") - "Program name to invoke S+. -On Unix/Linux, use the Splus executable. On Windows, the default -value is correct for a default installation of S-Plus 8.1 and -with bash as the shell. For any other version or location, -change this value in ess-site.el or site-start.el. Use the 8.3 -version of the path name. Use double backslashes if you use the -msdos shell." - :group 'ess-SPLUS - :type '(choice (string) (file))) - -(defvaralias 'inferior-S+6-start-args 'inferior-S+-start-args) -(defvaralias 'inferior-Splus-args 'inferior-S+-start-args) -(defcustom inferior-S+-start-args "" - "String of arguments used when starting S. -These arguments are currently passed only to S+6 and higher." - :group 'ess-SPLUS - :type 'string) - -(defcustom inferior-Splus-objects-command "objects(where=%d)\n" - "Format string for R command to get a list of objects at position %d. -Used in e.g., \\[ess-execute-objects] or \\[ess-display-help-on-object]." - :group 'ess-command - :type 'string) - -(defcustom ess-S-quit-kill-buffers-p nil - "Controls whether S buffers should also be killed once a process is killed. -This is used only when an iESS process is killed using \\[ess-quit]. -Possible values: -nil - do not kill any S buffers associated with the process. -t - kill S buffers associated with the process. -ask - ask the user whether the S buffers should be killed." - :group 'ess-S - :type '(choice (const nil) (const t) (const ask))) - -(define-obsolete-variable-alias 'inferior-SAS-program-name - 'inferior-SAS-program "ESS 18.10") -(defcustom inferior-SAS-program "sas" - "Program name for invoking an inferior ESS with SAS()." - :group 'ess-sas - :type '(choice (string) (file))) - -(define-obsolete-variable-alias 'inferior-STA-program-name - 'inferior-STA-program "ESS 18.10") -(defcustom inferior-STA-program "stata" - "Program name for invoking an inferior ESS with stata(). -This is NOT Stata, because we need to call Stata with TERM=emacs in -order for it to work right. And Emacs is too smart for it." - :group 'ess-Stata - :type '(choice (string) (file))) - -(defvaralias 'R-editor 'ess-r-editor) -(defcustom ess-r-editor "emacsclient" - "Editor called by R process with 'edit()' command." - :group 'ess - :type 'string) - -(defvaralias 'R-pager 'ess-r-pager) -(defcustom ess-r-pager 'nil ; Usually nil is correct as ESS and page() cooperate. - "Pager called by R process with 'page()' command." - :group 'ess - :type '(choice (const nil) string)) - -(defcustom S-editor "emacsclient" - "Editor called by S process with 'edit()' command." - :group 'ess - :type 'string) - -(defcustom S-pager - (if ess-microsoft-p "emacsclientw.exe" "emacsclient") - "Pager called by S process with 'page()' command." - :group 'ess - :type 'string) - -(defvar-local ess-editor nil - "Editor by which the process sends information to an Emacs buffer -for editing and then to be returned to the process.") - -(defvar-local ess-pager nil - "Pager by which the process sends information to an Emacs buffer.") - -(defvar-local inferior-ess-language-start nil - "Initialization commands sent to the ESS process.") - -(define-obsolete-variable-alias 'inferior-ess-program-name - 'inferior-ess-program "ESS 18.10") -(defvar-local inferior-ess-program nil - "Default program name for invoking `inferior-ess'. -The other variables ...-program should be changed, for the -corresponding program.") - -(make-obsolete-variable 'inferior-ess-start-args - "Use the language specific variables like `inferior-R-args'" - "ESS 19.04") -(defvar inferior-ess-start-args "" - "String of arguments passed to the ESS process. -If you wish to pass arguments to a process, see e.g. `inferior-R-args'.") - -(defcustom inferior-ess-pager (if ess-microsoft-p "console" "cat") - "Pager to use for reporting help files and similar things." - :group 'ess-proc - :type 'string) - -(defvar-local inferior-ess-primary-prompt "> " - "Regular expression used by `ess-mode' to detect the primary prompt.") - -(defvar-local inferior-ess-secondary-prompt nil - "Regular expression used by ess-mode to detect the secondary prompt. -This is issued by S to continue an incomplete expression. -Set to nil if language doesn't support secondary prompt.") - -(defvar ess-traceback-command nil - "Command to generate error traceback.") - -;; Need this to recognize prompts of the form + + + > > > -;; and "+ . + ", but not "Abcd. " -(defvar inferior-S-prompt "[]a-zA-Z0-9.[]*[>+] \\(?:[>+.] \\)*" - "Regexp used in S and R inferior and transcript buffers for prompt navigation. -Must not be anchored to BOL.") - -;;*;; Variables controlling interaction with the ESS process - -(defcustom ess-execute-in-process-buffer nil - "Non-nil means the ess-execute- commands output to the process buffer. -Otherwise, they get their own temporary buffer." - :group 'ess-proc - :type 'boolean) - -(defcustom ess-eval-empty nil - "Non-nil means `ess-eval-line*' will send empty lines to the ESS process." - :group 'ess-proc - :type 'boolean) - -(defvaralias 'ess-eval-visibly-p 'ess-eval-visibly) - -(defcustom ess-eval-visibly t - "Non-nil means ess-eval- commands display commands in the process buffer. -If t, ESS waits after each line of the command for the process -output. This results in a nice sequence of input and output but -stalls Emacs on long output (like Sys.sleep(5) in R). - -If 'nowait, ESS still shows the input commands, but don't wait -for the process. Thus all the output is printed after the input -lines. - -If nil, ESS doesn't print input commands and doesn't wait for the process. - -This variable also affect the evaluation of input code in -iESS. The effect is similar to the above. If t then ess waits for -the process output, otherwise not." - :group 'ess-proc - :type '(choice (const t) (const nowait) (const nil))) - -(defcustom ess-eval-deactivate-mark (fboundp 'deactivate-mark); was nil till 2010-03-22 - "Non-nil means that after ess-eval- commands the mark is deactivated." - :group 'ess-proc - :type 'boolean) - -(defcustom ess-use-R-completion t - "Non-nil means use R-builtin completion mechanism when available." - :group 'ess-proc - :type 'boolean) - -(defcustom ess-sleep-for-shell (if ess-microsoft-p 5 1) - "Pause before sending output to the shell." - :group 'ess-proc - :type 'number) - - ; System variables -;; VS[06-04-2016]: fixme: move all inf vars into ess-inf.el. - -;;*;; Variables relating to multiple processes - -(defvar-local ess--mode-line-process-indicator '("" ess-local-process-name) - "List of ESS mode-line indicators. -Local in process buffers and must start with a string. Changes of -this variable are automatically reflected in mode-lines of the -process and all associated with it buffers. - -Each symbol must evaluate to one of the standard mode line -objects. See info node `(elisp)Mode Line Data'). Add a symbol -with `add-to-list' and remove with `delq'. Note that the symbols -which are part of this list should better have -'risky-local-variable property set to t, otherwise the text -properties are not displayed. - -External utilities such as `ess-tracebug' and `ess-developer' -customize this variable to indicate changes in the process -status. -") -(put 'ess--mode-line-process-indicator 'risky-local-variable t) - -(defvar-local ess--local-mode-line-process-indicator '("") - "List of local process indicators. -See `ess--mode-line-process-indicator' for how to set it. - -This is an internal variable used by tools like `ess-developer' -and `ess-tracebug'.") -(put 'ess--local-mode-line-process-indicator 'risky-local-variable t) - -;;*;; Inferior ESS commands - -(defvar-local ess-load-command "source('%s')\n" - "Dialect specific format-string for building the ess command to load a file. - -This format string should use %s to substitute a file name and should -result in an ESS expression that will command the inferior ESS to load -that file.") - -(defvar-local ess-eval-command nil - "Dialect specific format-string for building the command to evaluate a string. - -It is usually faster to send a string to remote processes than a -file. The latter involves Tramp and can be quite slow. When -possible, a dialect should implement that command and use it -preferentially. - -This format string should use %s as a placeholder for the string -to be evaluated and, optionally, %f for the file name to be -reported in the error references. - -The resulting command should not echo code or print any -transitory output. See also `ess-eval-visibly-command' and -`ess-eval-visibly-noecho-command'.") - -(defvar-local ess-build-eval-message-function nil - "Dialect-specific function for formatting an evaluation message.") - -(defcustom inferior-ess-dump-command "dump(\"%s\",file=\"%s\")\n" - "Format-string for building the ess command to dump an object into a file. -Use first %s to substitute an object name. -Use second %s to substitute the dump file name." - :group 'ess-command - :type 'string) - -(defvar-local inferior-ess-help-command "help(\"%s\")\n" - "Format-string for building the ESS command to ask for help on an object. -This format string should use %s to substitute an object name.") - -(defcustom inferior-ess-r-help-command ".ess.help('%s')\n" - "Format-string for building the R command to ask for help on an object. -This format string should use %s to substitute an object name. -If set, changes will take effect when next R session is started." - :group 'ess-command - :type 'string) - -(defvar-local inferior-ess-exit-command "q()\n" - "Format-string for building the ess command to exit. -This format string should use %s to substitute an object name.") - -(defvar-local inferior-ess-search-list-command nil - "`ess-language' command that prints out the search list; -i.e. the list of directories and (recursive) objects that `ess-language' uses -when it searches for objects. - -Really set in -customize-alist in ess[dl]-*.el") - -(defcustom inferior-ess-safe-names-command - "tryCatch(base::print(base::names(%s), max=1e6), error=function(e){})\n" - "Format string for ESS command to extract names from an object *safely*. - -%s is replaced by an \"object name\" -- usually a list or data -frame, but in R also e.g., 'package:stats'." - :group 'ess-command - :type 'string) - -;;*;; Regular expressions -(defvar-local inferior-ess-prompt nil - "The regular expression used for recognizing prompts. - -It is always used in transcript mode. In inferior ess mode it is -used only if `comint-use-prompt-regexp' is t. - -If not set in language's customize-alist it is constructed at run time -from `inferior-ess-primary-prompt' and `inferior-ess-secondary-prompt'.") - - -(defvar-local ess-change-sp-regexp "" - "The regexp for matching the S/R/.. commands that change the search path.") - -(defvar ess-S+-change-sp-regexp - "\\(attach(\\([^)]\\|$\\)\\|detach(\\|collection(\\|library(\\|module(\\|source(\\)" - "The regexp for matching the S-plus commands that change the search path.") - -(defvaralias 'ess-R-change-sp-regexp 'ess-r-change-sp-regexp) -(defvar ess-r-change-sp-regexp - "\\(attach(\\([^)]\\|$\\)\\|detach(\\|library(\\|require(\\|source(\\)" - "The regexp for matching the R commands that change the search path.") - -;;*;; Process-dependent variables - -(defvar-local ess-sl-modtime-alist nil - "Alist of modification times for all ess directories accessed this session.") - -(defvar-local ess-prev-load-dir/file nil - "This symbol saves the (directory . file) pair used in the last -`ess-load-file' command. Used for determining the default in the next one.") - -(defvar-local ess-object-list nil - ;; This is a list of the currently known object names. It is - ;; current only for one command entry; it exists under the - ;; assumption that the list of objects doesn't change while entering - ;; a command. - "Cache of object names.") - -(defvar-local ess-help-topics-list nil - ;; List of currently known help topics. - "Cache of help topics.") - -;;*;; Miscellaneous system variables - -;; SJE: Wed 29 Dec 2004 - following 3 ess-object* variables can be removed -;; soon if no-one needs the completion code. -(defvar ess-object-name-db-file "ess-namedb" - "File containing definitions for `ess-object-name-db'.") - -(defvar ess-object-name-db-file-loaded '() - "List of programs whose name-db file has been loaded.") - -(defvar-local ess-object-name-db nil - "Alist of lists of object names, with directory names as keys. -The file ess-namedb.el is loaded (if it exists) to define this variable. -See also function `ess-create-object-name-db'.") - -;;;*;;; Font-lock support - -;; "Reserved Words" -- part 1 -- -(defvar ess-RS-constants - '("TRUE" "FALSE" "NA" "NULL" "Inf" "NaN")) -(defvar ess-R-constants - (append ess-RS-constants - '("NA_integer_" "NA_real_" "NA_complex_" "NA_character_"))) -(defvar ess-S-constants - (append ess-RS-constants - '("T" "F"))) - -(defvar ess-R-keywords - '("if" "else" "repeat" "while" "function" "for" "in" "next" "break" - "switch" "function" "return" "on.exit" "stop" ".Defunct" "tryCatch" - "withRestarts" "invokeRestart" - "recover" "browser") - "Reserved words or special functions in the R language.") - -(defvar ess-S-keywords - (append ess-R-keywords '("terminate"))) - -;; only some of these keywords "look like functions but are not": -(defvar ess-S-non-functions - '("if" "for" "function" "while")) - -;; first the common ones -(define-obsolete-variable-alias 'ess-S-modifyiers 'ess-S-modifiers "18.10") -(defvar ess-S-modifiers - '("library" "attach" "detach" "source" "module" - "message" "warning")) - -(define-obsolete-variable-alias 'ess-R-modifyiers 'ess-R-modifiers "18.10") -(defvar ess-R-modifiers - '("library" "attach" "detach" "source" "require" - "setwd" "options" "par" "load" "rm" - "message" "warning" ".Deprecated" - "signalCondition" "withCallingHandlers")) - -(defvar ess-R-message-prefixes - '("Error:" "Error in" - "Warning:" "Warning in" - "Warning messages")) -(defvar ess-S-message-prefixes - (append ess-R-message-prefixes - '("Syntax error:" "Dumped"))) - -(defvar ess-R-assign-ops - ;; don't want "=" here which is not only for assign - '("<<-" "<-" "->" "->>")) -(defvar ess-S-assign-ops ess-R-assign-ops) - -(defvar ess-R-function-name-regexp - (concat "\\(" "\\sw+" "\\)" - "[ \t]*" "\\(<-\\)" - "[ \t\n]*" "function\\b")) - -(defvar ess-S-function-name-regexp - ess-R-function-name-regexp) - -(defvar ess-font-lock-keywords nil - "A name of the dialect specific font-lock keywords in the current buffer. -See `ess-R-font-lock-keywords' for an example. This is an -internal variable.") - -(defvar ess-fl-keyword:fun-calls - (cons "\\(\\sw+\\)[\t ]*(" '(1 ess-function-call-face keep)) - "Font lock for function calls.") - -(defvar ess-fl-keyword:numbers - (cons "\\b\\.?[0-9]+[.eEL]?[0-9]*\\b" 'ess-numbers-face) - "Font lock for numbers.") - -(defvar ess-fl-keyword:delimiters - (cons "\\s(\\|\\s)" 'ess-paren-face) - "Font lock for parenthesis.") - -(defvar ess-fl-keyword:= - (cons "=" 'ess-paren-face) - "Font lock for equal sign (=).") - -(defvar ess-fl-keyword:operators - (cons "[-=+>" table) ; \n single-line comment end - (modify-syntax-entry ?\{ "(} " table) - (modify-syntax-entry ?\} "){ " table) - (modify-syntax-entry ?\[ "(] " table) - (modify-syntax-entry ?\] ")[ " table) - (modify-syntax-entry ?\( "() " table) - (modify-syntax-entry ?\) ")( " table) - (modify-syntax-entry ?\r " " table) - (modify-syntax-entry ?+ "." table) - (modify-syntax-entry ?- "." table) - (modify-syntax-entry ?= "." table) - (modify-syntax-entry ?* "." table) - (modify-syntax-entry ?/ "." table) - (modify-syntax-entry ?> "." table) - (modify-syntax-entry ?< "." table) - (modify-syntax-entry ?& "." table) - (modify-syntax-entry ?| "." table) - (modify-syntax-entry ?! "." table) - (modify-syntax-entry ?\\ "\\" table) - (modify-syntax-entry ?\' "." table) - (modify-syntax-entry ?\` "w" table) - (modify-syntax-entry ?\" "\"" table) - (modify-syntax-entry ?. "w" table) - (modify-syntax-entry ?_ "w" table) - (modify-syntax-entry ?\% "." table) - (modify-syntax-entry ?\# "<" table) - (modify-syntax-entry ?\n ">" table) - table) - "Syntax table for `ess-gretl-mode'.") - -;; syntax table that holds within strings -(defvar ess-gretl-mode-string-syntax-table - (let ((table (make-syntax-table))) - table) - "Syntax table for `ess-gretl-mode' that holds within strings.") - -(defcustom gretl-continuation-offset 4 - "Extra indentation applied to Gretl continuation lines." - :type 'integer - :group 'ess-gretl) - -(defvar gretl-continuation-regexp - "[^#%\n]*\\(\\\\\\|\\.\\.\\.\\)\\s-*\\(\\s<.*\\)?$") - -(defcustom gretl-continuation-string "\\" - "Character string used for Gretl continuation lines. Normally \\." - :type 'string - :group 'ess-gretl) - -;; (defconst gretl-string-regex -;; "\"[^\"]*?\\(\\(\\\\\\\\\\)*\\\\\"[^\"]*?\\)*\"") - -(defconst gretl-function-header-regexp - (concat "^\\s-*\\<\\(function\\)\\>" - "\\([^=;\n]*=[ \t]*\\|[ \t]*\\)\\(\\w+\\)\\>") - "Regexp to match a Gretl function header. -The string `function' and its name are given by the first and third -parenthetical grouping.") - -;; (defconst ess-function-call-regexp -;; "\\s\"?\\(\\(\\sw\\|\\s_\\)+\\(<-\\)?\\)\\s\"?*\\s-*(" -;; "Regexp for function names") - -(defvar gretl-command-words - '("add" "adf" "anova" "append" "ar" "ar1" "arbond" "arch" - "arima" "biprobit" "break" "boxplot" "chow" "clear" "coeffsum" "coint" - "coint2" "corr" "corrgm" "cusum" "data" "dataset" "delete" "diff" - "difftest" "discrete" "dpanel" "dummify" "duration" "elif" "else" "end" - "endif" "endloop" "eqnprint" "equation" "estimate" "fcast" "foreign" "fractint" - "freq" "function" "funcerr" "garch" "genr" "gmm" "gnuplot" "graphpg" - "hausman" "heckit" "help" "hsk" "hurst" "if" "include" "info" - "intreg" "kalman" "kpss" "labels" "lad" "lags" "ldiff" "leverage" - "levinlin" "logistic" "logit" "logs" "loop" "mahal" "makepkg" "meantest" - "mle" "modeltab" "modprint" "modtest" "mpols" "negbin" "nls" "normtest" - "nulldata" "ols" "omit" "open" "orthdev" "outfile" "panel" "pca" - "pergm" "textplot" "poisson" "print" "printf" "probit" "pvalue" "quantreg" - "qlrtest" "qqplot" "quit" "rename" "reset" "restrict" "rmplot" "run" - "runs" "scatters" "sdiff" "set" "setinfo" "setobs" "setmiss" "shell" - "smpl" "spearman" "sprintf" "square" "sscanf" "store" "summary" "system" - "tabprint" "tobit" "tsls" "var" "varlist" "vartest" "vecm" "vif" - "wls" "xcorrgm" "xtab" "debug" "return" "catch" "for" "foreach" - "while" "const" "3sls" "liml" "fiml" - "sur" "params" "deriv" "orthog" "weights" "series" "scalar") - "Commands in Gretl (these names are also reserved).") - -(defvar gretl-genr-functions - '("abs" "sin" "cos" "tan" "asin" "acos" "atan" "sinh" - "cosh" "tanh" "asinh" "acosh" "atanh" "log" "ln" "log10" - "log2" "exp" "sqrt" "diff" "ldiff" "sdiff" "lags" "int" - "round" "ceil" "floor" "sort" "dsort" "sortby" "ranking" "orthdev" - "nobs" "firstobs" "lastobs" "uniform" "normal" "cum" "missing" "ok" - "misszero" "lrvar" "quantile" "median" "gini" "zeromiss" "sum" "mean" - "min" "max" "sd" "var" "sst" "cnorm" "dnorm" "qnorm" - "gammafun" "lngamma" "digamma" "resample" "pnobs" "pmin" "pmax" "pmean" - "psd" "hpfilt" "bkfilt" "bwfilt" "fracdiff" "boxcox" "cov" "corr" - "movavg" "I" "zeros" "ones" "seq" "replace" "muniform" "mnormal" - "sumc" "sumr" "meanc" "meanr" "sdc" "minc" "maxc" "minr" - "maxr" "iminc" "imaxc" "iminr" "imaxr" "fft" "ffti" "cmult" - "cdiv" "mcov" "mcorr" "mxtab" "cdemean" "cholesky" "psdroot" "inv" - "invpd" "ginv" "diag" "transp" "vec" "vech" "unvech" "upper" - "lower" "rows" "cols" "det" "ldet" "tr" "onenorm" "infnorm" - "rcond" "rank" "qform" "mlag" "qrdecomp" "eigensym" "eigengen" "nullspace" - "princomp" "mexp" "fdjac" "BFGSmax" "obsnum" "isseries" "isscalar" "islist" - "isstring" "isnull" "nelem" "pdf" "cdf" "invcdf" "pvalue" "critical" - "randgen" "urcpval" "values" "mshape" "svd" "mols" "mpols" "mrls" - "mread" "mwrite" "selifc" "selifr" "polroots" "dummify" "wmean" "wvar" - "wsd" "xpx" "filter" "kfilter" "ksmooth" "ksimul" "trimr" "getenv" - "argname" "obslabel" "readfile" "grab" "strstr" "strncmp" "strlen" "sscanf" - "varname" "varnum" "tolower" "colnames" "rownames" "ljungbox" "msortby" "lincomb" - "imhof" "toepsolv" "diagcat" "xmin" "xmax" "corrgm" "mcovg" "fcstats" - "bessel" "fraclag" "mreverse" "deseas" "pergm" "irr" "npv" "logistic" - "weekday" "kdensity" "monthlen" "epochday" "setnote" "invmills" "polyfit" "chowlin" - "varsimul" "strsplit" "inlist" "errmsg" "isconst" "irf" "inbundle") - "Builtin functions for Gretl's genr command.") - - -(defvar gretl-option-flags - '("addstats" "all" "anova" "append" - "arch" "arma-init" "asymptotic" "auto" - "autocorr" "auxiliary" "balanced" "bartlett" - "between" "bootstrap" "both" "breusch-pagan" - "byobs" "by" "c" "close" - "coded" "cols" "column" "comfac" - "complete" "conditional" "contiguous" "continue" - "continuous" "control" "covariance" "cross" - "cross-section" "crt" "csv" "ct" - "ctt" "cubes-only" "dat" "database" - "dataset" "db" "degrees" "dhansen" - "difference" "diffuse" "discrete" "dpdstyle" - "drop-empty" "drop-first" "drop-last" "dummy" - "dynamic" "equal" "exit" "exponential" - "fcp" "fixed-effects" "from-file" "full" - "func" "gamma" "geomean" "gls" - "gmm" "gnu-R" "gnu-octave" "gph" - "gzipped" "hausman-reg" "hessian" "hilu" - "impulse-responses" "input" "inst" "integrate" - "intervals" "inverse-fit" "iterate" "jackknife" - "jbera" "jitter" "jmulti" "kendall" - "lags" "lagselect" "lbfgs" "lillie" - "liml" "linear-fit" "list" "loess-fit" - "log" "loglogistic" "lognormal" "logs" - "matrix" "matrix-diff" "medians" "ml" - "model1" "multi" "multinomial" "nc" - "next" "no-corc" "no-dates" "no-df-corr" - "no-gradient-check" "no-header" "no-missing" "no-scaling" - "no-stats" "normal" "normality" "notches" - "numerical" "odbc" "omit-obs" "one-scale" - "opg" "orthdev" "other" "out-of-sample" - "output" "overwrite" "p-values" "panel" - "panel-vars" "plot" "pooled" "preserve" - "print-final" "progress-bar" "progressive" "pwe" - "quadratic-fit" "quiet" "quit" "radians" - "random" "random-effects" "rank-sum" "raw" - "rc" "replace" "restrict" "restructure" - "reverse" "robust" "rolling" "row" - "rtf" "save" "save-all" "save-ehat" - "save-xbeta" "scalars" "seasonals" "send-data" - "sign" "signed-rank" "silent" "simple" - "simple-print" "single-yaxis" "skip-df" "spearman" - "special-time-series" "squares" "squares-only" "stacked-cross-section" - "stacked-time-series" "static" "stdresid" "suppress-fitted" - "swilk" "system" "t-ratios" "tall" - "test-down" "tex" "time-dummies" "time-series" - "to-file" "to_file" "traditional" "trend" - "two-step" "unequal-vars" "uniform" "unit-weights" - "variance-decomp" "vcv" "verbose" "wald" - "weibull" "weights" "white" "white-nocross" - "with-impulses" "with-lines" "write" "www" - "x-12-arima" "y-diff-only" "z-scores" "zeros") - "Gretl option flags.") - -(defvar gretl-internal-vars - '("Fstat" "T" "ahat" "aic" "bic" "chisq" "coeff_ci" - "coeff" "compan" "datatype" "df" "dwpval" "ec" "ehat" - "error" "ess" "fcast" "fcerr" "gmmcrit" "hausman" "hqc" - "h" "jalpha" "jbeta" "jvbeta" "kalman_llt" "kalman_lnl" "kalman_s2" - "kalman_t" "kalman_uhat" "llt" "lnl" "mnlprobs" "ncoeff" "nobs" - "nscan" "nvars" "obs" "pd" "pvalue" "rho" "rlnl" - "rsq" "s00" "s01" "s11" "sample" "sargan" "sigma" - "stderr" "stopwatch" "sysA" "sysB" "sysGamma" "t1" "t2" - "test" "trsq" "uhat" "unit" "vcv" "version" "vma" - "windows" "xlist" "xtxinv" "yhat" ) - "Model- and dataset-related variables.") - -(defconst gretl-block-start-keywords - (list "loop" "foreign" "function" "gmm" "if" "system" "mle" "nls" "restrict")) - -(defconst gretl-block-other-keywords - (list "else" "elif")) - -(defconst gretl-block-end-keywords - (list "end" "endif" "endloop")) - -(defvar gretl-keywords - (append gretl-block-start-keywords - gretl-block-other-keywords - gretl-block-end-keywords - '("break")) - "Reserved words in Gretl.") - - -(defun gretl-at-keyword (kw-list) - ; not a keyword if used as a field name, X.word, or quoted, :word - (and (or (= (point) 1) - (and (not (equal (char-before (point)) ?.)) - (not (equal (char-before (point)) ?:)))) - (not (ess-inside-string-or-comment-p (point))) - (not (ess-inside-brackets-p (point))) - (member (current-word) kw-list))) - - -(defconst gretl-font-lock-keywords - (list - ;; Fontify all builtin keywords. - (cons (concat "\\<\\(" - (mapconcat 'identity gretl-keywords "\\|") - "\\)\\>") - 'font-lock-keyword-face) - ;; Fontify all option flags. - (cons (concat "[ \t]--\\(" - (mapconcat 'identity gretl-option-flags "\\|") - "\\)") - 'font-lock-constant-face) - ;; Fontify all command words. - (cons (concat "\\<\\(" - (mapconcat 'identity gretl-command-words "\\|") - "\\)\\>") - 'font-lock-builtin-face) - ;; Fontify all builtin operators. - (cons "\\(&\\||\\|<=\\|>=\\|==\\|<\\|>\\|!=\\|!\\)" - (if (boundp 'font-lock-builtin-face) - 'font-lock-builtin-face - 'font-lock-preprocessor-face)) - ;; Fontify all internal variables. - (cons (concat "\\$\\(" - (mapconcat 'identity gretl-internal-vars "\\|") - "\\)\\>") - 'font-lock-variable-name-face) - - ;; Fontify all genr functions. - (cons (concat "\\<\\(" - (mapconcat 'identity gretl-genr-functions "\\|") - "\\)\\>") - 'font-lock-variable-name-face) - ;; Fontify all function declarations. - (list gretl-function-header-regexp - '(1 font-lock-keyword-face) - '(3 font-lock-function-name-face nil t))) - "Additional Gretl expressions to highlight.") - - -(defvar gretl-block-begin-regexp - (concat "\\<\\(" - (mapconcat 'identity gretl-block-start-keywords "\\|") - "\\)\\>")) - -(defvar gretl-block-else-regexp - (concat "\\<\\(" - (mapconcat 'identity gretl-block-other-keywords "\\|") - "\\)\\>")) - -(defvar gretl-block-end-regexp - (concat "\\<\\(" - (mapconcat 'identity gretl-block-end-keywords "\\|") - "\\)\\>")) - -(defvar gretl-block-begin-or-end-regexp - (concat gretl-block-begin-regexp "\\|" gretl-block-end-regexp)) - - -(defvar gretl-block-else-or-end-regexp - (concat gretl-block-else-regexp "\\|" gretl-block-end-regexp)) - -(defvar gretl-basic-offset 4) - -(defvar gretl-block-match-alist - '(("loop" . ("endloop")) - ("if" . ("else" "elif" "endif")) - ("nls" . ("end")) - ("mle" . ("end")) - ("gmm" . ("end")) - ("foreign" . ("end")) - ("restrict" . ("end")) - ("kalman" . ("end")) - ("system" . ("end"))) - "Alist with Gretl's matching block keywords. -Has Gretl's begin keywords as keys and a list of the matching else or -end keywords as associated values.") - - - -; get the position of the last open block -(defun gretl-last-open-block-pos (min) - (let ((count 0)) - (while (not (or (> count 0) (<= (point) min))) - (backward-word 1) - (setq count - (cond ((gretl-at-keyword gretl-block-start-keywords) - (+ count 1)) - ((and (zerop (string-match "\\(?:e\\(?:l\\(?:if\\|se\\)\\|nd\\(?:if\\|loop\\)?\\)\\)" (current-word))) - (not (ess-inside-comment-p)) (not (ess-inside-brackets-p))) - (- count 1)) - (t count)))) - (if (> count 0) - (point) - nil))) - - -(defun gretl-last-open-block (min) - (let ((pos (gretl-last-open-block-pos min))) - (and pos - (progn - (goto-char pos) - (+ gretl-basic-offset (current-indentation)))))) - - -; return indent implied by a special form opening on the previous line, if any -(defun gretl-form-indent () - (forward-line -1) - (end-of-line) - (backward-sexp) - (if (gretl-at-keyword gretl-block-other-keywords) - (+ gretl-basic-offset (current-indentation)) - (if (char-equal (char-after (point)) ?\() - (progn - (backward-word 1) - (let ((cur (current-indentation))) - (if (gretl-at-keyword gretl-block-start-keywords) - (+ gretl-basic-offset cur) - nil))) - nil))) - - -(defun gretl-indent-line () - "Indent current line of gretl code." - (interactive) - (end-of-line) - (indent-line-to - (or (and (ess-inside-string-p (point-at-bol)) 0) - (save-excursion (ignore-errors (gretl-form-indent))) - (save-excursion - (let ((endtok (progn - (beginning-of-line) - (forward-to-indentation 0) - (gretl-at-keyword gretl-block-end-keywords)))) - (ignore-errors (+ (gretl-last-open-block (point-min)) - (if endtok (- gretl-basic-offset) 0))))) - ;; previous line ends in = - (save-excursion - (if (and (not (equal (point-min) (line-beginning-position))) - (progn - (forward-line -1) - (end-of-line) (backward-char 1) - (equal (char-after (point)) ?=))) - (+ gretl-basic-offset (current-indentation)) - nil)) - ;; take same indentation as previous line - (save-excursion (forward-line -1) - (current-indentation)) - 0)) - (when (gretl-at-keyword gretl-block-end-keywords) - (forward-word 1))) - -;; (defun gretl-send-string-function (process string visibly) -;; (let ((gretl-process (get-process "gretlcli"))) -;; (process-send-string process (format ess-load-command file))) - - -;; (defun gretl-send-string-function (process string visibly) -;; (let ((file (concat temporary-file-directory "gretl_eval_region.inp"))) -;; (with-temp-file file -;; (insert string)) -;; (process-send-string process (format ess-load-command file)))) - -(defun gretl--get-words-from-command (command start-reg end-reg proc) - (with-current-buffer (ess-command command nil nil nil nil proc) - (goto-char (point-min)) - (let ((beg (or (re-search-forward start-reg nil t) - (point-min))) - (end (progn (goto-char (point-max)) - (or (re-search-backward end-reg) - (point-max)))) - acum) - (goto-char beg) - (skip-chars-forward "\n") - (while (re-search-forward "[^ \t\n]+" end t) - (push (match-string-no-properties 0) acum)) - acum))) - -(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "gretl")) - (delete-dups - (append gretl-command-words gretl-genr-functions - gretl-block-end-keywords gretl-block-other-keywords - gretl-block-start-keywords - (gretl--get-words-from-command "help\n" "are:" "^For" proc) - (gretl--get-words-from-command "help functions\n" "Accessors:" "^Functions" proc) - (gretl--get-words-from-command "help functions\n" "^Functions" "^For" proc) - ))) - -;; (defvar ess-gretl-error-regexp-alist '(gretl-in gretl-at) -;; "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.") - -;; (add-to-list 'compilation-error-regexp-alist-alist -;; '(gretl-in "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) -;; (add-to-list 'compilation-error-regexp-alist-alist -;; '(gretl-at "^\\s-*\\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) - - -(defvar gretl-customize-alist - '((comint-use-prompt-regexp . t) - (inferior-ess-primary-prompt . "\\? ") - (inferior-ess-secondary-prompt . "\\ ") - (inferior-ess-prompt . "\\? ") - (ess-local-customize-alist . 'gretl-customize-alist) - (inferior-ess-program . "gretlcli") - (ess-load-command . "open \"%s\"\n") - ;; (ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+") - ;; (ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)") - ;; (ess-error-regexp-alist . ess-gretl-error-regexp-alist) - ;; (inferior-ess-objects-command . inferior-gretl-objects-command) - ;; (inferior-ess-search-list-command . "search()\n") - ;; inferior-ess-help-command . gretl-help-command) - (inferior-ess-help-command . "help %s\n") - (ess-language . "gretl") - (ess-dialect . "gretl") - (ess-suffix . "inp") - (ess-dump-filename-template . (replace-regexp-in-string - "S$" ess-suffix ; in the one from custom: - ess-dump-filename-template-proto)) - (ess-change-sp-regexp . nil );ess-r-change-sp-regexp) - (ess-help-sec-regex . ess-help-r-sec-regex) - (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) - (ess-function-pattern . ess-r-function-pattern) - (ess-object-name-db-file . "ess-r-namedb.el" ) - ;; (ess-imenu-mode-function . nil) - (ess-smart-operators . ess-r-smart-operators) - (inferior-ess-exit-command . "exit\n") - ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help? - (inferior-ess-language-start . nil) - (ess-STERM . "iESS") - ) - "Variables to customize for Gretl -- set up later than Emacs initialization.") - -;; (defcustom inferior-gretl-program "gretlcli" -;; "*The program to use for running gretl scripts." -;; :type 'string -;; :group 'ess-gretl) - -;; (defvar ess-gretl-versions '("gretcli") -;; "List of partial strings for versions of Julia to access within ESS. -;; Each string specifies the start of a filename. If a filename -;; beginning with one of these strings is found on `exec-path', a M-x -;; command for that version of Julia is made available. ") - -(defcustom inferior-gretl-args "" - "String of arguments used when starting gretl." - :group 'ess-gretl - :type 'string) - -;;;###autoload -(define-derived-mode ess-gretl-mode ess-mode "ESS[gretl]" - "Major mode for editing gretl source. See `ess-mode' for more help." - ;;(setq imenu-generic-expression R-imenu-generic-expression) - (ess-setq-vars-local gretl-customize-alist) - (setq font-lock-defaults `(,gretl-font-lock-keywords)) - (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-ignore-fill-prefix t) - (setq-local comment-start "# ") - (setq-local comment-add 1) - (setq-local comment-start-skip "\\s<+\\s-*") - (setq-local comment-column 40) - (setq-local indent-line-function #'gretl-indent-line) - (setq-local ess-local-customize-alist gretl-customize-alist) - (when (fboundp 'ess-add-toolbar) (ess-add-toolbar))) - - -(defvar ess-gretl-post-run-hook nil - "Functions run in process buffer after Gretl starts.") - -;;;###autoload -(defun gretl (&optional start-args) - "Call 'gretl', -Optional prefix (C-u) allows to set command line arguments, such as ---vsize. This should be OS agnostic. -If you have certain command line arguments that should always be passed -to gretl, put them in the variable `inferior-gretl-args'." - (interactive "P") - ;; get settings, notably inferior-ess-r-program : - ;; (if (null inferior-gretl-program) - ;; (error "'inferior-gretl-program' does not point to 'gretl-release-basic' executable") - (ess-write-to-dribble-buffer ;; for debugging only - (format - "\n(Gretl): ess-dialect=%s, buf=%s" - ess-dialect (current-buffer))) - (let* ((r-start-args - (concat inferior-gretl-args " " ; add space just in case - (if start-args - (read-string - (concat "Starting Args [other than `" - inferior-gretl-args - "'] ? ")) - nil))) - (inf-buf (inferior-ess r-start-args gretl-customize-alist))) - (setq-local indent-line-function 'gretl-indent-line) - (setq-local gretl-basic-offset 4) - (setq indent-tabs-mode nil) - (goto-char (point-max)) - ;; (if inferior-ess-language-start - ;; (ess-eval-linewise inferior-ess-language-start - ;; nil nil nil 'wait-prompt))) - (with-current-buffer inf-buf - (run-mode-hooks 'ess-gretl-post-run-hook)) - inf-buf)) - - -;;;; IMENU - -;; (defvar gretl-imenu-generic-expression -;; '(("Function (_)" "^\\s-*function\\s-+\\(_[^ \t\n]*\\)" 1) -;; ("Function" "^\\s-*function\\s-+\\([^_][^ \t\n]*\\)" 1) -;; ("Const" "^\\s-*const \\([^ \t\n]*\\)" 1) -;; ("Type" "^\\s-*\\w*type\\w* \\([^ \t\n]*\\)" 1) -;; ("Load" " *\\(load\\)(\\([^ \t\n)]*\\)" 2) -;; ;; ("Classes" "^.*setClass(\\(.*\\)," 1) -;; ;; ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to -;; ;; ("Generics" "^.*setGeneric(\\([^,]*\\)," 1) -;; ;; ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\"\\(.+\\)\"," 2) -;; ;; ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1) -;; ;; ;; -;; ;; ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1) -;; ;; ("Package" "^.*\\(library\\|require\\)(\\(.*\\)," 2) -;; ;; ("Data" "^\\(.+\\)\\s-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1))) -;; )) - - -;; (defun ess-imenu-gretl (&optional arg) -;; "Gretl Language Imenu support for ESS." -;; (interactive) -;; (setq imenu-generic-expression gretl-imenu-generic-expression) -;; (imenu-add-to-menubar "Imenu-gretl")) - - -;; (defun ess-imenu-gretl (&optional arg) -;; "Gretl Language Imenu support for ESS." -;; (interactive) -;; (setq imenu-generic-expression gretl-imenu-generic-expression) -;; (imenu-add-to-menubar "Imenu-jl")) - - -(provide 'ess-gretl) - -;;; ess-gretl.el ends here diff --git a/elpa/ess-20191014.1343/ess-help.el b/elpa/ess-20191014.1343/ess-help.el deleted file mode 100644 index 02bb8a75..00000000 --- a/elpa/ess-20191014.1343/ess-help.el +++ /dev/null @@ -1,874 +0,0 @@ -;;; ess-help.el --- Support for viewing ESS help files -*- lexical-binding: t; -*- - -;; Copyright (C) 1989-1994, 2017 Bates, Kademan, Ritter and Smith -;; Copyright (C) 1997, A.J. Rossini -;; Copyright (C) 1998--2001 A.J. Rossini, Martin Maechler, Kurt Hornik and -;; Richard M. Heiberger . -;; Copyright (C) 2001--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: David Smith -;; Created: 7 Jan 1994 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Code for dealing with ESS help files. See README. where -;; is one of `S', `SAS', `Stata' or `XLispStat'. - -;;; Code: - - ; Requires and autoloads -(require 'cl-lib) -(eval-when-compile - (require 'tramp)) -(require 'info) -(require 'ess-mode) -(require 'ess-inf) -(require 'ess-utils) -(require 'ansi-color) - -(declare-function ess-r-help-mode "ess-r-mode") -(declare-function ess-stata-help-mode "ess-stata-lang") - - -(defcustom ess-help-mode-hook nil - "Functions to call when entering `ess-help-mode'." - :group 'ess-hooks - :type 'hook) - -(defvar ess--help-frame nil - "Stores the frame used for displaying R help buffers.") - - ; ess-help-mode -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;; In this section: -;;;; -;;;; * The function ess-display-help-on-object -;;;; * The major mode ess-help-mode -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(cl-defgeneric ess--help-major-mode () - "Determine which help major mode to call, and call it. -Uses `ess-dialect' to determine the appropriate help mode." - (ess-help-mode)) - -(defun ess--help-get-bogus-buffer-substring (buffer &optional nr-first) - "Return non-nil if BUFFER looks like a bogus ESS help buffer. -Return the pair (match-beg. match-end) which can be used in error -message. NR-FIRST is the number of characters at the start of the -buffer to examine when deciding if the buffer if bogus. If nil, -the first 150 characters of the buffer are searched." - (if (not nr-first) (setq nr-first 150)) - (with-current-buffer buffer - (let ((PM (point-min)) - (case-fold-search t) - searching res) - (setq res - (or ;; evaluate up to first non-nil (or end): - (< (- (point-max) PM) 80); buffer less than 80 chars - (not (setq searching t)) - ;; todo: move to customize-alist - (progn (goto-char PM) ;; R: - (re-search-forward "Error in help" nr-first t)) - (progn (goto-char PM) ;; S-plus 5.1 : - (re-search-forward "^cat: .*--" nr-first t)) - (progn (goto-char PM) ;; S version 3 ; R : - (re-search-forward "no documentation .+" nr-first t)) - (progn (goto-char PM) ;; stata - (re-search-forward "^help .*not found" nr-first t)))) - (ess-write-to-dribble-buffer - (format " |--> %s [searching %s]\n" res searching)) - (when res - (if searching - (buffer-substring (match-beginning 0) (match-end 0)) - (buffer-string)))))) - -(defun ess-help-get-local-help-buffers () - (ess-force-buffer-current) - (cl-remove-if-not - (lambda (buffer) - (let* ((pattern (concat "*help[" ess-current-process-name "](")) - (name (buffer-name buffer)) - (candidate (when (> (length name) (length pattern)) - (substring name 0 (length pattern))) )) - (when (string= pattern candidate) - buffer))) - (buffer-list))) - -(defvar-local ess-help-type nil - "Type of help file, help, index, vignettes etc. -Local in `ess-help' buffers.") - -(defvar-local ess-help-object nil - "Name of the object the help is displayed for. -Is name of the package for package index. -Local in `ess-help' buffers.") -(put 'ess-help-object 'permanent-local t) - -(defun ess-display-help-on-object (object &optional command) - "Display documentation for OBJECT. -If prefix ARG is given, force an update of the cached help topics -and query the ESS process for the help file instead of reusing an -existing buffer if it exists. Uses the variable -`inferior-ess-help-command' for the actual help command. Prompts -for the object name based on the cursor location for all cases -except the S-Plus GUI. With S-Plus on Windows (both GUI and in an -inferior Emacs buffer) the GUI help window is used. If COMMAND is -supplied, it is used instead of `inferior-ess-help-command'." - (interactive - (progn - (ess-force-buffer-current) - (when current-prefix-arg ;update cache if prefix - (ess-process-put 'sp-for-help-changed? t)) - (list (ess-find-help-file "Help on")))) - (let* ((hb-name (concat "*help[" ess-current-process-name "](" - (replace-regexp-in-string "^\\?\\|`" "" object) ")*")) - (old-hb-p (get-buffer hb-name)) - (tbuffer (get-buffer-create hb-name))) - (when (or (not old-hb-p) - (ess-process-get 'sp-for-help-changed?) - (ess--help-get-bogus-buffer-substring old-hb-p)) - (ess-with-current-buffer tbuffer - (ess--flush-help-into-current-buffer object command) - (setq ess-help-object object) - (ess--help-major-mode) - (setq truncate-lines nil - ess-help-type 'help))) - (unless (ess--help-kill-bogus-buffer-maybe tbuffer) - (ess-display-help tbuffer)))) - -(defun ess-help-revert-buffer (_ignore-auto _noconfirm) - "Revert the current help buffer. -This reloads the documentation. IGNORE-AUTO and NOCONFIRM are -ignored." - (ess-process-put 'sp-for-help-changed? t) - (ess-display-help-on-object ess-help-object)) - -(defalias 'ess-help 'ess-display-help-on-object) - -(cl-defgeneric ess-build-help-command (object) - "Build a string command for retrieving help on OBJECT." - (format inferior-ess-help-command object)) - -(defun ess--flush-help-into-current-buffer (object &optional command) - (let ((inhibit-modification-hooks t) - (inhibit-read-only t)) - (delete-region (point-min) (point-max)) - (let ((command (if (and command (string-match-p "%s" command)) - (format command object) - command))) - (ess-command (or command (ess-build-help-command object)) (current-buffer))) - (ess-help-underline) - (unless (string= ess-language "STA") - (ess-nuke-help-bs)) - (goto-char (point-min)) - (set-buffer-modified-p 'nil))) - -(defun ess--help-kill-bogus-buffer-maybe (buffer) - "Internal, try to kill bogus BUFFER with message. Return t if killed." - (when ess-help-kill-bogus-buffers - (let ((bog-mes (ess--help-get-bogus-buffer-substring buffer))) - (when bog-mes - ;; The following is giving erroneous messages when help is displayed in the browser - ;; (when (< (length bog-mes) 10) ;;no message at all, how to treat this properly? - ;; (setq bog-mes (format "No documentation found; %s" bog-mes))) - (ess-write-to-dribble-buffer - (format "(ess-help: kill bogus buffer %s ..\n" (buffer-name buffer))) - (message "%s" (replace-regexp-in-string "\n" "" bog-mes)) - ;; (ding) ;; don't ding, in julia a lot of doc strings are very short - (kill-buffer buffer))))) - -(defun ess-display-help-in-browser () - "Displaying HTML help where available, using \\[browse-url]." - (interactive) - ;; Three ways to find HTML help, 1) ask sub-process 2) get URL/file from subprocess - ;; 3) call elisp function to get the file path - ;; For 2 and 3 call browse-url on the output - (let (com-html-help ;1) command for sub-process to trigger - ;help, must contain %s for help obj - com-get-file-path ;2) command for sub-process to return a - ; location for the help page, must - ; contain %s for help obj - fun-get-file-path ;3) elisp function to return the - ;location, gets one argument, help topic - not-implemented - ) - (cond - ((string-match "^R" ess-dialect) - (setq com-html-help "help('%s', help_type='html')\n")) - (t (setq not-implemented t)) - ) - (if not-implemented - (message "Sorry, not implemented for %s " ess-dialect) - (if (or (not ess-help-object) - (not (eq ess-help-type 'help))) - (message "No help topic found") - (if com-html-help - (ess-command (format com-html-help ess-help-object)) - (require 'browse-url) - (if com-get-file-path - (browse-url (car (ess-get-words-from-vector - (format com-get-file-path ess-help-object)))) - (when (functionp fun-get-file-path) - (browse-url (funcall fun-get-file-path ess-help-object))))))))) - -(defun ess--button-action (&optional button) - "Provide help on object at the beginning of line. -It's intended to be used in R-index help pages. Load the package -if necessary. It is bound to RET and C-m in R-index pages." - (let* ((string (button-label button)) - (command (ess-build-help-command string))) - (ess-display-help-on-object string command))) - -(cl-defgeneric ess-help-commands () - "Return an alist of dialect specific retriever commands. -Currently understood commands: - - package-for-object - command to get the package of current help object - - packages - command to get a list of available packages (REQUIRED) - - package-index - command to get the package index (REQUIRED) - - index-keyword-reg - regexp used to find keywords for linking in index listing - only (1st subexpression is used) - - index-start-reg - regexp from where to start searching for keywords in index listing" - (user-error "Not implemented for %s " ess-dialect)) - -(cl-defmethod ess-help-commands (&context (ess-dialect "R")) - '((package-for-object . "sub('package:', '', .ess.findFUN('%s'))\n") - (packages . ".packages(all.available=TRUE)\n") - (package-index . ".ess.help(package='%s', help.type='text')\n") - (index-keyword-reg . "^\\([^ \t\n:]+\\)") - (index-start-reg . "^Index:"))) - -(defun ess-display-package-index (&optional package) - "Prompt for package name and display its index." - (interactive - (list (let* ((coms (ess-help-commands)) - (all-packs (ess-get-words-from-vector (cdr (assoc 'packages coms)))) - (pack (or (when (and ess-help-object - (cdr (assoc 'package-for-object coms)) - (eq ess-help-type 'help)) - (car (ess-get-words-from-vector - (format (cdr (assoc 'package-for-object coms)) - ess-help-object)))) - (car (member (ess-read-object-name-default) all-packs))))) - (ess-completing-read "Index of" all-packs nil nil nil nil pack)))) - (let ((coms (ess-help-commands))) - (ess--display-indexed-help-page - (format (cdr (assoc 'package-index coms)) package) - (cdr (assoc 'index-keyword-reg coms)) - (format "*help[%s](index:%s)*" ess-dialect package) - 'index nil nil (cdr (assoc 'index-start-reg coms)) package))) - -(defun ess--display-indexed-help-page (command item-regexp title help-type - &optional action help-echo reg-start help-object) - "Internal function to display help pages with linked actions. -COMMAND to produce the indexed help page, -ITEM-REGEXP -- first subexpression is highlighted, -TITLE of the help page, -HELP-TYPE to be stored in `ess-help-type' local variable, -ACTION is a function with no argument (default is `ess--button-action'), -HELP-ECHO if given becomes the help-echo property of the button, -REG-START gives the start location from where to search linkifying, and HELP-OBJECT becomes `ess-help-object'." - (let ((inhibit-modification-hooks t) - (alist ess-local-customize-alist) - (pname ess-local-process-name) - (buff (get-buffer-create title))) - (ess-with-current-buffer buff - (setq buffer-read-only nil) - (delete-region (point-min) (point-max)) - (setq ess-local-process-name pname) - (ess--help-major-mode) - (ess-setq-vars-local (eval alist)) - (setq ess-help-object help-object - ess-help-sec-regex "\\(^\\s-.*\n\\)\\|\\(^\n\\)") - (ess-command command buff) - (ess-help-underline) - (set-buffer-modified-p 'nil) - (goto-char (point-min)) - (when reg-start ;; go to the beginning of listing - (re-search-forward reg-start nil t)) - (when item-regexp - ;;linkify the buffer - (save-excursion - (while (re-search-forward item-regexp nil t) - (make-text-button (match-beginning 1) (match-end 1) - 'mouse-face 'highlight - 'action (or action #'ess--button-action) - 'help-object (buffer-substring-no-properties (match-beginning 1) (match-end 1)) - 'follow-link t - 'help-echo (or help-echo "help on object"))))) - (save-excursion ;; why R help adds all these spaces? - (goto-char (point-min)) - (when (re-search-forward "Index:\n\n" nil t) - (let ((beg (point))) - (forward-paragraph 1) - (align-regexp beg (point) "\\(\\s-+\\)")))) - (setq buffer-read-only t) - (setq ess-help-type help-type) - (setq truncate-lines nil)) - (unless (ess--help-kill-bogus-buffer-maybe buff) - (ess-display-help buff)))) - -(defun ess-display-help-apropos (&optional pattern) - "Create an ess-apropos buffer with a *linked* list of apropos topics." - (interactive "sPattern: ") - (let (com regexp) - (cond ((equal ess-dialect "R") - (setq com "help.search('%s')\n" - regexp "^\\([^ \t\n:]+::[^ \t\n:]+\\)[ \t\n]+")) - ((equal ess-dialect "julia") - (setq com "apropos(\"%s\")\n" - regexp "^\\(\\(\\w\\|\\s_\\)+\\)(")) - ((equal ess-dialect "stata") - (setq com "hsearch %s\n" - regexp "^[\t ]*[0-9]+\\.[\t ]+\\(.+\\)$")) - (t (error "Not implemented for dialect %s" ess-dialect))) - (ess--display-indexed-help-page - (format com pattern) regexp - (format "*ess-apropos[%s](%s)*" ess-current-process-name pattern) - 'appropos))) - -(defun ess-display-demos () - "Create an ess-demos buffer with a *linked* list of available demos." - (interactive) - (let (com regexp) - (cond ((equal ess-dialect "R") - (setq com "demo()\n" - regexp "^\\([^ \n:]+\\) +")) - (t (error "Not implemented for dialect %s" ess-dialect))) - (ess--display-indexed-help-page - com regexp - (format "*ess-demos[%s]*" ess-current-process-name) - 'demos #'ess--action-demo))) - -(defun ess--action-demo (&optional button) - "Provide help on object at the beginning of line. -It's intended to be used in R-index help pages. Load the package -if necessary. It is bound to RET and C-m in R-index pages." - (let* ((string (button-label button)) - (command - (cond ((equal ess-dialect "R") - (format "demo('%s')\n" string)) - (t (error "Not implemented for dialect %s" ess-dialect))))) - (ess-eval-linewise command) - (ess-switch-to-end-of-ESS))) - -(defun ess-display-vignettes (&optional all) - "Display vignettes if available for the current dialect. -With (prefix) ALL non-nil, use `vignette(*, all=TRUE)`, i.e., from all installed - packages, which can be *very* slow." - (interactive "P") - (ess--display-vignettes-override all)) - -(cl-defgeneric ess--display-vignettes-override (_all) - "Display vignettes for the current dialect. -See `ess-display-vignettes' for ALL." - (user-error "Sorry, not implemented for %s" ess-dialect)) - -(defun ess--action-open-in-emacs (pos) - (display-buffer (find-file-noselect (get-text-property pos 'help-echo)))) -(defun ess--action-R-open-vignette (pos) - (ess-eval-linewise (format "vignette('%s', package='%s')\n" - (get-text-property pos 'vignette) - (get-text-property pos 'package)))) - -(defalias 'ess-help-quit 'quit-window) -(make-obsolete 'ess-help-quit 'quit-window "16.04") - -(defun ess-display-help (buff) - "Display buffer BUFF. -If `ess-help-pop-to-buffer' is non-nil, call `pop-to-buffer', -otherwise call `display-buffer' to display the buffer. - -You may control how help buffers are displayed by EITHER setting -an entry in `display-buffer-alist' (see examples in info -node `(ess) Controlling buffer display') OR setting the -ESS-specific variables `ess-help-own-frame', -`ess-help-reuse-window', `ess-help-frame-alist', and -`ess-display-buffer-reuse-frames'." - (let* ((action (cond (ess-help-own-frame - '(display-buffer-reuse-window - display-buffer-use-some-frame - display-buffer-pop-up-frame)) - (ess-help-reuse-window - '(display-buffer-reuse-window - ess-display-buffer-reuse-mode-window - display-buffer-pop-up-window - display-buffer-use-some-window)) - (t '(display-buffer-pop-up-window - display-buffer-use-some-window)))) - (alist `((mode . (ess-help-mode ess-r-help-mode ess-stata-help-mode ess-julia-help-mode)) - (reusable-frames . ,ess-display-buffer-reuse-frames) - ;; `display-buffer-use-some-frame' uses this to - ;; determine whether to use the frame or not. - (frame-predicate . (lambda (f) - (when (equal ess-help-own-frame 'one) - ;; Note we're always returning - ;; nil for `ess-help-own-frame' t. - (frame-parameter f 'ess-help-frame)))) - ;; If `display-buffer' makes a new frame, these are - ;; given as frame parameters. - (pop-up-frame-parameters . ,(append ess-help-frame-alist - `((auto-hide-function . delete-frame) - (ess-help-frame . ,(equal ess-help-own-frame 'one))))))) - (display-alist `(,action . ,alist))) - (if ess-help-pop-to-buffer - (pop-to-buffer buff display-alist) - (display-buffer buff display-alist)))) - -(defun ess-help-web-search (cmd) - "Search the web for documentation on CMD." - (interactive "sSearch for: ") - (ess--help-web-search-override cmd)) - -(cl-defgeneric ess--help-web-search-override (_cmd) - "Dialect-specific override for `ess-help-web-search', which see for CMD." - (error "Not implemented for %s" ess-dialect)) - -(defun ess-manual-lookup () - "Search manual for documentation." - (interactive) - (ess--manual-lookup-override)) - -(cl-defgeneric ess--manual-lookup-override () - "Dialect-specific override for `ess-manual-lookup'." - (error "Not implemented for %s" ess-dialect)) - -(defvar ess-doc-map - (let (ess-doc-map) - (define-prefix-command 'ess-doc-map) - (define-key ess-doc-map "\C-e" #'ess-describe-object-at-point) - (define-key ess-doc-map "e" #'ess-describe-object-at-point) - (define-key ess-doc-map "\C-d" #'ess-display-help-on-object) - (define-key ess-doc-map "d" #'ess-display-help-on-object) - (define-key ess-doc-map "\C-i" #'ess-display-package-index) - (define-key ess-doc-map "i" #'ess-display-package-index) - (define-key ess-doc-map "\C-a" #'ess-display-help-apropos) - (define-key ess-doc-map "a" #'ess-display-help-apropos) - (define-key ess-doc-map "\C-v" #'ess-display-vignettes) - (define-key ess-doc-map "v" #'ess-display-vignettes) - (define-key ess-doc-map "\C-o" #'ess-display-demos) - (define-key ess-doc-map "o" #'ess-display-demos) - (define-key ess-doc-map "\C-w" #'ess-help-web-search) - (define-key ess-doc-map "w" #'ess-help-web-search) - (define-key ess-doc-map "\C-m" #'ess-manual-lookup) - (define-key ess-doc-map "m" #'ess-manual-lookup) - ess-doc-map) - "ESS documentation map.") - - -(defvar ess-help-mode-map - (let ((map (make-keymap))) - (define-key map "\C-m" #'next-line) - (define-key map "h" #'ess-display-help-on-object) - (define-key map "w" #'ess-display-help-in-browser) - (define-key map "i" #'ess-display-package-index) - (define-key map "a" #'ess-display-help-apropos) - (define-key map "v" #'ess-display-vignettes) - (define-key map "l" #'ess-eval-line-visibly-and-step) - (define-key map "r" #'ess-eval-region-and-go) - (define-key map "f" #'ess-eval-function-or-paragraph-and-step) - (define-key map "n" #'ess-skip-to-next-section) - (define-key map "p" #'ess-skip-to-previous-section) - (define-key map "/" #'isearch-forward) - (define-key map "x" #'ess-kill-buffer-and-go) - (define-key map "k" #'kill-this-buffer) - (define-key map "\C-c\C-s" #'ess-switch-process) - (define-key map "\C-c\C-r" #'ess-eval-region) - (define-key map "\C-c\M-r" #'ess-eval-region-and-go) - (define-key map "\C-c\C-f" #'ess-eval-function) - (define-key map "\M-\C-x" #'ess-eval-function) - (define-key map "\C-c\M-f" #'ess-eval-function-and-go) - (define-key map "\C-c\C-j" #'ess-eval-line) - (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) - (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) - (define-key map [(control return)] #'ess-eval-region-or-line-visibly-and-step) - (define-key map "\C-c\M-j" #'ess-eval-line-and-go) - (define-key map "\M-\C-a" #'ess-goto-beginning-of-function-or-para) - (define-key map "\M-\C-e" #'ess-goto-end-of-function-or-para) - (define-key map "\C-c\C-y" #'ess-switch-to-ESS) - (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) - (define-key map "\C-c\C-l" #'ess-load-file) - (define-key map "\C-c\M-l" #'ess-load-file); alias, as in #'iESS#' where C-c C-l is comint-list-* - (define-key map "\C-c\C-v" #'ess-display-help-on-object) - (define-key map "\C-c\C-k" #'ess-request-a-process) - (define-key map "\C-c\C-d" 'ess-doc-map) - (define-key map "\C-c\C-e" 'ess-extra-map) - (define-key map "\C-c\C-t" 'ess-dev-map) - map) - "Keymap for ESS help mode.") - -;; One reason for the following menu is to the user about key strokes -(defvar ess-help-mode-menu - '("ESS-help" - ["Search forward" isearch-forward t] - ["Next section" ess-skip-to-next-section t] - ["Previous section" ess-skip-to-previous-section t] - ["Help on section skipping" ess-describe-sec-map t] - ["Beginning of buffer" beginning-of-buffer t] - ["End of buffer" end-of-buffer t] - "-" - ["Help on ..." ess-display-help-on-object t] - ["Apropos of ..." ess-display-help-apropos t] - ["Index of ..." ess-display-package-index t] - ["Vignettes" ess-display-vignettes t] - ["Open in browser" ess-display-help-in-browser t] - "-" - ["Eval line" ess-eval-line-and-step t] - ["Eval paragraph & step" ess-eval-paragraph-and-step t] - ["Eval region & go" ess-eval-region-and-go t] - ["Switch to ESS process" ess-switch-to-ESS t] - ["Switch to end of ESS proc." ess-switch-to-end-of-ESS t] - ["Switch _the_ process" ess-switch-process t] - "-" - ["Kill buffer" kill-this-buffer t] - ["Kill buffer & go" ess-kill-buffer-and-go t] - "-" - ["Handy commands" ess-handy-commands t]) - "Menu used in ess-help mode.") - -(easy-menu-define ess-help-mode-menu-map ess-help-mode-map - "Menu keymap for ess-help mode." ess-help-mode-menu) - -(define-derived-mode ess-help-mode special-mode "ESS Help" - "Mode for viewing ESS help files." - :group 'ess-help - ;; FIXME - ;; (if ess-mode-syntax-table ;;set in advance by ess-setq-local - ;; (set-syntax-table ess-mode-syntax-table)) - (setq-local revert-buffer-function #'ess-help-revert-buffer) - (setq show-trailing-whitespace nil)) - - -;;*;; User commands defined in ESS help mode - -(defun ess-skip-to-help-section () - "Jump to a section heading of a help buffer. -The section selected is determined by the command letter used to -invoke the command, as indicated by `ess-help-sec-keys-alist'. -Use \\[ess-describe-sec-map] to see which keystrokes find which -sections." - (interactive) - (let ((old-point (point)) - (case-fold-search nil) - (the-sec (cdr (assoc last-command-event ess-help-sec-keys-alist)))) - (cl-assert the-sec nil (format "Invalid section key: %c" last-command-event)) - (goto-char (point-min)) - (if (re-search-forward (concat "^" the-sec) nil t) - (progn (recenter) - (beginning-of-line)) - (message "No %s section in this help. Sorry." the-sec) - (goto-char old-point)))) - -(defun ess-skip-to-next-section () - "Jump to next section in ESS help buffer." - (interactive) - (let ((case-fold-search nil)) - (when (looking-at-p ess-help-sec-regex) - (forward-line)) - (if (re-search-forward ess-help-sec-regex nil 'no-error) - (beginning-of-line) - (message "No more sections.")))) - -(defun ess-skip-to-previous-section () - "Jump to previous section in ESS help buffer." - (interactive) - (let ((case-fold-search nil)) - (if (re-search-backward ess-help-sec-regex nil 'no-error) - (beginning-of-line) - (message "No previous section.")))) - -(defun ess-kill-buffer-and-go nil - "Kill the current buffer and switch back to the ESS process." - (interactive) - (kill-buffer (current-buffer)) - (when (and ess-current-process-name (get-process ess-current-process-name)) - (ess-switch-to-ESS nil))) - -(defun ess-describe-sec-map nil - "Display help for the `s' key." - (interactive) - (let ((keys-alist ess-help-sec-keys-alist)) - (describe-function 'ess-skip-to-help-section) - - (with-current-buffer "*Help*" - (setq buffer-read-only nil) - (goto-char (point-max)) - (insert "\n\nCurrently defined keys are: - -Keystroke Section ---------- -------\n") - (dolist (cs keys-alist) - (insert " " - (car cs) - " " - (cdr cs) "\n"))))) - -(defun ess-helpobjs-at-point--read-obj () - (let* ((obj (ess-read-object-name-default))) - ;; Exclude numbers - (unless (and obj (not (string-match "[[:alpha:]]" obj))) - obj))) - -(defun ess-unqualify-symbol (object) - (if (string-match "^[[:alnum:].]+::?" object) - (substring object (match-end 0)) - object)) - -(defun ess-helpobjs-at-point (slist) - "Return a list (def obj fun). -Obj is a name at point, fun is the name of the function call -point is in, and def is either obj or fun (in that order) which -has a a help file, i.e. it is a member of SLIST (string-list). -nil otherwise." - (let* ((obj (ess-helpobjs-at-point--read-obj)) - (unqualified-obj (and obj (ess-unqualify-symbol obj))) - ;; FIXME: probably should use syntactic logic here - (fun (ignore-errors - (save-excursion - (save-restriction - (narrow-to-region (max (point-min) (- (point) 1000)) - (point-max)) - (backward-up-list 1) - (backward-char 1) - (ess-read-object-name-default)))))) - (list (or (car (member obj slist)) - (when (member unqualified-obj slist) - obj) - (car (member fun slist))) - obj fun))) - -(cl-defgeneric ess-help-get-topics (proc) - "Return a list of help topics from PROC." - (user-error "Not supported for %s (process: %s)" ess-dialect proc)) - -(defun ess-find-help-file (p-string) - "Find help, prompting for P-STRING." - (ess-make-buffer-current) - (let* ((help-files-list (ess-help-get-topics ess-current-process-name)) - (hlpobjs (delq nil (ess-helpobjs-at-point help-files-list)))) - (ess-completing-read p-string (append hlpobjs help-files-list) - nil nil nil nil (car hlpobjs)))) - - -;;*;; Utility functions - -(defun ess-get-help-files-list () - "Return a list of files which have help available." - (apply 'nconc - (mapcar (lambda (str) - (let ((dirname (concat str "/.Help"))) - (and (file-directory-p dirname) - (directory-files dirname)))) - (ess-search-list)))) - -(defun ess-get-help-aliases-list () - "Return a list of aliases which have help available." - (message "Retrieving RDS aliases...") - ;; ess-command locks display, make sure the above message is visible - (redisplay t) - (ess-write-to-dribble-buffer "Processing RDS files ...\n") - (prog1 (ess-get-words-from-vector ".ess.getHelpAliases()\n") - (message "Retrieving RDS aliases...done"))) - -(defun ess-nuke-help-bs () - "Remove ASCII underlining and overstriking performed by ^H codes." - ;; This function is a modification of nuke-nroff-bs in man.el from the - ;; standard Emacs 18 lisp library. - ;; Nuke underlining and overstriking (only by the same letter) - (goto-char (point-min)) - (while (search-forward "\b" nil t) - (let* ((preceding (char-after (- (point) 2))) - (following (following-char))) - (cond ((= preceding following) - ;; x\bx - (delete-char -2)) - ((= preceding ?\_) - ;; _\b - (delete-char -2)) - ((= following ?\_) - ;; \b_ - (delete-region (1- (point)) (1+ (point))))))) - (goto-char (point-min)) - (let ((case-fold-search nil)); 'URL' != 'url' ('libcurl: ' on ?capabilities) - (while (re-search-forward "\\bURL: " nil t); test with ?rtags - ;; quick fix for C-x f confusion (getting into tramp) - (delete-region (match-beginning 0) (match-end 0)))) - ;; Crunch blank lines - (goto-char (point-min)) - (while (re-search-forward "\n\n\n\n*" nil t) - (replace-match "\n\n")) - ;; Nuke blanks lines at start. - (goto-char (point-min)) - (skip-chars-forward "\n") - (delete-region (point-min) (point))) - -(defun ess-help-underline () - "Replace _^H codes with underline face." - (save-excursion - (goto-char (point-min)) - (while (search-forward "_" nil t) - (backward-delete-char 2) - (put-text-property (point) (1+ (point)) 'face 'underline)))) - -;;*;; Link to Info -(defun ess-goto-info (node) - "Display node NODE from `ess-mode' info." - (require 'info) - (split-window) - (Info-goto-node (concat "(ess)" node))) - - -;; describe object at point - -(defvar-local ess-describe-object-at-point-commands nil - "Commands cycled by `ess-describe-object-at-point'. -Dialect specific.") - -(defvar ess--descr-o-a-p-commands nil) - -(defun ess-describe-object-at-point () - "Get info for object at point, & display it in an electric buffer or tooltip. -If region is active use it instead of the object at point. - -This is an electric command (`ess--execute-electric-command'), -which means that you can use the last key to cycle through the -action set (in this case `C-e'). After invocation of this command -all standard Emacs commands, except those containing 'window' in -their names, remove the electric *ess-describe* buffer. Use -`other-window' to switch to *ess-describe* window. - -Customize `ess-describe-at-point-method' if you wan to display -the description in a tooltip. See also -`ess-r-describe-object-at-point-commands' (and similar option for -other dialects)." - (interactive) - (if (not ess-describe-object-at-point-commands) - (message "Not implemented for dialect %s" ess-dialect) - (ess-force-buffer-current) - (let ((map (make-sparse-keymap)) - (objname (or (and (use-region-p) - (buffer-substring-no-properties (point) (mark))) - (ess-symbol-at-point))) - ess--descr-o-a-p-commands) ;; used in ess--describe-object-at-point - (unless objname (error "No object at point ")) - (define-key map (vector last-command-event) 'ess--describe-object-at-point) - ;; todo: put digits into the map - (let* ((inhibit-quit t) ;; C-g removes the buffer - (buf (ess--execute-electric-command - map (format "Press %s to cycle" - (single-key-description last-command-event)) - nil nil objname)) - ;; read full command - (keys (read-key-sequence-vector "")) - (command (and keys (key-binding keys)))) - (when (and (commandp command) - (bufferp buf) - (or (not (symbolp command)) ;; kill on lambdas - (not (string-match "window" (symbol-name command))))) - (kill-buffer buf)) ;; bury does not work here :( (Emacs bug?) - (setq unread-command-events - (append keys unread-command-events)))))) - -(defun ess--describe-object-at-point (_ev objname) - (setq ess--descr-o-a-p-commands (or ess--descr-o-a-p-commands - (symbol-value ess-describe-object-at-point-commands))) - (let* ((com (format (car (pop ess--descr-o-a-p-commands)) objname)) - (buf (get-buffer-create "*ess-describe*")) - pos) - (unless (eq ess-describe-at-point-method 'tooltip) - ;; can take some time for the command to execute - (display-buffer buf)) - (sit-for .01) - (ess-command (concat com "\n") buf) ;; erases buf - (with-current-buffer buf - (goto-char (point-min)) - (insert (propertize (format "%s:\n\n" com) 'face 'font-lock-string-face)) - (forward-line -1) - (setq pos (point)) - ;; set the keys that we are used to in help mode - (special-mode) - (let ((inhibit-read-only t)) - (ansi-color-apply-on-region (point-min) (point-max)))) - (if (eq ess-describe-at-point-method 'tooltip) - (ess-tooltip-show-at-point - (with-current-buffer buf (buffer-string)) 0 30) - (display-buffer buf) - (set-window-point (get-buffer-window buf) pos) ;; don't move window point - buf))) - -(with-no-warnings - ;; We're just backporting here, don't care about compiler warnings - (defalias 'ess-display-buffer-reuse-mode-window - ;; TODO: Remove once we drop support for Emacs 25 - (if (fboundp 'display-buffer-reuse-mode-window) - 'display-buffer-reuse-mode-window - (lambda (buffer alist) - (let* ((alist-entry (assq 'reusable-frames alist)) - (alist-mode-entry (assq 'mode alist)) - (frames (cond (alist-entry (cdr alist-entry)) - ((if (eq pop-up-frames 'graphic-only) - (display-graphic-p) - pop-up-frames) - 0) - (display-buffer-reuse-frames 0) - (t (last-nonminibuffer-frame)))) - (inhibit-same-window-p (cdr (assq 'inhibit-same-window alist))) - (windows (window-list-1 nil 'nomini frames)) - (buffer-mode (with-current-buffer buffer major-mode)) - (allowed-modes (if alist-mode-entry - (cdr alist-mode-entry) - buffer-mode)) - (curwin (selected-window)) - (curframe (selected-frame))) - (unless (listp allowed-modes) - (setq allowed-modes (list allowed-modes))) - (let (same-mode-same-frame - same-mode-other-frame - derived-mode-same-frame - derived-mode-other-frame) - (dolist (window windows) - (let ((mode? - (with-current-buffer (window-buffer window) - (cond ((memq major-mode allowed-modes) - 'same) - ((derived-mode-p allowed-modes) - 'derived))))) - (when (and mode? - (not (and inhibit-same-window-p - (eq window curwin)))) - (push window (if (eq curframe (window-frame window)) - (if (eq mode? 'same) - same-mode-same-frame - derived-mode-same-frame) - (if (eq mode? 'same) - same-mode-other-frame - derived-mode-other-frame)))))) - (let ((window (car (nconc same-mode-same-frame - same-mode-other-frame - derived-mode-same-frame - derived-mode-other-frame)))) - (when (window-live-p window) - (prog1 (window--display-buffer buffer window 'reuse alist) - (unless (cdr (assq 'inhibit-switch-frame alist)) - (window--maybe-raise-frame (window-frame window)))))))))))) - -(provide 'ess-help) -;;; ess-help.el ends here diff --git a/elpa/ess-20191014.1343/ess-inf.el b/elpa/ess-20191014.1343/ess-inf.el deleted file mode 100644 index 815b8313..00000000 --- a/elpa/ess-20191014.1343/ess-inf.el +++ /dev/null @@ -1,2974 +0,0 @@ -;;; ess-inf.el --- Support for running S as an inferior Emacs process -*- lexical-binding: t; -*- - -;; Copyright (C) 1989-1994 Bates, Kademan, Ritter and Smith -;; Copyright (C) 1997-1999 A.J. Rossini , -;; Martin Maechler . -;; Copyright (C) 2000--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: David Smith -;; Created: 7 Jan 1994 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Code for handling running ESS processes. - -;;; Code: - -(eval-when-compile - (require 'cl-lib) - (require 'tramp) - (require 'subr-x)) -(require 'ess-utils) -(require 'ess) -(require 'ess-tracebug) - -(require 'ansi-color) -(require 'comint) -(require 'compile) -(require 'format-spec) -(require 'overlay) -(require 'project) - -;; Don't require tramp at run time. It's an expensive library to load. -;; Instead, guard calls with (require 'tramp) and silence the byte -;; compiler. -(declare-function tramp-sh-handle-expand-file-name "tramp-sh" (name &optional dir)) -(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) -(declare-function tramp-tramp-file-p "tramp" (name)) -(declare-function inferior-ess-r-mode "ess-r-mode" ()) -(declare-function inferior-ess-julia-mode "ess-julia" ()) -(declare-function inferior-ess-stata-mode "ess-stata-mode" ()) -(declare-function extract-rectangle-bounds "rect" (start end)) - -(declare-function ess-mode "ess-mode" ()) -(declare-function ess-complete-object-name "ess-r-completion" ()) -;; FIXME:This one should not be necessary -(declare-function ess-display-help-on-object "ess-help" (object &optional command)) -(declare-function ess-dump-object-into-edit-buffer "ess-mode" (object)) - -(defvar add-log-current-defun-header-regexp) - -;; The following declares can be removed once we drop Emacs 25 -(declare-function tramp-file-name-method "tramp") -(declare-function tramp-file-name-user "tramp") -(declare-function tramp-file-name-host "tramp") -(declare-function tramp-file-name-localname "tramp") -(declare-function tramp-file-name-hop "tramp") - -(defcustom inferior-ess-mode-hook nil - "Hook for customizing inferior ESS mode. -Called after `inferior-ess-mode' is entered and variables have -been initialized." - :group 'ess-hooks - :type 'hook) - -(defvar inferior-ess-mode-syntax-table - (let ((tab (copy-syntax-table comint-mode-syntax-table))) - tab) - "Syntax table for `inferior-ess-mode'.") - -(defun inferior-ess--set-major-mode (dialect) - "Set major mode according to DIALECT." - (cond ((string= "R" dialect) - (progn (require 'ess-r-mode) - (inferior-ess-r-mode))) - ((string= "julia" dialect) - (progn (require 'ess-julia) - (inferior-ess-julia-mode))) - ((string= "stata" dialect) - (progn (require 'ess-stata-mode) - (inferior-ess-stata-mode))) - ;; FIXME: we need this horrible hack so that - ;; inferior-ess-mode-syntax-table gets set for - ;; languages that still rely on the old way of doing - ;; things (before we used define-derived-mode for - ;; inferior modes). - (t - (progn - (setq-local inferior-ess-mode-syntax-table - (eval (or (alist-get 'inferior-ess-mode-syntax-table ess-local-customize-alist) - (alist-get 'ess-mode-syntax-table ess-local-customize-alist)))) - (inferior-ess-mode))))) - - ;;*;; Process handling - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; In this section: -;;; -;;; * User commands for starting an ESS process -;;; * Functions called at startup -;;; * Process handling code -;;; * Multiple process implementation -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;*;; Starting a process -(defun ess-proc-name (n name) - "Return name of process N, as a string, with NAME prepended. -If `ess-plain-first-buffername', then initial process is number-free." - (concat name - (if (not (and ess-plain-first-buffername - (= n 1))) ; if not both first and plain-first add number - (concat ":" (number-to-string n))))) - -(defvar-local inferior-ess--local-data nil - "Program name and arguments used to start the inferior process.") - -(defun inferior-ess (start-args customize-alist &optional no-wait) - "Start inferior ESS process. -Without a prefix argument, starts a new ESS process, or switches -to the ESS process associated with the current buffer. With -START-ARGS (perhaps specified via \\[universal-argument]), starts -the process with those args. The current buffer is used if it is -an `inferior-ess-mode' or `ess-transcript-mode' buffer. - -If `ess-ask-about-transfile' is non-nil, you will be asked for a -transcript file to use. If there is no transcript file, the -buffer name will be like *R* or *R2*, determined by -`ess-gen-proc-buffer-name-function'. - -Takes the program name from the variable `inferior-ess-program'. - -See Info node `(ess)Customizing startup' and -`display-buffer-alist' to control where and how the buffer is -displayed. - -\(Type \\[describe-mode] in the process buffer for a list of -commands.) - -CUSTOMIZE-ALIST is the list of dialect-specific variables. When -non-nil, NO-WAIT tells ESS not to wait for the process to finish. -This may be useful for debugging." - ;; Use the current buffer if it is in inferior-ess-mode or ess-trans-mode - ;; If not, maybe ask about starting directory and/or transcript file. - ;; If no transfile, use buffer *S* - ;; This function is primarily used to figure out the Process and - ;; buffer names to use for inferior-ess. - (run-hooks 'ess-pre-run-hook) - (let* ((dialect (eval (cdr (assoc 'ess-dialect customize-alist)))) - (process-environment process-environment) - ;; Use dialect if not R, R program name otherwise - (temp-dialect (if ess-use-inferior-program-in-buffer-name ;VS[23-02-2013]: FIXME: this should not be here - (if (string-equal dialect "R") - (file-name-nondirectory inferior-ess-r-program) - dialect) - dialect)) - (inf-buf (inferior-ess--get-proc-buffer-create temp-dialect)) - (proc-name (buffer-local-value 'ess-local-process-name inf-buf)) - (cur-dir (inferior-ess--maybe-prompt-startup-directory proc-name temp-dialect)) - (default-directory cur-dir)) - (with-current-buffer inf-buf - ;; TODO: Get rid of this, we should rely on modes to set the - ;; variables they need. - (ess-setq-vars-local customize-alist) - (inferior-ess--set-major-mode ess-dialect) - ;; Set local variables after changing mode because they might - ;; not be permanent - (setq default-directory cur-dir) - (setq inferior-ess--local-data (cons inferior-ess-program start-args)) - ;; Read the history file - (when ess-history-file - (setq comint-input-ring-file-name - (expand-file-name (if (eql t ess-history-file) - (concat "." ess-dialect "history") - ess-history-file) - ess-history-directory)) - (comint-read-input-ring)) - ;; Show the buffer - ;; TODO: Remove inferior-ess-own-frame after ESS 19.04, then just have: - ;; (pop-to-buffer inf-buf) - (pop-to-buffer inf-buf (with-no-warnings - (when inferior-ess-own-frame - '(display-buffer-pop-up-frame)))) - (let ((proc (inferior-ess--start-process inf-buf proc-name start-args))) - (ess-make-buffer-current) - (goto-char (point-max)) - (unless no-wait - (ess-write-to-dribble-buffer "(inferior-ess: waiting for process to start (before hook)\n") - (ess-wait-for-process proc nil 0.01 t)) - (unless (and proc (eq (process-status proc) 'run)) - (error "Process %s failed to start" proc-name)) - (when ess-setwd-command - (ess-set-working-directory cur-dir)) - (setq-local font-lock-fontify-region-function #'inferior-ess-fontify-region) - (setq-local ess-sl-modtime-alist nil) - (run-hooks 'ess-post-run-hook) - ;; User initialization can take some time ... - (unless no-wait - (ess-write-to-dribble-buffer "(inferior-ess 3): waiting for process after hook") - (ess-wait-for-process proc))) - inf-buf))) - -(defun inferior-ess--get-proc-buffer-create (name) - "Get a process buffer, creating a new one if needed. -This always returns a process-less buffer. The variable -`ess-local-process-name' is set in the buffer with the name of -the next process to spawn. This name may be different from the -buffer name, depending on how `ess-gen-proc-buffer-name-function' -generated the latter from NAME." - (let* ((proc-name (let ((ntry 1)) - ;; Find the next non-existent process N (*R:N*) - (while (get-process (ess-proc-name ntry name)) - (setq ntry (1+ ntry))) - (ess-proc-name ntry name))) - (inf-name (funcall ess-gen-proc-buffer-name-function proc-name))) - (let ((buf (cond - ;; Try to use current buffer, if inferior-ess-mode but - ;; no process - ((and (not (comint-check-proc (current-buffer))) - (derived-mode-p 'inferior-ess-mode)) - ;; Don't change existing buffer name in this case. It - ;; is very common to restart the process in the same - ;; buffer. - (setq proc-name ess-local-process-name) - (current-buffer)) - ;; Pick up a transcript file - (ess-ask-about-transfile - (let ((transfilename (read-file-name - "Use transcript file (default none):" nil ""))) - (if (string= transfilename "") - (get-buffer-create inf-name) - (find-file-noselect (expand-file-name transfilename))))) - ;; Create a new buffer or take the *R:N* buffer if - ;; already exists (it should contain a dead process) - (t - (get-buffer-create inf-name))))) - ;; We generated a new process name but there might still be a - ;; live process in the buffer in corner cases because of - ;; `ess-gen-proc-buffer-name-function` or if the user renames - ;; inferior buffers - (when (comint-check-proc buf) - (error "Can't start a new session in buffer `%s` because one already exists" - inf-name)) - (with-current-buffer buf - (setq-local ess-local-process-name proc-name)) - buf))) - -(defun ess--accumulation-buffer (proc) - (let ((abuf (process-get proc :accum-buffer))) - (if (buffer-live-p abuf) - abuf - (let ((abuf (get-buffer-create (format " *%s:accum*" (process-name proc))))) - (process-put proc :accum-buffer abuf) - (with-current-buffer abuf - (buffer-disable-undo) - (setq-local inhibit-modification-hooks t)) - abuf)))) - -(defvar-local inferior-ess-objects-command nil - "The language/dialect specific command for listing objects. -It is initialized from the corresponding inferior--objects-command -and then made buffer local."); and the *--* ones are customized! - -(defvar-local ess-save-lastvalue-command nil - "The command to save the last value. See S section for more details. -Default depends on the ESS language/dialect and hence made buffer local") - -(defvar-local ess-retr-lastvalue-command nil - "The command to retrieve the last value. See S section for more details. -Default depends on the ESS language/dialect and hence made buffer local") - -(defun inferior-ess-fontify-region (beg end &optional verbose) - "Fontify output by output to avoid fontification spilling over prompts." - (let* ((buffer-undo-list t) - (inhibit-point-motion-hooks t) - (font-lock-dont-widen t) - (font-lock-extend-region-functions nil) - (pos1 beg) - (pos2)) - (when (< beg end) - (with-silent-modifications - ;; fontify chunks from prompt to prompt - (while (< pos1 end) - (goto-char pos1) - (comint-next-prompt 1) - (setq pos2 (min (point) end)) - (save-restriction - (narrow-to-region pos1 pos2) - (font-lock-default-fontify-region pos1 pos2 verbose)) - (setq pos1 pos2)) - ;; highlight errors - (setq compilation--parsed beg) - `(jit-lock-bounds ,beg . ,end))))) - -(defun ess-gen-proc-buffer-name:simple (proc-name) - "Function to generate buffer name by wrapping PROC-NAME in *proc-name*. -See `ess-gen-proc-buffer-name-function'." - (format "*%s*" proc-name)) - -(defun ess-gen-proc-buffer-name:directory (proc-name) - "Function to generate buffer name by wrapping PROC-NAME in *PROC-NAME:DIR-NAME*. -DIR-NAME is a short directory name. See -`ess-gen-proc-buffer-name-function'." - (format "*%s:%s*" proc-name (file-name-nondirectory - (directory-file-name default-directory)))) - -(defun ess-gen-proc-buffer-name:abbr-long-directory (proc-name) - "Function to generate buffer name in the form *PROC-NAME:ABBREVIATED-LONG-DIR-NAME*. -PROC-NAME is a string representing an internal process -name. ABBREVIATED-LONG-DIR-NAME is an abbreviated full directory -name. Abbreviation is performed by `abbreviate-file-name'. See -`ess-gen-proc-buffer-name-function'." - (format "*%s:%s*" proc-name (abbreviate-file-name default-directory))) - -(defun ess-gen-proc-buffer-name:project-or-simple (proc-name) - "Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*. -PROC-NAME is a string representing an internal process name. -PROJECT-ROOT is directory name returned by `project-roots'. If no -project directory has been found use -`ess-gen-proc-buffer-name:simple'. See -`ess-gen-proc-buffer-name-function'." - (if-let ((p (project-current)) - (proj (car (project-roots p)))) - (format "*%s:%s*" proc-name (file-name-nondirectory - (directory-file-name proj))) - (ess-gen-proc-buffer-name:simple proc-name))) - -(defun ess-gen-proc-buffer-name:project-or-directory (proc-name) - "Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*. -PROC-NAME is a string representing an internal process name. -PROJECT-ROOT is directory name returned by `project-roots' if -defined. If no project directory has been found, use -`ess-gen-proc-buffer-name:directory'. See -`ess-gen-proc-buffer-name-function'." - (if-let ((p (project-current)) - (proj (car (project-roots p)))) - (format "*%s:%s*" proc-name (file-name-nondirectory - (directory-file-name proj))) - (ess-gen-proc-buffer-name:directory proc-name))) - -;; This ensures that people who have this set in their init file don't -;; get errors about undefined functions after upgrading ESS: -(define-obsolete-function-alias 'ess-gen-proc-buffer-name:projectile-or-simple - 'ess-gen-proc-buffer-name:project-or-simple "ESS 19.04") -(define-obsolete-function-alias 'ess-gen-proc-buffer-name:projectile-or-directory - 'ess-gen-proc-buffer-name:project-or-directory "ESS 19.04") - -(defun inferior-ess-available-p (&optional proc) - "Return non-nil if PROC is not busy." - (when-let ((proc (or proc (and ess-local-process-name - (get-process ess-local-process-name))))) - (unless (process-get proc 'busy) - (or (ess-debug-active-p proc) ; don't send empty lines in debugger - (when-let ((last-check (process-get proc 'last-availability-check))) - (time-less-p (process-get proc 'last-eval) last-check)) - (progn - ;; Send an empty string and waiting a bit to make sure we are not busy. - (process-send-string proc "\n") - (inferior-ess-mark-as-busy proc) - (process-put proc 'availability-check t) - ;; Start with a very conservative waiting time and quickly average - ;; down to the actual response. - (let ((avresp (or (process-get proc 'average-response-time) 0.1)) - (ts (current-time))) - (when (accept-process-output proc (max 0.005 (* 2.0 avresp))) - (let ((avresp (/ (+ (* 2.0 avresp) - (float-time (time-subtract (current-time) ts))) - 3.0))) - (process-put proc 'average-response-time avresp))) - (process-put proc 'last-availability-check ts)) - (not (process-get proc 'busy))))))) - -(defun inferior-ess--set-status (proc string) - "Internal function to set the status of process PROC. -Return non-nil if the process is in a ready (not busy) state." - ;; TODO: do it in one search, use starting position, use prog1 - (let ((ready (string-match-p (concat "\\(" inferior-ess-primary-prompt "\\)\\'") string))) - (process-put proc 'busy-end? (and ready (process-get proc 'busy))) - ;; When "\n" inserted from inferior-ess-available-p, delete the prompt. - (when (and ready - (process-get proc 'availability-check) - (string-match-p (concat "^" inferior-ess-primary-prompt "\\'") string)) - (process-put proc 'suppress-next-output? t)) - (process-put proc 'availability-check nil) - (when ready - (process-put proc 'running-async? nil)) - (process-put proc 'busy (not ready)) - (process-put proc 'sec-prompt - (when inferior-ess-secondary-prompt - (string-match (concat "\\(" inferior-ess-secondary-prompt "\\)\\'") string))) - ready)) - -(defun inferior-ess-mark-as-busy (proc) - (process-put proc 'busy t) - (process-put proc 'sec-prompt nil)) - -(defun inferior-ess-run-callback (proc string) - ;; callback is stored in 'callbacks proc property. Callbacks is a list that - ;; can contain either functions to be called with two arguments PROC and - ;; STRING, or cons cells of the form (func . suppress). If SUPPRESS is non-nil - ;; next process output will be suppressed. - (unless (process-get proc 'busy) - ;; only one callback is implemented for now - (let* ((cb (car (process-get proc 'callbacks))) - (listp (not (functionp cb))) - (suppress (and listp (consp cb) (cdr cb))) - (cb (if (and listp (consp cb)) - (car cb) - cb))) - (when cb - (when ess-verbose - (ess-write-to-dribble-buffer "executing callback ...\n")) - (when suppress - (process-put proc 'suppress-next-output? t)) - (process-put proc 'callbacks nil) - (condition-case-unless-debug err - (funcall cb proc string) - (error (message "%s" (error-message-string err)))))))) - -(defun ess--if-verbose-write-process-state (proc string &optional filter) - (ess-if-verbose-write - (format "\n%s: - --> busy:%s busy-end:%s sec-prompt:%s interruptable:%s <-- - --> running-async:%s callback:%s suppress-next-output:%s <-- - --> dbg-active:%s is-recover:%s <-- - --> string:%s\n" - (or filter "NORMAL-FILTER") - (process-get proc 'busy) - (process-get proc 'busy-end?) - (process-get proc 'sec-prompt) - (process-get proc 'interruptable?) - (process-get proc 'running-async?) - (if (process-get proc 'callbacks) "yes") - (process-get proc 'suppress-next-output?) - (process-get proc 'dbg-active) - (process-get proc 'is-recover) - (if (> (length string) 150) - (format "%s .... %s" (substring string 0 50) (substring string -50)) - string)))) - -(defun inferior-ess-output-filter (proc string) - "Standard output filter for the inferior ESS process PROC. -Ring Emacs bell if process output starts with an ASCII bell, and pass -the rest to `comint-output-filter'. -Taken from octave-mod.el." - (inferior-ess--set-status proc string) - (ess--if-verbose-write-process-state proc string) - (inferior-ess-run-callback proc string) - (if (process-get proc 'suppress-next-output?) - ;; works only for suppressing short output, for time being is enough (for callbacks) - (process-put proc 'suppress-next-output? nil) - (comint-output-filter proc (inferior-ess-strip-ctrl-g string)))) - -(defun inferior-ess-strip-ctrl-g (string) - "Strip leading `^G' character. -If STRING starts with a `^G', ring the Emacs bell and strip it. -Depending on the value of `visible-bell', either the frame will -flash or you'll hear a beep. Taken from octave-mod.el." - (if (string-match "^\a" string) - (progn - (ding) - (setq string (substring string 1)))) - string) - -(defun ess-process-sentinel (proc message) - "Sentinel for use with ESS processes. -This marks the process with a message, at a particular time point." - (let ((abuf (process-get proc :accum-buffer))) - (when (buffer-live-p abuf) - (kill-buffer abuf))) - (let ((pbuf (process-buffer proc))) - (when (buffer-live-p pbuf) - (with-current-buffer pbuf - (save-excursion - (setq message (substring message 0 -1)) ; strip newline - (set-buffer (process-buffer proc)) - (comint-write-input-ring) - (goto-char (point-max)) - (insert-before-markers - (format "\nProcess %s %s at %s\n" - (process-name proc) message (current-time-string)))))))) - -;; FIXME: This list is structured as '(("R:2") ("R")). It doesn't -;; appear the CDR are used. Can probably just be '("R:2" "R"). -(defvar ess-process-name-list nil - "Alist of active ESS processes.") - -(defun inferior-ess--start-process (buf proc-name switches) - "Make a comint process in buffer BUF with process PROC-NAME. -SWITCHES is passed to `comint-exec'. BUF is guaranteed to be a -process-less buffer because it was created with -`inferior-ess--get-proc-buffer-create'." - (with-current-buffer buf - (if (eq (buffer-size) 0) nil - (goto-char (point-max)) - (insert "\^L\n"))) - (let ((process-environment - (nconc - (list "STATATERM=emacs" - (format "PAGER=%s" inferior-ess-pager)) - process-environment)) - (tramp-remote-process-environment - (nconc ;; it contains a pager already, so append - (when (boundp 'tramp-remote-process-environment) - (copy-sequence tramp-remote-process-environment)) - (list "STATATERM=emacs" - (format "PAGER=%s" inferior-ess-pager))))) - (comint-exec buf - proc-name - inferior-ess-program - nil - (split-string switches))) - (let ((proc (get-buffer-process buf))) - ;; Set the process hooks - (set-process-sentinel proc 'ess-process-sentinel) - (set-process-filter proc 'inferior-ess-output-filter) - (inferior-ess-mark-as-busy proc) - ;; Add this process to ess-process-name-list, if needed - (let ((conselt (assoc proc-name ess-process-name-list))) - (unless conselt - (setq ess-process-name-list - (cons (cons proc-name nil) ess-process-name-list)))) - proc)) - - -;;*;; Requester functions called at startup - -;; FIXME EMACS 25.1: -;; Deprecate `ess-directory-function' in favor of `project-find-functions'? -(defun inferior-ess--get-startup-directory () - (let ((dir (or (and ess--enable-experimental-projects - (fboundp 'project-current) - (cdr (project-current))) - (and ess-directory-function - (funcall ess-directory-function)) - ess-startup-directory - default-directory))) - (directory-file-name dir))) - -(defun inferior-ess--maybe-prompt-startup-directory (procname dialect) - "Possibly prompt for a startup directory. -When `ess-ask-for-ess-directory' is non-nil, prompt. PROCNAME is -the name of the inferior process (e.g. \"R:1\"), and DIALECT is -the language dialect (e.g. \"R\")." - (let ((default-dir (if (fboundp 'inferior-ess-r--adjust-startup-directory) - (inferior-ess-r--adjust-startup-directory - (inferior-ess--get-startup-directory) dialect) - (inferior-ess--get-startup-directory)))) - (if ess-ask-for-ess-directory - (let ((prompt (format "%s starting project directory? " procname))) - (ess-prompt-for-directory default-dir prompt)) - default-dir))) - -(defun ess-prompt-for-directory (default prompt) - "PROMPT for a directory, using DEFAULT as the usual." - (let* ((def-dir (file-name-as-directory default)) - (the-dir (expand-file-name - (file-name-as-directory - (read-directory-name prompt def-dir def-dir t nil))))) - (if (file-directory-p the-dir) nil - (error "%s is not a valid directory" the-dir)) - the-dir)) - - -;;*;; General process handling code -(defmacro with-ess-process-buffer (no-error &rest body) - "Execute BODY in the process buffer of `ess-current-process-name'. -If NO-ERROR is t don't trigger error when there is not current -process. Symbol *proc* is bound to the current process during the -evaluation of BODY." - (declare (indent 1) (debug t)) - `(let ((*proc* (and ess-local-process-name (get-process ess-local-process-name)))) - (if *proc* - (with-current-buffer (process-buffer *proc*) - ,@body) - (unless ,no-error - (error "No current ESS process"))))) - -(defmacro ess-with-current-buffer (buffer &rest body) - "Like `with-current-buffer' but with transfer of some essential -local ESS vars like `ess-local-process-name'." - (declare (indent 1) (debug t)) - (let ((lpn (make-symbol "lpn")) - (dialect (make-symbol "dialect")) - (alist (make-symbol "alist"))) - `(let ((,lpn ess-local-process-name) - (,dialect ess-dialect) - (,alist ess-local-customize-alist)) - (with-current-buffer ,buffer - (ess-setq-vars-local (eval ,alist)) - (setq ess-local-process-name ,lpn) - (setq ess-dialect ,dialect) - ,@body)))) - -(dolist (mode '(emacs-lisp-mode lisp-interaction-mode)) - (font-lock-add-keywords - mode - '(("(\\(ess-with-current-buffer\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)" - (1 font-lock-keyword-face) - (2 font-lock-variable-name-face))))) - -(defun ess-get-process (&optional name use-another) - "Return the ESS process named by NAME. -If USE-ANOTHER is non-nil, and the process NAME is not -running (anymore), try to connect to another if there is one. By -default (USE-ANOTHER is nil), the connection to another process -happens interactively (when possible)." - (setq name (or name ess-local-process-name)) - (cl-assert name nil "No ESS process is associated with this buffer now") - (update-ess-process-name-list) - (cond ((assoc name ess-process-name-list) - (get-process name)) - ((= 0 (length ess-process-name-list)) - (save-current-buffer - (message "trying to (re)start process %s for language %s ..." - name ess-language) - (ess-start-process-specific ess-language ess-dialect) - ;; and return the process: "call me again" - (ess-get-process name))) - ;; else: there are other running processes - (use-another ; connect to another running process : the first one - (let ((other-name (car (elt ess-process-name-list 0)))) - ;; "FIXME": try to find the process name that matches *closest* - (message "associating with *other* process '%s'" other-name) - (ess-get-process other-name))) - ((and (not noninteractive) - (y-or-n-p - (format "Process %s is not running, but others are. Switch? " name))) - (ess-force-buffer-current (concat ess-dialect " process to use: ") 'force) - (ess-get-process ess-current-process-name)) - (t (error "Process %s is not running" name)))) - -(defun inferior-ess-default-directory () - (ess-get-process-variable 'default-directory)) - -;;--- Unfinished idea (ESS-help / R-help ) -- probably not worth it... -;;- (defun ess-set-inferior-program (filename) -;;- "Allows to set or change `inferior-ess-program', the program (file)name." -;;- (interactive "fR executable (script) file: ") -;;- ;; "f" : existing file {file name completion} ! -;;- (setq inferior-ess-program filename)) -;; the inferior-ess-program is initialized in the customize..alist, -;; e.g. from inferior-ess-r-program ... --> should change rather these. -;; However these really depend on the current ess-language! -;; Plan: 1) must know and use ess-language -;; 2) change the appropriate inferior--program -;; (how?) in R/S : assign(paste("inferior-",ESSlang,"-p...."), filename)) - - -;;*;; Multiple process handling code - -;; FIXME: It seems the only effect of this function is to remove dead -;; processes from `ess-process-name-list'. Am I missing something? -(defun ess-make-buffer-current nil - "Make the process associated with the current buffer the current ESS process. -Returns the name of the process, or nil if the current buffer has none." - (update-ess-process-name-list) - ;; (if ess-local-process-name - ;; (setq ess-current-process-name ess-local-process-name)) - ess-local-process-name) - -(defun ess-get-process-variable (var) - "Return the variable VAR (symbol) local to ESS process called NAME (string)." - (buffer-local-value var (process-buffer (ess-get-process ess-local-process-name)))) - -(defun ess-set-process-variable (var val) - "Set variable VAR (symbol) local to ESS process called NAME (string) to VAL." - (with-current-buffer (process-buffer (ess-get-process ess-local-process-name)) - (set var val))) - -(defun ess-process-live-p (&optional proc) - "Check if the local ess process is alive. -Return nil if current buffer has no associated process, or -process was killed. PROC defaults to `ess-local-process-name'" - (and (or proc ess-local-process-name) - (let ((proc (or proc (get-process ess-local-process-name)))) - (and (processp proc) - (process-live-p proc))))) - -(defun ess-process-get (propname &optional proc) - "Return the variable PROPNAME (symbol) from the plist of the current ESS process. -PROC defaults to process with name `ess-local-process-name'." - (process-get (or proc (get-process ess-local-process-name)) propname)) - -(defun ess-process-put (propname value &optional proc) - "Set the variable PROPNAME (symbol) to VALUE in the plist of the current ESS process. -PROC defaults to the process given by `ess-local-process-name'" - (process-put (or proc (get-process ess-local-process-name)) propname value)) - -(defun ess-start-process-specific (language dialect) - "Start an ESS process. -Typically from a language-specific buffer, using LANGUAGE (and DIALECT)." - (save-current-buffer - (let ((dsymb (intern dialect))) - (ess-write-to-dribble-buffer - (format " ..start-process-specific: lang:dialect= %s:%s, current-buf=%s\n" - language dialect (current-buffer))) - (cond ;; ((string= dialect "R") (R)) - ;; ((string= language "S") ; - ;; (message "ESS process not running, trying to start R, since language = 'S") - ;; (R)) - ;; ((string= dialect STA-dialect-name) (stata)) - ;;general case - ((fboundp dsymb) - (funcall dsymb)) - (t ;; else: ess-dialect is not a function - - ;; Typically triggered from - ;; ess-force-buffer-current("Process to load into: ") - ;; \--> ess-request-a-process("Process to load into: " no-switch) - (error "No ESS processes running; not yet implemented to start (%s,%s)" - language dialect)))))) - -(defun ess-request-a-process (message &optional noswitch ask-if-1) - "Ask for a process, and make it the current ESS process. -If there is exactly one process, only ask if ASK-IF-1 is non-nil. -Also switches to the process buffer unless NOSWITCH is non-nil. Interactively, -NOSWITCH can be set by giving a prefix argument. -Returns the name of the selected process." - (interactive - (list "Switch to which ESS process? " current-prefix-arg)) - ; prefix sets 'noswitch - (ess-write-to-dribble-buffer "ess-request-a-process: {beginning}\n") - (update-ess-process-name-list) - - (setq ess-dialect (or ess-dialect - (ess-completing-read - "Set `ess-dialect'" - (delete-dups (list "R" "S+" (or (bound-and-true-p S+-dialect-name) "S+") - "stata" (or (bound-and-true-p STA-dialect-name) "stata") - "julia" "SAS" "XLS" "ViSta"))))) - - (let* ((pname-list (delq nil ;; keep only those matching dialect - (append - (mapcar (lambda (lproc) - (and (equal ess-dialect - (buffer-local-value - 'ess-dialect - (process-buffer (get-process (car lproc))))) - (not (equal ess-local-process-name (car lproc))) - (car lproc))) - ess-process-name-list) - ;; append local only if running - (when (assoc ess-local-process-name ess-process-name-list) - (list ess-local-process-name))))) - (num-processes (length pname-list)) - (auto-started?)) - (if (or (= 0 num-processes) - (and (= 1 num-processes) - (not (equal ess-dialect ;; don't auto connect if from different dialect - (buffer-local-value - 'ess-dialect - (process-buffer (get-process - (car pname-list)))))))) - ;; try to start "the appropriate" process - (progn - (ess-write-to-dribble-buffer - (concat " ... request-a-process:\n " - (format - "major mode %s; current buff: %s; ess-language: %s, ess-dialect: %s\n" - major-mode (current-buffer) ess-language ess-dialect))) - (ess-start-process-specific ess-language ess-dialect) - (ess-write-to-dribble-buffer - (format " ... request-a-process: buf=%s\n" (current-buffer))) - (setq num-processes 1 - pname-list (car ess-process-name-list) - auto-started? t))) - ;; now num-processes >= 1 : - (let* ((proc-buffers (mapcar (lambda (lproc) - (buffer-name (process-buffer (get-process lproc)))) - pname-list)) - (proc - (if (or auto-started? - (and (not ask-if-1) (= 1 num-processes))) - (progn - (message "using process '%s'" (car proc-buffers)) - (car pname-list)) - ;; else - (unless (and ess-current-process-name - (get-process ess-current-process-name)) - (setq ess-current-process-name nil)) - (when message - (setq message (replace-regexp-in-string ": +\\'" "" message))) ;; <- why is this here?? - ;; ask for buffer name not the *real* process name: - (let ((buf (ess-completing-read message (append proc-buffers (list "*new*")) nil t nil nil))) - (if (equal buf "*new*") - (progn - (ess-start-process-specific ess-language ess-dialect) ;; switches to proc-buff - (caar ess-process-name-list)) - (process-name (get-buffer-process buf)) - )) - ))) - (if noswitch - (pop-to-buffer (current-buffer)) ;; VS: this is weird, but is necessary - (pop-to-buffer (buffer-name (process-buffer (get-process proc))))) - proc))) - -(defun ess-force-buffer-current (&optional prompt force no-autostart ask-if-1) - "Make sure the current buffer is attached to an ESS process. -If not, or FORCE (prefix argument) is non-nil, prompt for a -process name with PROMPT. If NO-AUTOSTART is nil starts the new -process if process associated with current buffer has -died. `ess-local-process-name' is set to the name of the process -selected. `ess-dialect' is set to the dialect associated with -the process selected. ASK-IF-1 asks user for the process, even if -there is only one process running. Returns the inferior buffer if -it was successfully forced, throws an error otherwise." - (interactive - (list (concat ess-dialect " process to use: ") current-prefix-arg nil)) - (let ((proc-name (ess-make-buffer-current))) - (cond ((and (not force) proc-name (get-process proc-name))) - ;; Make sure the source buffer is attached to a process - ((and ess-local-process-name (not force) no-autostart) - (error "Process %s has died" ess-local-process-name)) - ;; Request a process if `ess-local-process-name' is nil - (t - (let* ((prompt (or prompt "Process to use: ")) - (proc (ess-request-a-process prompt 'no-switch ask-if-1))) - (setq ess-local-process-name proc))))) - (process-buffer (get-process ess-local-process-name))) - -(defalias 'inferior-ess-force #'ess-force-buffer-current) - -(defun ess-switch-process () - "Force a switch to a new underlying process." - (interactive) - (ess-force-buffer-current "Process to use: " 'force nil 'ask-if-1)) - -(defun ess-get-next-available-process (&optional dialect ignore-busy) - "Return first available (aka not busy) process of dialect DIALECT. -DIALECT defaults to the local value of ess-dialect. Return nil if -no such process has been found." - (setq dialect (or dialect ess-dialect)) - (when dialect - (let (proc) - (catch 'found - (dolist (p (cons ess-local-process-name - (mapcar 'car ess-process-name-list))) - (when p - (setq proc (get-process p)) - (when (and proc - (process-live-p proc) - (equal dialect - (buffer-local-value 'ess-dialect (process-buffer proc))) - (or ignore-busy - (inferior-ess-available-p proc))) - (throw 'found proc)))))))) - - -;;*;;; Commands for switching to the process buffer - -(defun ess-switch-to-ESS (eob-p) - "Switch to the current inferior ESS process buffer. -With (prefix) EOB-P non-nil, positions cursor at end of buffer." - (interactive "P") - (ess-force-buffer-current) - (pop-to-buffer (buffer-name (process-buffer (get-process ess-current-process-name))) - '(nil . ((inhibit-same-window . t)))) - (when eob-p (goto-char (point-max)))) - -(defun ess-switch-to-end-of-ESS () - "Switch to the end of the inferior ESS process buffer." - (interactive) - (ess-switch-to-ESS t)) - -(defun ess-switch-to-inferior-or-script-buffer (toggle-eob) - "Switch between script and process buffer. -This is a single-key command. Assuming that it is bound to C-c -C-z, you can navigate back and forth between iESS and script -buffer with C-c C-z C-z C-z ... If variable -`ess-switch-to-end-of-proc-buffer' is t (the default) this -function switches to the end of process buffer. If TOGGLE-EOB is -given, the value of `ess-switch-to-end-of-proc-buffer' is -toggled." - (interactive "P") - (let ((eob (if toggle-eob - (not ess-switch-to-end-of-proc-buffer) - ess-switch-to-end-of-proc-buffer))) - (if (derived-mode-p 'inferior-ess-mode) - (let ((dialect ess-dialect) - (proc-name ess-local-process-name) - (blist (buffer-list))) - (while (and (pop blist) - (with-current-buffer (car blist) - (not (or (and (ess-derived-mode-p) - (equal dialect ess-dialect) - (null ess-local-process-name)) - (and (ess-derived-mode-p) - (equal proc-name ess-local-process-name))))))) - (if blist - (pop-to-buffer (car blist)) - (message "Found no buffers for `ess-dialect' %s associated with process %s" - dialect proc-name))) - (ess-switch-to-ESS eob)) - (set-transient-map (let ((map (make-sparse-keymap)) - (key (vector last-command-event))) - (define-key map key #'ess-switch-to-inferior-or-script-buffer) map)))) - - -(defun ess-get-process-buffer (&optional name) - "Return the buffer associated with the ESS process named by NAME." - (process-buffer (ess-get-process (or name ess-local-process-name)))) - -(defun update-ess-process-name-list () - "Remove names with no process." - (let (defunct) - (dolist (conselt ess-process-name-list) - (let ((proc (get-process (car conselt)))) - (unless (and proc (eq (process-status proc) 'run)) - (push conselt defunct)))) - (dolist (pointer defunct) - (setq ess-process-name-list (delq pointer ess-process-name-list)))) - (if (eq (length ess-process-name-list) 0) - (setq ess-current-process-name nil))) - - -;;; Functions for evaluating code - -;;*;; Utils for evaluation - -(defun ess-build-eval-command (string &optional visibly output file &rest args) - "Format an evaluation command. -Wrap STRING with `ess-quote-special-chars' and dispatch on -`ess-build-eval-command--override'." - (setq string (ess-quote-special-chars string)) - (ess-build-eval-command--override string visibly output file args)) - -(cl-defgeneric ess-build-eval-command--override - (string &optional _visibly _output file &rest _args) - "Default method to build eval command." - (and ess-eval-command - (format-spec ess-eval-command - `((?s . ,string) - (?f . ,file))))) - -(cl-defgeneric ess-build-load-command (file &optional _visibly _output &rest _args) - "Format a loading command. -Dispatches on the dialect-specific `ess-build-load-command' -and `ess-load-command', in that order." - (and ess-load-command - (format ess-load-command file))) - -(defun ess-wait-for-process (&optional proc sec-prompt wait force-redisplay timeout) - "Wait for 'busy property of the process to become nil. -If SEC-PROMPT is non-nil return if secondary prompt is detected -regardless of whether primary prompt was detected or not. If WAIT -is non-nil wait for WAIT seconds for process output before the -prompt check, default 0.002s. When FORCE-REDISPLAY is non-nil -force redisplay. You better use WAIT >= 0.1 if you need -FORCE-REDISPLAY to avoid excessive redisplay. If TIMEOUT is -non-nil stop waiting for output after TIMEOUT seconds." - (setq proc (or proc (get-process ess-local-process-name))) - (setq wait (or wait 0.005)) - (setq timeout (or timeout most-positive-fixnum)) - (let ((start-time (float-time)) - (elapsed 0)) - (save-excursion - (while (and - (or (eq (process-status proc) 'run) - (progn - (when (process-buffer proc) - (display-buffer (process-buffer proc))) - (error "ESS process has died unexpectedly"))) - (< elapsed timeout) - (or (accept-process-output proc wait) - (unless (and sec-prompt (process-get proc 'sec-prompt)) - (process-get proc 'busy)))) - (when force-redisplay - (redisplay 'force)) - (setq elapsed (- (float-time) start-time)) - (when (> elapsed .3) - (setq wait .3)))))) - -(defun inferior-ess-ordinary-filter (proc string) - (inferior-ess--set-status proc string) - (ess--if-verbose-write-process-state proc string "ordinary-filter") - (inferior-ess-run-callback proc string) - (with-current-buffer (process-buffer proc) - (insert string))) - -(defvar ess-presend-filter-functions nil - "List of functions to call before sending the input string to the process. -Each function gets one argument, a string containing the text to -be send to the subprocess. It should return the string sent, -perhaps the same string that was received, or perhaps a modified -or transformed string. - -The functions on the list are called sequentially, and each one -is given the string returned by the previous one. The string -returned by the last function is the text that is actually sent -to the process. You can use `add-hook' to add functions to this -list either globally or locally. The hook is executed in current -buffer. Before execution, the local value of this hook in the -process buffer is appended to the hook from the current buffer.") - -(defvar ess--inhibit-presend-hooks nil - "If non-nil don't run presend hooks.") - -(defun ess--run-presend-hooks (process string) - ;; run ess-presend-filter-functions and comint-input-filter-functions - (if ess--inhibit-presend-hooks - string - ;;return modified string - (let* ((pbuf (process-buffer process)) - ;; also run proc buffer local hooks - (functions (unless (eq pbuf (current-buffer)) - (buffer-local-value 'ess-presend-filter-functions pbuf)))) - (setq functions (append (delq t (copy-sequence functions)) ;; even in let, delq distructs - ess-presend-filter-functions)) - (while (and functions string) - ;; cannot use run-hook-with-args here because string must be passed from one - ;; function to another - (if (eq (car functions) t) - (let ((functions - (default-value 'ess-presend-filter-functions))) - (while (and functions string) - (setq string (funcall (car functions) string)) - (setq functions (cdr functions)))) - (setq string (funcall (car functions) string))) - (setq functions (cdr functions))) - (with-current-buffer pbuf - (run-hook-with-args 'comint-input-filter-functions string)) - string))) - -(defun ess--concat-new-line-maybe (string) - "Append \\n at the end of STRING if missing." - (if (string-match "\n\\'" string (max (- (length string) 2) 0)) - string - (concat string "\n"))) - -(defvar ess--dbg-del-empty-p t - "Internal variable to control removal of empty lines during the debugging. -Let-bind it to nil before calling `ess-send-string' or -`ess-send-region' if no removal is necessary.") - -(defun inferior-ess--interrupt-subjob-maybe (proc) - "Internal. Interrupt the process if interruptable? process variable is non-nil. -Hide all the junk output in temporary buffer." - (when (process-get proc 'interruptable?) - (let ((cb (cadr (process-get proc 'callbacks))) - (buf (get-buffer-create " *ess-temp-buff*")) - (old-filter (process-filter proc)) - (old-buff (process-buffer proc))) - (unwind-protect - (progn - (ess-if-verbose-write "interrupting subjob ... start") - (process-put proc 'interruptable? nil) - (process-put proc 'callbacks nil) - (process-put proc 'running-async? nil) - ;; this is to avoid putting junk in user's buffer on process - ;; interruption - (set-process-buffer proc buf) - (set-process-filter proc 'inferior-ess-ordinary-filter) - (interrupt-process proc) - (when cb - (ess-if-verbose-write "executing interruption callback ... ") - (funcall cb proc)) - ;; should be very fast as it inputs only the prompt - (ess-wait-for-process proc) - (ess-if-verbose-write "interrupting subjob ... finished") - ) - (set-process-buffer proc old-buff) - (set-process-filter proc old-filter))))) - - -;;*;; Evaluation primitives - -(defun ess-send-string (process string &optional visibly message _type) - "ESS wrapper for `process-send-string'. -Run `comint-input-filter-functions' and current buffer's and -PROCESS' `ess-presend-filter-functions' hooks on the input -STRING. VISIBLY can be nil, t, 'nowait or a string. If string -the behavior is as with 'nowait with the differences that -inserted string is VISIBLY instead of STRING (evaluated command -is still STRING). In all other cases the behavior is as -described in `ess-eval-visibly'. STRING need not end with -\\n. TYPE is a symbol indicating type of the string. -MESSAGE is a message to display." - ;; No support of `visibly' when there's no secondary prompt - (let ((visibly (if (and (eq visibly t) - (null inferior-ess-secondary-prompt)) - 'nowait - visibly)) - (string (ess--run-presend-hooks process string))) - (inferior-ess--interrupt-subjob-maybe process) - (inferior-ess-mark-as-busy process) - (process-put process 'last-eval (current-time)) - (cond - ;; Wait after each line - ((eq visibly t) - (let ((ess--inhibit-presend-hooks t)) - (ess-eval-linewise string))) - ;; Insert command and eval invisibly - ((or (stringp visibly) - (eq visibly 'nowait)) - (with-current-buffer (process-buffer process) - (save-excursion - (goto-char (process-mark process)) - (insert-before-markers - (propertize (format "%s\n" - (replace-regexp-in-string - "\n" "\n+ " - (if (stringp visibly) visibly string))) - 'font-lock-face 'comint-highlight-input))) - (process-send-string process (ess--concat-new-line-maybe string)))) - (t - (process-send-string process (ess--concat-new-line-maybe string)))) - (when message - (message "%s" message)))) - -(defun ess-send-region (process start end &optional visibly message type) - "Low level ESS version of `process-send-region'. -If VISIBLY call `ess-eval-linewise', else call -`ess-send-string'. If MESSAGE is supplied, display it at the -end. Run current buffer's and PROCESS' -`ess-presend-filter-functions' hooks. TYPE is a symbol indicating -type of the region." - (cond - ((ess-tracebug-p) - (ess-tracebug-send-region process start end visibly message type)) - (t (ess-send-region--override process start end visibly message type)))) - -(cl-defgeneric ess-send-region--override (process start end visibly message type) - (ess-send-string process (buffer-substring start end) visibly message type)) - - -;;*;; Evaluation commands - -(defun ess-load-file--normalise-file (file) - "Handle Tramp and system peculiarities." - (require 'tramp) - (let* ((file (if (tramp-tramp-file-p file) - (tramp-file-name-localname (tramp-dissect-file-name file)) - file)) - (file (if ess-microsoft-p - (ess-replace-in-string file "[\\]" "/") - file))) - (abbreviate-file-name file))) - -(defun ess-load-file--normalise-buffer (file) - (when (ess-save-file file) - (error "Buffer %s has not been saved" (buffer-name file))) - (let ((source-buffer (get-file-buffer file))) - (if source-buffer - (with-current-buffer source-buffer - (when (buffer-modified-p) (save-buffer)) - (ess-force-buffer-current "Process to load into: ") - (ess-check-modifications)) - (ess-force-buffer-current "Process to load into: ")))) - -;;;###autoload -(defun ess-load-file (&optional filename) - "Load FILENAME into an inferior ESS process. -This handles Tramp when working on a remote." - (interactive (list (or (and (ess-derived-mode-p) - (buffer-file-name)) - (expand-file-name - (read-file-name "Load source file: " nil nil t))))) - (ess-load-file--normalise-buffer filename) - (setq filename (ess-load-file--normalise-file filename)) - (ess-load-file--override filename) - (message "Loaded %s" filename)) - -(cl-defgeneric ess-load-file--override (filename) - (let ((command (ess-build-load-command filename nil t))) - (ess-send-string (ess-get-process) command t))) - -;; ;;; VS[03-09-2012]: Test Cases: -;; (ess-command "a<-0\n" nil nil nil nil (get-process "R")) -;; (ess-async-command-delayed "Sys.sleep(5);a<-a+1;cat(1:10)\n" nil -;; (get-process "R") (lambda (proc) (message "done"))) -;; (ess-async-command-delayed "Sys.sleep(5)\n" nil (get-process "R") -;; (lambda (proc) (message "done"))) -;; (process-get (get-process "R") 'running-async?) - -(defun ess-command--get-proc (proc no-prompt-check) - (if proc - (unless ess-local-process-name - (setq ess-local-process-name (process-name proc))) - (setq proc (ess-get-process ess-local-process-name))) - (unless no-prompt-check - (when (process-get proc 'busy) - (user-error "ESS process not ready. Finish your command before trying again"))) - proc) - -(defun ess-command (cmd &optional out-buffer _sleep no-prompt-check wait proc force-redisplay) - "Send the ESS process CMD and delete the output from the ESS process buffer. -If an optional second argument OUT-BUFFER exists save the output -in that buffer. OUT-BUFFER is erased before use. CMD should have -a terminating newline. Guarantees that the value of `.Last.value' -will be preserved. - -SLEEP is deprecated and no longer has any effect. WAIT and -FORCE-REDISPLAY are as in `ess-wait-for-process' and are passed -to `ess-wait-for-process'. - -PROC should be a process, if nil the process name is taken from -`ess-local-process-name'. This command doesn't set 'last-eval -process variable. - -Note: for critical, or error prone code you should consider -wrapping the code into: - - local({ - olderr <- options(error=NULL) - on.exit(options(olderr)) - ... - })" - (let ((out-buffer (or out-buffer (get-buffer-create " *ess-command-output*"))) - (proc (ess-command--get-proc proc no-prompt-check)) - ;; Set `inhibit-quit' to t to avoid dumping R output to the - ;; process buffer if `ess-command' gets interrupted for some - ;; reason. See bugs #794 and #842 - (inhibit-quit t)) - (with-current-buffer (process-buffer proc) - (let ((primary-prompt inferior-ess-primary-prompt) - (oldpb (process-buffer proc)) - (oldpf (process-filter proc)) - (oldpm (marker-position (process-mark proc)))) - (ess-if-verbose-write (format "(ess-command %s ..)" cmd)) - ;; Swap the process buffer with the output buffer before - ;; sending the command - (unwind-protect - (progn - (set-process-buffer proc out-buffer) - (set-process-filter proc 'inferior-ess-ordinary-filter) - (with-current-buffer out-buffer - (setq inferior-ess-primary-prompt primary-prompt) - (setq buffer-read-only nil) - (erase-buffer) - (set-marker (process-mark proc) (point-min)) - (inferior-ess-mark-as-busy proc) - (process-send-string proc cmd) - ;; Need time for ess-create-object-name-db on PC - (if no-prompt-check - (sleep-for 0.02) ; 0.1 is noticeable! - (ess-wait-for-process proc nil wait force-redisplay) - ;; Should (almost) never be incomplete unless the message - ;; contains "> " and was accidentally split by the process - ;; right there. - (while (eq :incomplete (ess-mpi-handle-messages (current-buffer))) - (ess-wait-for-process proc nil wait force-redisplay)) - ;; Remove prompt - ;; If output is cat(..)ed this deletes the output - (goto-char (point-max)) - (delete-region (point-at-bol) (point-max))) - (ess-if-verbose-write " .. ok{ess-command}"))) - (ess-if-verbose-write " .. exiting{ess-command}\n") - ;; Restore the process buffer in its previous state - (set-process-buffer proc oldpb) - (set-process-filter proc oldpf) - (set-marker (process-mark proc) oldpm)))) - out-buffer)) - -(defun ess-boolean-command (com &optional buf wait) - "Like `ess-command' but expects COM to print TRUE or FALSE. -If TRUE (or true) is found return non-nil otherwise nil. -Example (ess-boolean-command \"2>1\n\")" - (with-current-buffer (ess-command com buf nil nil wait) - (goto-char (point-min)) - (let ((case-fold-search t)) - (re-search-forward "true" nil t)))) - -(defun ess-string-command (com &optional buf wait) - "Returns the output of COM as a string." - (let ((prompt inferior-ess-prompt)) - (with-current-buffer (ess-command com buf nil nil wait) - (goto-char (point-min)) - ;; remove leading prompt - (when (and prompt (re-search-forward (concat "^" prompt) (point-at-eol) t)) - (delete-region (point-min) (match-end 0))) - (ess-kill-last-line) - (buffer-substring (point-min) (point-max))))) - -(defun ess-async-command (com &optional buf proc callback interrupt-callback) - "Asynchronous version of `ess-command'. -COM, BUF, WAIT and PROC are as in `ess-command'. - -CALLBACK is a function of two arguments (PROC STRING) to run -after the successful execution. When INTERRUPT-CALLBACK is -non-nil, user evaluation can interrupt the -job. INTERRUPT-CALLBACK should be either t or a function of one -argument (PROC) to be called on interruption. - -NOTE: Currently this function should be used only for background -jobs like caching. ESS tries to suppress any output from the -asynchronous command, but long output of COM will most likely end -up in user's main buffer." - (setq proc (or proc (get-process ess-local-process-name))) - (cond ((not (and proc (eq (process-status proc) 'run))) - (error "Process %s is dead" proc)) - ((process-get proc 'busy) - (error "Process %s is busy" proc)) - ((process-get proc 'running-async?) - (error "Process %s is already running an async command" proc))) - (when (eq interrupt-callback t) - (setq interrupt-callback (lambda (_proc)))) - (process-put proc 'callbacks (list (cons callback 'suppress-output) - interrupt-callback)) - (process-put proc 'interruptable? (and interrupt-callback t)) - (process-put proc 'running-async? t) - (ess-command com buf nil 'no-prompt-check .01 proc)) - -(defun ess-async-command-delayed (com buf proc &optional callback delay) - "Delayed asynchronous ess-command. -COM and BUF are as in `ess-command'. DELAY is a number of idle -seconds to wait before starting the execution of the COM. On -interruption (by user's evaluation) ESS tries to rerun the job -after next DELAY seconds, and the whole process repeats itself -until the command manages to run completely. DELAY defaults to -`ess-idle-timer-interval' + 3 seconds. You should always provide -PROC for delayed evaluation, as the current process might change, -leading to unpredictable consequences. This function is a wrapper -of `ess-async-command' with an explicit interrupt-callback." - (let* ((delay (or delay - (+ ess-idle-timer-interval 3))) - (int-cb `(lambda (proc) - (ess-async-command-delayed ,com ,buf proc ,callback ,delay))) - (com-fun `(lambda () - (when (eq (process-status ,proc) 'run) ; do nothing if not running - (if (or (process-get ,proc 'busy) ; if busy, try later - (process-get ,proc 'running-async?)) - ;; idle timer doesn't work here - (run-with-timer ,delay nil 'ess-async-command-delayed - ,com ,buf ,proc ,callback ,delay)) - (ess-async-command ,com ,buf ,proc ,callback ',int-cb))))) - (run-with-idle-timer delay nil com-fun))) - -(defun ess-load-library () - "Prompt and load dialect specific library/package/module. -Note that in R these are called 'packages' and the name of this -function has nothing to do with R package mechanism, but it -rather serves a generic, dialect independent purpose. It is also -similar to `load-library' Emacs function." - (interactive) - (let ((ess-eval-visibly-p t) - (packs (ess-installed-packages)) - pack) - (setq pack (ess-completing-read "Load" packs)) - (ess-load-library--override pack) - (ess--mark-search-list-as-changed))) - -(cl-defgeneric ess-installed-packages () - "Return a list of installed packages.") - -(cl-defgeneric ess-load-library--override (pack) - "Load library/package PACK.") - - -;;*;; Evaluating lines, paragraphs, regions, and buffers. - -(defun ess-eval-linewise - (text &optional invisibly eob even-empty wait-last-prompt sleep-sec wait-sec) - "Evaluate TEXT in the ESS process buffer as if typed in w/o tabs. -Waits for prompt after each line of input, so won't break on large texts. - -If optional second arg INVISIBLY is non-nil, don't echo commands. -If it is a string, just include that string. If optional third -arg EOB is non-nil go to end of ESS process buffer after -evaluation. If optional 4th arg EVEN-EMPTY is non-nil, also send -empty text (e.g. an empty line). If 5th arg WAIT-LAST-PROMPT is -non-nil, also wait for the prompt after the last line; if 6th arg -SLEEP-SEC is a number, ESS will call '(\\[sleep-for] SLEEP-SEC) -at the end of this function. If the 7th arg WAIT-SEC is set, it -will be used instead of the default .001s and be passed to -\\[ess-wait-for-process]. - -Run `comint-input-filter-functions' and -`ess-presend-filter-functions' of the associated PROCESS on the -TEXT." - (unless (numberp wait-sec) - (setq wait-sec 0.001)) - (ess-force-buffer-current "Process to use: ") - ;; Use this to evaluate some code, but don't wait for output. - (let* ((deactivate-mark) ; keep local {do *not* deactivate wrongly} - (sprocess (ess-get-process ess-current-process-name)) - (sbuffer (process-buffer sprocess)) - (win (get-buffer-window sbuffer t))) - (setq text (ess--concat-new-line-maybe - (ess--run-presend-hooks sprocess text))) - (with-current-buffer sbuffer - (setq text (propertize text 'field 'input 'front-sticky t)) - (goto-char (marker-position (process-mark sprocess))) - (if (stringp invisibly) - (insert-before-markers (concat "*** " invisibly " ***\n"))) - ;; dbg: - ;; dbg (ess-write-to-dribble-buffer - ;; dbg (format "(eval-visibly 2): text[%d]= '%s'\n" (length text) text)) - (while (or (> (length text) 0) even-empty) - (setq even-empty nil) - (let* ((pos (string-match "\n\\|$" text)) - (input (if (= (length text) 0) - "\n" - (concat (substring text 0 pos) "\n")))) - (setq text (substring text (min (length text) (1+ pos)))) - (goto-char (marker-position (process-mark sprocess))) - (if win (set-window-point win (process-mark sprocess))) - (unless invisibly - ;; for consistency with comint :( - (insert (propertize input 'font-lock-face 'comint-highlight-input)) - (set-marker (process-mark sprocess) (point))) - (inferior-ess-mark-as-busy sprocess) - (process-send-string sprocess input)) - (when (or (> (length text) 0) - wait-last-prompt) - (ess-wait-for-process sprocess t wait-sec))) - (if eob (with-temp-buffer (buffer-name sbuffer))) - (goto-char (marker-position (process-mark sprocess))) - (when win - (with-selected-window win - (goto-char (point)) - ;; this is crucial to avoid resetting window-point - (recenter (- -1 scroll-margin)))))) - (if (numberp sleep-sec) - (sleep-for sleep-sec))) - - -;;;*;;; Evaluate only - -(defun ess-eval-region--normalise-region (start end) - "Clean the region from START to END for evaluation. -This trims newlines at beginning and end of the region because -they might throw off the debugger." - (save-excursion - (goto-char start) - (skip-chars-forward "\n\t ") - (setq start (point)) - (unless mark-active - (ess-blink-region start end)) - (goto-char end) - (skip-chars-backward "\n\t ") - (setq end (point)))) - -(defun ess-eval-region (start end vis &optional message type) - "Send the region from START to END to the inferior ESS process. -VIS switches the meaning of `ess-eval-visibly'. If given, -MESSAGE is `message'ed. TYPE is a symbol indicating what type of -region this is. If command `rectangle-mark-mode' is active, send -the lines of the rectangle separately to the inferior process." - (interactive "r\nP") - (ess-force-buffer-current "Process to use: ") - (message "Starting evaluation...") - (unless ess-local-customize-alist - ;; External applications might call ess-eval-* functions; make it - ;; easier for them - (ess-setq-vars-local (symbol-value (ess-get-process-variable 'ess-local-customize-alist)))) - (if (bound-and-true-p rectangle-mark-mode) - ;; If we're in rectangle-mark-mode, loop over each line of the - ;; rectangle. Send them separately. - (let ((reclines (extract-rectangle-bounds (min (mark) (point)) (max (mark) (point))))) - (mapc (lambda (l) - (ess--eval-region (car l) (cdr l) vis message type)) - reclines)) - (ess--eval-region start end vis message type))) - -(defun ess--eval-region (start end vis &optional message type) - "Helper function for `ess-eval-region', which see. -START, END, VIS, MESSAGE, and TYPE described there." - (ess-eval-region--normalise-region start end) - (let ((visibly (if vis (not ess-eval-visibly) ess-eval-visibly)) - (message (or message "Eval region")) - (proc (ess-get-process))) - (save-excursion - (ess-send-region proc start end visibly message type))) - (when ess-eval-deactivate-mark - (ess-deactivate-mark)) - (list start end)) - -(defun ess-eval-buffer (&optional vis) - "Send the current buffer to the inferior ESS process. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-region (point-min) (point-max) vis "Eval buffer" 'buffer)) - -(defun ess-eval-buffer-from-beg-to-here (&optional vis) - "Send region from beginning to point to the inferior ESS process. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-region (point-min) (point) vis "Eval buffer till point")) - -(defun ess-eval-buffer-from-here-to-end (&optional vis) - "Send region from point to end of buffer to the inferior ESS process. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-region (point) (point-max) vis "Eval buffer till end")) - -(defun ess-eval-function (&optional vis) - "Send the current function to the inferior ESS process. -Prefix arg VIS toggles visibility of ess-code as for -`ess-eval-region'. Returns nil if not inside a function." - (interactive "P") - (ess-force-buffer-current) - (save-excursion - (ignore-errors - ;; Evaluation is forward oriented - (forward-line -1) - (ess-next-code-line 1)) - (let ((pos (point)) - beg end msg) - (end-of-defun) - (beginning-of-defun) - ;; While we are the beginning of the function, get the function - ;; name. FIXME: should use our ess-function-pattern. - (setq msg (format "Eval function: %s" - (if (looking-at add-log-current-defun-header-regexp) - (match-string 1) - (buffer-substring (point) (point-at-eol))))) - (setq beg (point)) - (end-of-defun) - (setq end (point)) - (when (or (< pos beg) - (< end pos)) - (error "Not in a function")) - (if (ess-tracebug-p) - (ess-tracebug-send-function (get-process ess-local-process-name) beg end vis msg) - (ess-eval-region beg end vis msg))))) - -(defun ess-eval-paragraph (&optional vis) - "Send the current paragraph to the inferior ESS process. -Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'." - (interactive "P") - (let ((start-pos (point))) - (if (= (point-at-bol) (point-min)) - (ess-next-code-line 0) - ;; Evaluation is forward oriented - (forward-line -1) - (ess-next-code-line 1)) - (when (< (point) start-pos) - (goto-char start-pos)) - (save-excursion - (let ((beg (progn (backward-paragraph) (point))) - (end (progn (forward-paragraph) (point)))) - (ess-eval-region beg end vis))))) - -(defun ess-eval-function-or-paragraph (&optional vis) - "Send the current function if \\[point] is inside one. -Otherwise send the current paragraph to the inferior ESS process. -Prefix arg VIS toggles visibility of ess-code as for -`ess-eval-region'. Returns 'function if a function was evaluated -or 'paragraph if a paragraph." - (interactive "P") - (condition-case nil - (progn (ess-eval-function vis) - 'function) - ;; TODO: Maybe be smarter than just catching all errors? - (error (ess-eval-paragraph vis) - 'paragraph))) - -(defun ess-eval-function-or-paragraph-and-step (&optional vis) - "Send the current function if \\[point] is inside one. -Otherwise send the current paragraph to the inferior ESS process. -Prefix arg VIS toggles visibility of ess-code as for -`ess-eval-region'." - (interactive "P") - (ess-skip-thing (ess-eval-function-or-paragraph vis)) - (ess-next-code-line)) - -(defun ess-eval-region-or-function-or-paragraph (&optional vis) - "Send the region, function, or paragraph depending on context. -Send the region if it is active. If not, send function if `point' -is inside one, otherwise the current paragraph. Treats -rectangular regions as `ess-eval-region' does. Prefix arg VIS -toggles visibility of ess-code as for `ess-eval-region'." - (interactive "P") - (if (use-region-p) - (ess-eval-region (region-beginning) (region-end) vis) - (ess-eval-function-or-paragraph vis))) - -(defun ess-eval-region-or-function-or-paragraph-and-step (&optional vis) - "Send the region, function, or paragraph depending on context. -Send the region if it is active. If not, send function if `point' -is inside one, otherwise the current paragraph. Treats -rectangular regions as `ess-eval-region' does. After evaluation -step to the next code line or to the end of region if region was -active. Prefix arg VIS toggles visibility of ess-code as for -`ess-eval-region'." - (interactive "P") - (ess-skip-thing (ess-eval-region-or-function-or-paragraph vis)) - (ess-next-code-line)) - -(defun ess-eval-region-or-line-and-step (&optional vis) - "Evaluate region if active, otherwise `ess-eval-line-and-step'. -See `ess-eval-region' for the meaning of VIS. Treats rectangular -regions as `ess-eval-region' does." - (interactive "P") - (if (use-region-p) - (ess-eval-region (region-beginning) (region-end) vis) - (ess-eval-line-and-step))) - -(defun ess-eval-region-or-line-visibly-and-step () - "Evaluate region if active, otherwise the current line and step. -Evaluation is done visibly. - -Note that when inside a package and namespaced evaluation is in -place (see `ess-r-set-evaluation-env') evaluation of multiline -input will fail." - (interactive) - (ess-force-buffer-current) - (display-buffer (ess-get-process-buffer) - ;; Use a different window for the process buffer: - '(nil (inhibit-same-window . t)) - ;; Pass t to reusable-frames if users have help in - ;; own frames, otherwise help frames get split to - ;; display the inferior. - (or (equal ess-help-own-frame 'one) - ess-help-own-frame)) - (let ((ess-eval-visibly t)) - (ess-eval-region-or-line-and-step))) - -(defun ess-eval-line (&optional vis) - "Send the current line to the inferior ESS process. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (let* ((beg (point-at-bol)) - (end (point-at-eol)) - (msg (format "Loading line: %s" (buffer-substring beg end)))) - (ess-eval-region beg end vis msg))) - -(defun ess-eval-line-and-step (&optional vis) - "Evaluate the current line and step to the \"next\" line. -See `ess-eval-region' for VIS." - (interactive "P") - (ess-eval-line vis) - (ess-skip-thing 'line) - (ess-next-code-line)) - -(defun ess-eval-line-visibly-and-step (&optional simple-next) - "Evaluate the current line visibly and step to the \"next\" line. -If SIMPLE-NEXT is non-nil, possibly via prefix arg, first skip -empty and commented lines. When the variable `ess-eval-empty' -is non-nil both SIMPLE-NEXT and EVEN-EMPTY are interpreted as -true. - -Note that when inside a package and namespaced evaluation is in -place (see `ess-r-set-evaluation-env'), the evaluation of -multiline input will fail." - (interactive "P") - (ess-force-buffer-current) - (display-buffer (ess-get-process-buffer) - ;; Use a different window for the process buffer: - '(nil (inhibit-same-window . t)) - ;; Pass t to reusable-frames if users have help in - ;; own frames, otherwise help frames get split to - ;; display the inferior. - (or (equal ess-help-own-frame 'one) - ess-help-own-frame)) - (let ((ess-eval-visibly t) - (ess-eval-empty (or ess-eval-empty simple-next))) - (ess-eval-line) - (ess-skip-thing 'line) - (ess-next-code-line))) - -(defun ess-eval-line-invisibly-and-step () - "Evaluate the current line invisibly and step to the next line. -Evaluate all comments and empty lines." - (interactive) - (let ((ess-eval-visibly nil)) - (ess-eval-line-and-step))) -(define-obsolete-function-alias 'ess-eval-line-and-step-invisibly 'ess-eval-line-invisibly-and-step "18.10") - - -;;;*;;; Evaluate and switch to S - -(defun ess-eval-region-and-go (start end &optional vis) - "Send region from START to END to the inferior process buffer. -START and END default to the current region, and rectangular -regions are treated as `ess-eval-region'. VIS has same meaning as -for `ess-eval-region'." - (interactive "r\nP") - (ess-eval-region start end vis) - (ess-switch-to-ESS t)) - -(defun ess-eval-buffer-and-go (&optional vis) - "Send the current buffer to the inferior S and switch to the process buffer. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-buffer vis) - (ess-switch-to-ESS t)) - -(defun ess-eval-function-and-go (&optional vis) - "Send the current function, then switch to the inferior process buffer. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-function vis) - (ess-switch-to-ESS t)) - -(defun ess-eval-line-and-go (&optional vis) - "Send the current line, then switch to the inferior process buffer. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-line vis) - (ess-switch-to-ESS t)) - -(defun ess-eval-paragraph-and-go (&optional vis) - "Send the current paragraph, then switch to the inferior process buffer. -VIS has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-paragraph vis) - (ess-switch-to-ESS t)) - -(defun ess-eval-paragraph-and-step (&optional vis) - "Evaluate the current paragraph and move point to the next line. -If not inside a paragraph, evaluate the next one. VIS has same -meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-paragraph vis) - (ess-skip-thing 'paragraph) - (ess-next-code-line)) - - ; Inferior ESS mode -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;; In this section: -;;;; -;;;; * The major mode inferior-ess-mode -;;;; * Process handling code -;;;; * Completion code -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;*;; Major mode definition - -(defvar inferior-ess-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-y" #'ess-yank) - (define-key map "\r" #'inferior-ess-send-input) - (define-key map "\C-a" #'comint-bol) - ;; 2010-06-03 SJE - ;; disabled this in favor of ess-dirs. Martin was not sure why this - ;; key was defined anyway in this mode. - ;;(define-key map "\M-\r" #'ess-transcript-send-command-and-move) - (define-key map "\C-c\M-l" #'ess-load-file) - (define-key map "\C-c`" #'ess-show-traceback) - (define-key map [(control ?c) ?~] #'ess-show-call-stack) - (define-key map "\C-c\C-d" #'ess-dump-object-into-edit-buffer) - (define-key map "\C-c\C-v" #'ess-display-help-on-object) - (define-key map "\C-c\C-q" #'ess-quit) - (define-key map "\C-c\C-s" #'ess-execute-search) - (define-key map "\C-c\C-x" #'ess-execute-objects) - (define-key map "\C-c\034" #'ess-abort) ; \C-c\C-backslash - (define-key map "\C-c\C-z" #'ess-switch-to-inferior-or-script-buffer) ; mask comint map - (define-key map "\C-d" #'delete-char) ; EOF no good in S - (define-key map "\t" #'completion-at-point) - (define-key map "\M-?" #'ess-complete-object-name) - (define-key map "\C-c\C-k" #'ess-request-a-process) - (define-key map "," #'ess-smart-comma) - (define-key map "\C-c\C-d" 'ess-doc-map) - (define-key map "\C-c\C-e" 'ess-extra-map) - (define-key map "\C-c\C-t" 'ess-dev-map) - map) - "Keymap for `inferior-ess' mode.") - -(easy-menu-define - inferior-ess-mode-menu inferior-ess-mode-map - "Menu for use in Inferior S mode" - '("iESS" - ["Quit" ess-quit t] - ["Reload process" inferior-ess-reload t] - ;; ["Send and move" ess-transcript-send-command-and-move t] - ["Copy command" comint-copy-old-input t] - ["Send command" inferior-ess-send-input t] - ["Switch to script buffer" ess-switch-to-inferior-or-script-buffer t] - ["Get help on S object" ess-display-help-on-object t] - "------" - ("Process" - ["Process Echoes" (lambda () (interactive) - (setq comint-process-echoes (not comint-process-echoes))) - :active t - :style toggle - :selected comint-process-echoes] - ("Eval visibly " - :filter ess--generate-eval-visibly-submenu )) - "------" - ("Utils" - ["Attach directory" ess-execute-attach t] - ["Display object list" ess-execute-objects t] - ["Display search list" ess-execute-search t] - ["Edit S object" ess-dump-object-into-edit-buffer t] - ["Enter S command" ess-execute t] - ["Jump to error" ess-parse-errors t] - ["Load source file" ess-load-file t] - ["Resynch S completions" ess-resynch t] - ["Recreate R versions known to ESS" - (lambda () (interactive) (ess-r-redefine-runners 'verbose)) t] - ) - "------" - ("start-dev" :visible nil); <-- ?? - ("end-dev" :visible nil) - "------" - ("Font Lock" - :active ess-font-lock-keywords - :filter ess--generate-font-lock-submenu) - "------" - ["Describe" describe-mode t] - ["Send bug report" ess-submit-bug-report t] - ["About" (ess-goto-info "Entering Commands") t] - )) - - -(defvar ess-mode-minibuffer-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-map) - (define-key map "\t" #'ess-complete-object-name) - (define-key map "\C-\M-i" #'ess-complete-object-name) ;; doesn't work:( - (define-key map "\C-c\C-s" #'ess-execute-search) - (define-key map "\C-c\C-x" #'ess-execute-objects) - map) - "Keymap used in `ess-execute'.") - -(define-derived-mode inferior-ess-mode comint-mode "iESS" - "Major mode for interacting with an inferior ESS process. -To learn more about how to use inferior ess modes, see Info -node `(ess)Top'. If you accidentally suspend your process, use -\\[comint-continue-subjob] to continue it." - :group 'ess-proc - (setq-local comint-input-sender 'inferior-ess-input-sender) - (setq-local font-lock-fontify-region-function - #'inferior-ess-fontify-region) - ;; If comint-process-echoes is t inferior-ess-input-sender - ;; recopies the input, otherwise not - (setq-local comint-process-echoes (not (member ess-language '("SAS" "XLS" "OMG" "julia")))) - - (when comint-use-prompt-regexp ;; why comint is not setting this? bug? - (setq-local inhibit-field-text-motion t)) - - (unless inferior-ess-prompt ;; build when unset - (setq inferior-ess-prompt - (concat "\\(" - inferior-ess-primary-prompt - (when inferior-ess-secondary-prompt "\\|") - inferior-ess-secondary-prompt - "\\)"))) - (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) - - (setq mode-line-process - '(" [" - ess--mode-line-process-indicator - ess--local-mode-line-process-indicator - "]: %s")) - - ;;; Completion support ---------------- - (remove-hook 'completion-at-point-functions 'comint-completion-at-point t) ;; reset the hook - (add-hook 'completion-at-point-functions 'comint-c-a-p-replace-by-expanded-history nil 'local) - (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) - - ;; hyperlinks support - (goto-address-mode t) - - ;; Avoid spaces after filenames - (setq-local comint-completion-addsuffix (cons "/" "")) - - (setq comint-input-autoexpand t) ; Only for completion, not on input. - - (add-hook 'window-configuration-change-hook #'ess-set-width nil t) - (setq-local indent-tabs-mode nil) - - (setq-local paragraph-start (concat inferior-ess-primary-prompt "\\|\^L")) - (setq-local paragraph-separate "\^L") - (setq-local jit-lock-chunk-size inferior-ess-jit-lock-chunk-size)) - - - -;;*;; Commands used exclusively in inferior-ess-mode - -;;;*;;; Main user commands - -(defun inferior-ess-input-sender (proc string) - (inferior-ess--interrupt-subjob-maybe proc) - (let ((comint-input-filter-functions nil)) ; comint runs them, don't run twice. - (if comint-process-echoes - (ess-eval-linewise string nil nil ess-eval-empty) - (ess-send-string proc string)))) - -(defvar ess-help-arg-regexp "\\(['\"]?\\)\\([^,=)'\"]*\\)\\1" - "Reg(ular) Ex(pression) of help(.) arguments. MUST: 2nd \\(.\\) = arg.") - -(defun inferior-ess-send-input () - "Sends the command on the current line to the ESS process." - (interactive) - (run-hooks 'ess-send-input-hook) - (unless (ess-process-get 'busy) - ;; avoid new line insertion - (ess-process-put 'prev-prompt nil)) - (comint-send-input) - (setq ess-object-list nil)) - -(defun inferior-ess--goto-input-start:field () - "Move point to the beginning of input skipping all continuation lines. -If in the output field, goes to the beginning of previous input -field. -Note: `inferior-ess-secondary-prompt' should match exactly." - (goto-char (field-beginning)) - ;; move to the beginning of non-output field - (while (and (not (bobp)) - (eq (field-at-pos (point)) 'output)) - (goto-char (field-beginning nil t))) - ;; skip all secondary prompts - (let ((pos (field-beginning (point) t)) - (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) - (while (and pos - (if (eq (get-text-property pos 'field) 'output) - (string-match secondary-prompt (field-string-no-properties pos)) - t)) - (goto-char pos) - (setq pos (previous-single-property-change pos 'field))))) - -(defun inferior-ess--goto-input-end:field () - "Move point to the end of input skipping all continuation lines. -If in the output field, goes to the beginning of previous input -field. NOTE: to be used only with fields, see -`comint-use-prompt-regexp'." - ;; this func is not used but might be useful some day - (goto-char (field-end)) - (let ((pos (point)) - (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) - (while (and pos - (if (eq (get-text-property pos 'field) 'output) - (string-match secondary-prompt (field-string-no-properties pos)) - t)) - (goto-char pos) - (setq pos (next-single-property-change pos 'field))))) - -(defun inferior-ess--get-old-input:field () - "Return the ESS command surrounding point (use with fields)." - (save-excursion - (if (eq (field-at-pos (point)) 'output) - (if (called-interactively-p 'any) - (error "No command on this line") - ;; else, just return "" - "") - (inferior-ess--goto-input-start:field) - (let ((command (field-string-no-properties (point))) - (pos (next-single-property-change (point) 'field )) - (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) - (while (and pos - (cond - ((eq (get-text-property pos 'field) 'input) - (setq command (concat command "\n" (field-string-no-properties pos)))) - ((eq (get-text-property pos 'field) 'output) - (string-match secondary-prompt (field-string-no-properties pos))) - (t)));; just skip if unknown - (setq pos (next-single-property-change pos 'field))) - command)))) - -;; TODO: error when entering a multiline function -;; check.integer <- function(N){ -;; is.integer(N) | !length(grep("[^[:digit:]]", as.character(N))) -;; } -(defun inferior-ess--goto-input-start:regexp () - "Move point to the beginning of input skipping all continuation lines. -If in the output field, goes to the beginning of previous input." - (beginning-of-line) - (unless (looking-at inferior-ess-prompt) - (re-search-backward (concat "^" inferior-ess-prompt) nil t)) - ;; at bol - (when (and inferior-ess-secondary-prompt - (looking-at inferior-ess-secondary-prompt)) - (while (and (> (forward-line -1) -1) - (looking-at inferior-ess-secondary-prompt)))) - (unless (looking-at inferior-ess-prompt) - (error "Beginning of input not found")) - (comint-skip-prompt)) - -(defun inferior-ess--get-old-input:regexp () - "Return the ESS command surrounding point (use regexp)." - ;;VS[03-09-2012]: This should not rise errors!! Troubles comint-interrupt-subjob - (save-excursion - (let* ((inhibit-field-text-motion t) - command) - (beginning-of-line) - (when (and inferior-ess-secondary-prompt - (looking-at inferior-ess-secondary-prompt)) - (inferior-ess--goto-input-start:regexp)) - (beginning-of-line) - (if (looking-at inferior-ess-prompt) ; cust.var, might not include sec-prompt - (progn - (comint-skip-prompt) - (setq command (buffer-substring-no-properties (point) (point-at-eol))) - (when inferior-ess-secondary-prompt - (while (progn (forward-line 1) - (looking-at inferior-ess-secondary-prompt)) - (re-search-forward inferior-ess-secondary-prompt (point-at-eol) t) - (setq command (concat command "\n" - (buffer-substring-no-properties (point) (point-at-eol)))))) - (forward-line -1) - command) - (message "No command at this point") - "")))) - -(defun inferior-ess-get-old-input () - "Return the ESS command surrounding point." - (if comint-use-prompt-regexp - (inferior-ess--get-old-input:regexp) - (inferior-ess--get-old-input:field))) - - -;;;*;;; Hot key commands - -(defun ess-execute-objects (posn) - "Send the objects() command to the ESS process. -By default, gives the objects at position 1. -A prefix argument toggles the meaning of `ess-execute-in-process-buffer'. -A prefix argument of 2 or more means get objects for that position. -A negative prefix argument gets the objects for that position - and toggles `ess-execute-in-process-buffer' as well." - (interactive "P") - (ess-make-buffer-current) - (let* ((num-arg (if (listp posn) - (if posn -1 1) - (prefix-numeric-value posn))) - (the-posn (if (< num-arg 0) (- num-arg) num-arg)) - (invert (< num-arg 0)) - (the-command (format inferior-ess-objects-command the-posn ".*")) - (the-message (concat ">>> Position " - (number-to-string the-posn) - " (" - (nth (1- the-posn) (ess-search-list)) - ")\n"))) - (ess-execute the-command invert "S objects" the-message))) - -(defun ess-execute-search (invert) - "Send the `inferior-ess-search-list-command' command to the `ess-language' process. -[search(..) in S]" - (interactive "P") - (ess-execute inferior-ess-search-list-command invert "S search list")) - -;; FIXME --- this *only* works in S / S-plus; not in R -;; ----- ("at least" is not assigned to any key by default) -(defun ess-execute-attach (dir &optional posn) - "Attach a directory in the `ess-language' process with the attach() command. -When used interactively, user is prompted for DIR to attach and -prefix argument is used for POSN (or 2, if absent.) -Doesn't work for data frames." - (interactive "Attach directory: \nP") - (ess-execute (concat "attach(\"" - (directory-file-name (expand-file-name dir)) - "\"" - (if posn (concat "," (number-to-string - (prefix-numeric-value posn)))) - ")") 'buffer) - (ess-process-put 'sp-for-help-changed? t)) - -(defun ess-execute-screen-options (&optional invisibly) - "Cause S to set the \"width\" option to 1 less than the window width. -Also sets the \"length\" option to 99999. When INVISIBLY is -non-nil, don't echo to R subprocess. This is a good thing to put -in `ess-r-post-run-hook' or `ess-S+-post-run-hook'." - (interactive) - (if (null ess-execute-screen-options-command) - (message "Not implemented for '%s'" ess-dialect) - (let ((command (ess-calculate-width 'window))) - (if invisibly - (ess-command command) - (ess-eval-linewise command nil nil nil 'wait-prompt))))) - -(defun ess-calculate-width (opt) - "Calculate width command given OPT. -OPT can be 'window, 'frame, or an integer. Return a command -suitable to send to the inferior process (e.g. \"options(width=80, length=999999)\")." - (when (null ess-execute-screen-options-command) - (error "Not implemented for %s" ess-dialect)) - (let (command) - (cond ((integerp opt) - (setq command (format ess-execute-screen-options-command opt))) - ((eql 'window opt) - ;; We cannot use (window-width) here because it returns sizes - ;; in default (frame) characters which leads to incorrect - ;; sizes with scaled fonts.To solve this we approximate font - ;; width in pixels and use window-pixel-width to compute the - ;; approximate number of characters that fit into line. - (let* ((wedges (window-inside-pixel-edges)) - (wwidth (- (nth 2 wedges) (nth 0 wedges))) - (nchars (floor (/ wwidth (default-font-width))))) - (setq command (format ess-execute-screen-options-command - nchars)))) - ((eql 'frame opt) - (setq command - (format ess-execute-screen-options-command (frame-width)))) - (t (error "OPT (%s) not 'window, 'frame or an integer" opt))) - command)) - -(defun ess-set-width () - "Set the width option. -A part of `window-configuration-change-hook' in inferior ESS -buffers." - (when (and ess-auto-width - ess-execute-screen-options-command) - ;; `window-configuration-change-hook' runs with the window selected. - (let ((proc (get-buffer-process (window-buffer))) - command) - ;; TODO: Set the width once the process is no longer busy. - (when (and (process-live-p proc) - (not (process-get proc 'busy))) - (setq command (ess-calculate-width ess-auto-width)) - (if ess-auto-width-visible - (ess-eval-linewise command nil nil nil 'wait-prompt) - (ess-command command)))))) - -(defun ess-execute (command &optional invert buff message) - "Send a command to the ESS process. -A newline is automatically added to COMMAND. Prefix arg (or second arg -INVERT) means invert the meaning of -`ess-execute-in-process-buffer'. If INVERT is 'buffer, output is -forced to go to the process buffer. If the output is going to a -buffer, name it *BUFF*. This buffer is erased before use. Optional -fourth arg MESSAGE is text to print at the top of the buffer (defaults -to the command if BUFF is not given.)" - (interactive (list - ;; simpler way to set proc name in mb? - (let ((enable-recursive-minibuffers t) - (proc-name (progn (ess-force-buffer-current) - ess-local-process-name))) - (with-current-buffer (get-buffer " *Minibuf-1*") ;; FIXME: hardcoded name - (setq ess-local-process-name proc-name)) - (read-from-minibuffer "Execute> " nil - ess-mode-minibuffer-map)) - current-prefix-arg)) - (ess-make-buffer-current) - (let ((the-command (concat command "\n")) - (buff-name (concat "*" (or buff "ess-output") "*")) - (in-pbuff (if invert (or (eq invert 'buffer) - (not ess-execute-in-process-buffer)) - ess-execute-in-process-buffer))) - (if in-pbuff - (ess-eval-linewise the-command) - (ess-with-current-buffer (get-buffer-create buff-name) - (ess-command the-command (current-buffer) nil nil nil - (get-process ess-local-process-name)) - (ansi-color-apply-on-region (point-min) (point-max)) - (goto-char (point-min)) - (if message (insert message) - (insert "> " the-command)) - (display-buffer (current-buffer)))))) - - -;;;*;;; Quitting - -(cl-defgeneric ess-quit--override (_arg) - "Stops the inferior process" - (let ((proc (ess-get-process))) - (ess-cleanup) - (goto-char (marker-position (process-mark proc))) - (insert inferior-ess-exit-command) - (process-send-string proc inferior-ess-exit-command))) - -(defun ess-quit (&optional arg) - "Issue an exiting command to the inferior process. -Runs `ess-cleanup'. ARG gets passed to a language specific -method, see `ess-quit--override'." - (interactive "P") - (unless (ess-process-live-p) - (user-error "No live ESS process associated with this buffer")) - (ess-force-buffer-current "Process to quit: ") - (ess-interrupt) - (ess-make-buffer-current) - (ess-quit--override arg)) - -(defun ess-interrupt () - "Interrupt the inferior process. -This sends an interrupt and quits a debugging session." - (interactive) - (inferior-ess-force) - (let ((proc (ess-get-process))) - ;; Interrupt current task before reloading. Useful if the process is - ;; prompting for input, for instance in R in case of a crash - (interrupt-process proc comint-ptyp) - ;; Workaround for Windows terminals - (unless (memq system-type '(gnu/linux darwin)) - (process-send-string nil "\n")) - (ess-wait-for-process proc) - ;; Quit debugging session before reloading - (when (ess-debug-active-p) - (ess-debug-command-quit) - (ess-wait-for-process proc)))) - -(defun ess-abort () - "Kill the ESS process, without executing .Last or terminating devices. -If you want to finish your session, use \\[ess-quit] instead." -;;; Provided as a safety measure over the default binding of C-c C-z in -;;; comint-mode-map. - (interactive) - (ding) - (message "WARNING: \\[inferior-ess-exit-command] will not be executed and graphics devices won't finish properly!") - (sit-for 2) - (if (y-or-n-p "Still abort? ") - (comint-quit-subjob) - (message "Good move."))) - -(defun ess-cleanup () - "Cleanup buffers associated with the process. -Possibly kill or offer to kill, depending on the value of -`ess-S-quit-kill-buffers-p', all buffers associated with this ESS -process. Uses `display-buffer' to display the process buffer. It -is run automatically by \\[ess-quit]." - (interactive) - (let* ((the-procname (or (ess-make-buffer-current) ess-local-process-name)) - (buf (buffer-name (process-buffer (get-process the-procname))))) - (unless the-procname - (error "I don't know which ESS process to clean up after!")) - (when - (or (eq ess-S-quit-kill-buffers-p t) - (and - (eq ess-S-quit-kill-buffers-p 'ask) - (y-or-n-p - (format - "Delete all buffers associated with process %s? " the-procname)))) - (dolist (buf (buffer-list)) - (with-current-buffer buf - ;; Consider buffers for which ess-local-process-name is - ;; the same as the-procname - (when (and (not (get-buffer-process buf)) - ess-local-process-name - (equal ess-local-process-name the-procname)) - (kill-buffer buf))))) - (display-buffer buf) - buf)) - -(defun inferior-ess-reload (&optional start-args) - "Reload the inferior process. -START-ARGS gets passed to the dialect-specific -`inferior-ess-reload-override'." - (interactive) - (let* ((inf-buf (inferior-ess-force)) - (inf-proc (get-buffer-process inf-buf)) - (inf-start-data (buffer-local-value 'inferior-ess--local-data inf-buf)) - (start-name (car inf-start-data)) - (start-args (or start-args (cdr inf-start-data)))) - ;; Interrupt early so we can get working directory - (ess-interrupt) - (save-window-excursion - ;; Make sure we don't ask for directory again - ;; Use current working directory as default - (let ((project-find-functions nil) - (ess-directory-function nil) - (ess-startup-directory (ess-get-working-directory)) - (ess-ask-for-ess-directory nil)) - (ess-quit 'no-save) - (inferior-ess--wait-for-exit inf-proc) - (with-current-buffer inf-buf - (inferior-ess-reload--override start-name start-args)))))) - -(cl-defgeneric inferior-ess-reload--override (_start-name _start-args) - (user-error "Reloading not implemented for %s" ess-dialect)) - -(defun inferior-ess--wait-for-exit (proc) - "Wait for process exit. -This should be used instead of `ess-wait-for-process' for waiting -after issuing a quit command as the latter assumes a live process." - (let ((start-time (float-time))) - (while (eq (process-status proc) 'run) - (accept-process-output proc 0.002) - (when (> (- (float-time) start-time) 1) - (error "Timeout while quitting process"))))) - - -;;;*;;; Support functions - -(defun ess-extract-onames-from-alist (alist posn &optional force) - "Return the object names in position POSN of ALIST. -ALIST is an alist like `ess-sl-modtime-alist'. POSN should be in 1 .. (length -ALIST). If optional third arg FORCE is t, the corresponding element -of the search list is re-read. Otherwise it is only re-read if it's a -directory and has been modified since it was last read." - (let* ((entry (nth (1- posn) alist)) - (dir (car entry)) - (timestamp (car (cdr entry))) - (new-modtime (and timestamp - (ess-dir-modtime dir)))) - ;; Refresh the object listing if necessary - (if (or force (not (equal new-modtime timestamp))) - (setcdr (cdr entry) (ess-object-names dir posn))) - (cdr (cdr entry)))) - -(defun ess-dir-modtime (dir) - "Return the last modtime if DIR is a directory, and nil otherwise." - (and ess-filenames-map - (file-directory-p dir) - (nth 5 (file-attributes dir)))) - -(defun ess-object-modtime (object) - "Return the modtime of the S object OBJECT (a string). -Searches along the search list for a file named OBJECT and returns its modtime -Returns nil if that file cannot be found, i.e., for R or any non-S language!" - (let ((path (ess-search-list)) - result) - (while (and (not result) path) - (setq result (file-attributes - (concat (file-name-as-directory (car path)) - object))) - (setq path (cdr path))) - (nth 5 result))) - -(defun ess-modtime-gt (mod1 mod2) - "Return t if MOD1 is later than MOD2." - (and mod1 - (or (> (car mod1) (car mod2)) - (and (= (car mod1) (car mod2)) - (> (car (cdr mod1)) (car (cdr mod2))))))) - -(defun ess-get-object-list (name &optional exclude-first) - "Return a list of current S object names associated with process NAME, -using `ess-object-list' if that is non-nil. -If exclude-first is non-nil, don't return objects in first positon (.GlobalEnv)." - (or ess-object-list ;; <<- MM: this is now always(?) nil; we cache the *-modtime-alist - (with-current-buffer (process-buffer (ess-get-process name)) - (ess-make-buffer-current) - (ess-write-to-dribble-buffer (format "(get-object-list %s) .." name)) - (if (or (not ess-sl-modtime-alist) - (ess-process-get 'sp-for-help-changed?)) - (progn (ess-write-to-dribble-buffer "--> (ess-get-modtime-list)\n") - (ess-get-modtime-list)) - ;;else - (ess-write-to-dribble-buffer " using existing ess-sl-modtime-alist\n")) - (let* ((alist ess-sl-modtime-alist) - (i 2) - (n (length alist)) - result) - (ess-write-to-dribble-buffer (format " (length alist) : %d\n" n)) - (unless exclude-first - ;; re-read of position 1 : - (setq result (ess-extract-onames-from-alist alist 1 'force))) - (ess-write-to-dribble-buffer - (format " have re-read pos=1: -> length %d\n" (length result))) - ;; Re-read remaining directories if necessary. - (while (<= i n) - (setq result - (append result - (ess-extract-onames-from-alist alist i))) - (setq i (1+ i))) - (setq ess-object-list (delete-dups result)))))) - -(defun ess-get-words-from-vector (command &optional no-prompt-check wait proc) - "Evaluate the S command COMMAND, which returns a character vector. -Return the elements of the result of COMMAND as an alist of -strings. COMMAND should have a terminating newline. -NO-PROMPT-CHECK, WAIT, and PROC are passed to `ess-command'. -FILTER may be the keyword 'non-... or nil. To avoid truncation of -long vectors, wrap your command (%s) like this, or a version with -explicit options(max.print=1e6): \"local({ out <- try({%s}); -print(out, max=1e6) })\n\"." - (unless proc - (inferior-ess-force)) - (let* ((tbuffer (get-buffer-create - " *ess-get-words*")); initial space: disable-undo - (word-RE - (concat "\\(" - "\\\\\"" "\\|" "[^\"]" ; \" or non-"-char - "\\)*")) - (full-word-regexp - (concat "\"" "\\(" word-RE "\\)" - "\"" - "\\( \\|$\\)"; space or end - )) - words) - (ess-command command tbuffer 'sleep no-prompt-check wait proc) - (with-current-buffer tbuffer - (goto-char (point-min)) - (while (re-search-forward full-word-regexp nil t) - (setq words (cons (buffer-substring (match-beginning 1) (match-end 1)) - words)))) - (ess-if-verbose-write - (if (> (length words) 5) - (format " |-> (length words)= %d\n" (length words)) - (format " |-> words= '%s'\n" words))) - (reverse words))) - -(defun ess-compiled-dir (dir) - "Return non-nil if DIR is an S object directory with special files. -I.e. if the filenames in DIR are not representative of the objects in DIR." - (or (file-exists-p (concat (file-name-as-directory dir) "___nonfile")) - (file-exists-p (concat (file-name-as-directory dir) "__BIGIN")) - (file-exists-p (concat (file-name-as-directory dir) "___NONFI")))) - -(defun ess-object-names (obj &optional pos) - "Return alist of S object names in directory (or object) OBJ. -If OBJ is a directory name (begins with `/') returns a listing of -that dir. This may use the search list position POS if necessary. -If OBJ is an object name, returns result of the command -`inferior-ess-safe-names-command'. If POS is supplied return the -result of the command in `inferior-ess-objects-command'. If OBJ -is nil or not a directory, POS must be supplied. In all cases, -the value is an list of object names." - (cond ((and (stringp obj) - (string-match-p "ESSR" obj)) - nil) - ;; FIXME: in both cases below, the same fallback "objects(POS)" is used -- merge! - ((and obj (file-accessible-directory-p obj)) - ;; Check the pre-compiled object list in ess-object-name-db first - - ;; FIXME: If used at all, ess-object-name-db should not only - ;; ----- be used in the directory case !! - (or (cdr-safe (assoc obj ess-object-name-db)) - ;; Take a directory listing - (and ess-filenames-map - ;; first try .Data subdirectory: - ;;FIXME: move ".Data" or ``this function'' to ess-sp6-d.el etc: - (let ((dir (concat (file-name-as-directory obj) ".Data"))) - (if (not (file-accessible-directory-p dir)) - (setq dir obj)) - (and (not (ess-compiled-dir dir)) - (directory-files dir)))) - ;; Get objects(pos) instead - (and (or (ess-write-to-dribble-buffer - (format "(ess-object-names ..): directory %s not used\n" obj)) - t) - pos - (ess-get-words-from-vector - (format inferior-ess-objects-command pos))))) - ((and obj ;; want names(obj) - (ess-get-words-from-vector - (format inferior-ess-safe-names-command obj)))) - (pos - (ess-get-words-from-vector - (format inferior-ess-objects-command pos))))) - -(defun ess-slot-names (obj) - "Return alist of S4 slot names of S4 object OBJ." - (ess-get-words-from-vector (format "slotNames(%s)\n" obj))) - -(defun ess-function-arguments (funname &optional proc) - "Get FUNARGS from cache or ask the process for it. -Return FUNARGS - a list with the first element being a -cons (PACKAGE_NAME . TIME_STAMP), second element is a string -giving arguments of the function as they appear in documentation, -third element is a list of arguments of all methods. If PROC is -given, it should be an ESS process. If PACKAGE_NAME is nil, and -TIME_STAMP is less recent than the time of the last user -interaction to the process, then update the entry. PACKAGE_NAME -is also nil when FUNNAME was not found, or FUNNAME is a special -name that contains :,$ or @." - (when (and funname ;; usually returned by ess--fn-name-start (might be nil) - (or proc (ess-process-live-p))) - (let* ((proc (or proc (get-process ess-local-process-name))) - (cache (or (process-get proc 'funargs-cache) - (let ((cache (make-hash-table :test 'equal))) - (process-put proc 'funargs-cache cache) - cache))) - (args (gethash funname cache)) - (pack (caar args)) - (ts (cdar args))) - (when (and args - (and (time-less-p ts (process-get proc 'last-eval)) - (or (null pack) - (equal pack "")))) - ;; reset cache - (setq args nil)) - (or args - (cadr (assoc funname (process-get proc 'funargs-pre-cache))) - (and - (not (process-get proc 'busy)) - (with-current-buffer (ess-command (format ess-funargs-command - (ess-quote-special-chars funname)) - nil nil nil nil proc) - (goto-char (point-min)) - (when (re-search-forward "(list" nil t) - (goto-char (match-beginning 0)) - (setq args (ignore-errors (eval (read (current-buffer))))) - (when args - (setcar args (cons (car args) (current-time))))) - ;; push even if nil - (puthash (substring-no-properties funname) args cache))))))) - -;;; SJE: Wed 29 Dec 2004 --- remove this function. -;;; rmh: Wed 5 Jan 2005 --- bring it back for use on Windows -(defun ess-create-object-name-db () - "Create a database of object names in standard S directories. -This database is saved in the file specified by -`ess-object-name-db-file', and is loaded when `ess-mode' is -loaded. It defines the variable `ess-object-name-db', which is -used for completions. Before you call this function, modify the S -search list so that it contains all the non-changing (i.e. -system) S directories. All positions of the search list except -for position 1 are searched and stored in the database. After -running this command, you should move ess-namedb.el to a -directory in the `load-path'." - (interactive) - (setq ess-object-name-db nil) - (let ((search-list (cdr (ess-search-list))) - (pos 2) - name - (buffer (get-buffer-create " *ess-db*")) - (temp-object-name-db nil)) - - (ess-write-to-dribble-buffer - (format "(object db): search-list=%s \n " search-list)) - (while search-list - (message "Searching %s" (car search-list)) - (setq temp-object-name-db (cons (cons (car search-list) - (ess-object-names nil pos)) - temp-object-name-db)) - (setq search-list (cdr search-list)) - (ess-write-to-dribble-buffer - (format "(object db): temp-obj-name-db=%s \n pos=%s" - temp-object-name-db pos)) - (setq pos (1+ pos))) - (with-current-buffer buffer - (erase-buffer) - (insert "(setq ess-object-name-db '") - (prin1 temp-object-name-db (current-buffer)) - (insert ")\n") - (setq name (expand-file-name ess-object-name-db-file)) - (write-region (point-min) (point-max) name) - (message "Wrote %s" name)) - (kill-buffer buffer) - (setq ess-object-name-db temp-object-name-db))) - -(defun ess-resynch nil - "Reread all directories/objects in variable `ess-search-list' to form completions." - (interactive) - (if (ess-make-buffer-current) nil - (error "Not an ESS process buffer")) - (setq - ess-sl-modtime-alist nil - ess-object-list nil - ess-object-name-db nil ; perhaps it would be better to reload? - ) - (ess-process-put 'sp-for-help-changed? t) - ;; Action! : - (ess-get-modtime-list)) - -(defun ess-filename-completion () - "Return completion only within string or comment." - (save-restriction ;; explicitly handle inferior-ess - (ignore-errors - (when (and (derived-mode-p 'inferior-ess-mode) - (> (point) (process-mark (get-buffer-process (current-buffer))))) - (narrow-to-region (process-mark (get-buffer-process (current-buffer))) - (point-max)))) - (when (and (not (equal ?` (nth 3 (syntax-ppss (point))))) - (ess-inside-string-or-comment-p (point))) - (append (comint-filename-completion) '(:exclusive no))))) - -(defun ess-complete-filename () - "Do file completion only within strings." - (save-restriction ;; explicitly handle inferior-ess - (ignore-errors - (when (and (derived-mode-p 'inferior-ess-mode) - (> (point) (process-mark (get-buffer-process (current-buffer))))) - (narrow-to-region (process-mark (get-buffer-process (current-buffer))) - (point-max)))) - (when (or (ess-inside-string-or-comment-p (point))) ;; usable within ess-mode as well - (comint-dynamic-complete-filename)))) - -(defun ess-after-pathname-p nil - ;; Heuristic: after partial pathname if it looks like we're in a - ;; string, and that string looks like a pathname. Not the best for - ;; use with unix() (or it's alias, !). Oh well. - (save-excursion - (save-match-data - (let ((opoint (point))) - (and (re-search-backward "\\(\"\\|'\\)[~/#$.a-zA-Z0-9][^ \t\n\"']*" - nil t) - (eq opoint (match-end 0))))))) - - -;;*;; Functions handling the search list - -(defun ess-search-list (&optional force-update) - "Return the current search list as a list of strings. -Elements which are apparently directories are expanded to full -dirnames. Don't try to use cache if FORCE-UPDATE is non-nil. Is -*NOT* used by \\[ess-execute-search], but by \\[ess-resynch], -\\[ess-get-object-list], \\[ess-get-modtime-list], -\\[ess-execute-objects], \\[ess-object-modtime], -\\[ess-create-object-name-db], and (indirectly) by -\\[ess-get-help-files-list]." - (with-current-buffer - (ess-get-process-buffer ess-current-process-name);to get *its* local vars - (let ((result nil) - (slist (ess-process-get 'search-list)) - (tramp-mode nil)) ;; hack for bogus file-directory-p below - (if (and slist - (not force-update) - (not (ess-process-get 'sp-for-help-changed?))) - slist - ;; else, re-compute: - (ess-write-to-dribble-buffer " (ess-search-list ... ) ") - (let ((tbuffer (get-buffer-create " *search-list*")) - (homedir default-directory) - (my-search-cmd inferior-ess-search-list-command); from ess-buffer - elt) - (ess-command my-search-cmd tbuffer 0.05); <- sleep for dde only; does (erase-buffer) - (with-current-buffer tbuffer - ;; guaranteed by the initial space in its name: (buffer-disable-undo) - (goto-char (point-min)) - (ess-write-to-dribble-buffer - (format "after '%s', point-max=%d\n" my-search-cmd (point-max))) - (while (re-search-forward "\"\\([^\"]*\\)\"" nil t) - (setq elt (buffer-substring (match-beginning 1) (match-end 1))) - ;;Dbg: (ess-write-to-dribble-buffer (format " .. elt= %s \t" elt)) - (if (and (string-match "^[^/]" elt) - (file-directory-p (concat homedir elt))) - (progn - ;;Dbg: (ess-write-to-dribble-buffer "*IS* directory\n") - (setq elt (concat homedir elt))) - ;;else - ;;dbg - ;;- (ess-write-to-dribble-buffer "not dir.\n") - ) - (setq result (append result (list elt)))) - (kill-buffer tbuffer))) - result)))) - -;;; ess-sl-modtime-alist is a list with elements as follows: -;;; * key (directory or object name) -;;; * modtime (list of 2 integers) -;;; * name, name ... (accessible objects in search list posn labeled by key) -;;; It is a buffer-local variable (belonging to e.g. *R*, *S+6*, .. etc) -;;; and has the same number of elements and is in the same order as the -;;; S search list - -(defun ess-get-modtime-list (&optional cache-var-name exclude-first) - "Record directories in the search list, and the objects in those directories. -The result is stored in CACHE-VAR-NAME. If nil, CACHE-VAR-NAME -defaults to `ess-sl-modtime-alist'. If EXCLUDE-FIRST is non-nil -don't recompile first object in the search list." - ;; Operation applies to process of current buffer - (let* ((searchlist (if exclude-first - (cdr (ess-search-list)) - (ess-search-list))) - (index (if exclude-first 2 1)) - (cache-name (or cache-var-name 'ess-sl-modtime-alist)) - pack newalist) - (while searchlist - (setq - pack (car searchlist) - newalist (append newalist - (list (or (assoc pack (symbol-value cache-name)) - (append - (list pack (ess-dir-modtime pack)) - (prog2 - (message "Forming completions for %s..." pack) - (ess-object-names pack index) - (message "Forming completions for %s...done" pack)))))) - index (1+ index) - searchlist (cdr searchlist))) - ;;DBG: - (ess-write-to-dribble-buffer - (format "(%s): created new alist of length %d\n" - cache-var-name (length newalist))) - (set cache-name newalist))) - - -(defun ess-search-path-tracker (str) - "Check if input STR changed the search path. -This function monitors user input to the inferior ESS process so -that Emacs can keep the process variable 'search-list' up to -date. `ess-completing-read' in \\[ess-read-object-name] uses this -list indirectly when it prompts for help or for an object to -dump. From ESS 12.09 this is not necessary anymore, as the search -path is checked on idle time. It is kept for robustness and -backward compatibility only." - (when ess-change-sp-regexp - (if (string-match ess-change-sp-regexp str) - (ess-process-put 'sp-for-help-changed? t)))) - - -;;; Miscellaneous routines - -;;;*;;; Routines for reading object names -(defun ess-read-object-name (p-string) - "Read an object name from the minibuffer with completion, and return it. -P-STRING is the prompt string." - (let* ((default (ess-read-object-name-dump)) - (object-list (ess-get-object-list ess-local-process-name)) - (spec (ess-completing-read p-string object-list nil nil nil nil default))) - (list (cond - ((string= spec "") default) - (t spec))))) - -(defun ess-read-object-name-default () - "Return the object name at point, or nil if none." - (ignore-errors - (save-excursion - ;; The following line circumvents an 18.57 bug in following-char - (if (eobp) (backward-char 1)) ; Hopefully buffer is not empty! - ;; Get onto a symbol - (catch 'nosym ; bail out if there's no symbol at all before point - (while (let ((sc (char-syntax (following-char)))) - (not (or (= sc ?w) (= sc ?_)))) - (if (bobp) (throw 'nosym nil) (backward-char 1)))) - (let* - ((end (progn (forward-sexp 1) (point))) - (beg (progn (backward-sexp 1) (point)))) - (buffer-substring-no-properties beg end))))) - -(defun ess-read-object-name-dump () - "Return the object name at point, or \"Temporary\" if none." - (ignore-errors - (save-excursion - ;; Get onto a symbol - (catch 'nosym ; bail out if there's no symbol at all before point - (while (/= (char-syntax (following-char)) ?w) - (if (bobp) (throw 'nosym nil) (backward-char 1))) - (let* - ((end (progn (forward-sexp 1) (point))) - (beg (progn (backward-sexp 1) (point))) - (object-name (buffer-substring beg end))) - (or object-name "Temporary")))))) - -;;;; start of ess-smart-operators -;;;; inspired by slime repl shortcuts - -(defvar ess--handy-history nil) - -(defun ess-handy-commands () - "Request and execute a command from `ess-handy-commands' list." - (interactive) - (let* ((commands (or ess--local-handy-commands - ess-handy-commands)) - (hist (and (assoc (car ess--handy-history) - commands) - (car ess--handy-history)))) - (call-interactively - (cdr (assoc (ess-completing-read "Execute" - (sort (mapcar 'car commands) - 'string-lessp) - nil t nil 'ess--handy-history hist) - commands))))) - -(defun ess-smart-comma () - "If comma is invoked at the process marker of an ESS inferior -buffer, request and execute a command from `ess-handy-commands' -list." - (interactive) - (let ((proc (get-buffer-process (current-buffer)))) - (if (and proc - (eq (point) (marker-position (process-mark proc)))) - (ess-handy-commands) - (if ess-smart-operators - (progn - (delete-horizontal-space) - (insert ", ") - (unless (derived-mode-p 'inferior-ess-mode) - (indent-according-to-mode))) - (insert ","))))) - - ; directories -(defun ess-set-working-directory (path &optional no-error) - "Set the current working to PATH for the ESS buffer and iESS process. -NO-ERROR prevents errors when this has not been implemented for -`ess-dialect'." - (interactive "DChange working directory to: ") - (if ess-setwd-command - (let* ((remote (file-remote-p path)) - (path (if remote - (progn - (require 'tramp-sh) - (tramp-sh-handle-expand-file-name path)) - path)) - (lpath (if remote - (with-parsed-tramp-file-name path v v-localname) - path))) - (ess-eval-linewise (format ess-setwd-command lpath)) - ;; use set instead of setq to take effect even when let bound - (set 'default-directory (file-name-as-directory path))) - (unless no-error - (error "Not implemented for dialect %s" ess-dialect)))) - -(defalias 'ess-change-directory 'ess-set-working-directory) -(define-obsolete-function-alias - 'ess-use-dir 'ess-set-working-directory "ESS 18.10") - -(defun ess-use-this-dir (&rest _ignore) - "Set the current process directory to the directory of this file. -`default-directory' is used as a fallback." - (interactive) - (let ((dir (if buffer-file-name - (file-name-directory buffer-file-name) - default-directory))) - (ess-set-working-directory (abbreviate-file-name dir)))) - -(defun ess-get-working-directory (&optional no-error) - "Retrieve the current working directory from the current ess process." - (if ess-getwd-command - (abbreviate-file-name (car (ess-get-words-from-vector ess-getwd-command))) - (unless no-error - (error "Not implemented for dialect %s" ess-dialect)))) - -(defun ess-synchronize-dirs () - "Set Emacs' current directory to be the same as the subprocess directory. -To be used in `ess-idle-timer-functions'." - (when (and ess-can-eval-in-background - ess-getwd-command - (inferior-ess-available-p)) - (ess-when-new-input last-sync-dirs - (ess-if-verbose-write "\n(ess-synchronize-dirs)\n") - (setq default-directory - (car (ess-get-words-from-vector ess-getwd-command))) - default-directory))) - -(defun ess-dirs () - "Set Emacs' current directory to be the same as the *R* process." - ;; Note: This function is not necessary anymore. The Emacs - ;; default-directory and subprocess working directory are - ;; synchronized automatically. - (interactive) - (let ((dir (car (ess-get-words-from-vector "getwd()\n")))) - (message "(ESS / default) directory: %s" dir) - (setq default-directory (file-name-as-directory dir)))) - -;; search path -(defun ess--mark-search-list-as-changed () - "Internal. Mark all the search-list related variables as changed." - ;; other guys might track their own - (ess-process-put 'sp-for-help-changed? t) - (ess-process-put 'sp-for-ac-changed? t)) - -(defun ess-cache-search-list () - "To be used in `ess-idle-timer-functions', to set search path related variables." - (when (and ess-can-eval-in-background - inferior-ess-search-list-command) - (ess-when-new-input last-cache-search-list - (let ((path (ess-search-list 'force)) - (old-path (process-get *proc* 'search-list))) - (when (not (equal path old-path)) - (process-put *proc* 'search-list path) - (ess--mark-search-list-as-changed) - path))))) - - -;;*;; Temporary buffer handling -(defun ess-display-temp-buffer (buff) - "Display the buffer BUFF. -Uses `temp-buffer-show-function' and respects -`ess-display-buffer-reuse-frames'." - (if (fboundp temp-buffer-show-function) - (funcall temp-buffer-show-function buff)) - (display-buffer buff '(display-buffer-reuse-window) ess-display-buffer-reuse-frames)) - -(defun ess--inject-code-from-file (file &optional chunked) - "Load code from FILE into process. -If CHUNKED is non-nil, split the file by separator (must be at -bol) and load each chunk separately." - ;; This is different from ess-load-file as it works by directly loading the - ;; string into the process and thus works on remotes. - (let ((proc-name ess-local-process-name) - (dialect ess-dialect) - (send-1 (lambda (str) - (if (string= ess-dialect "R") - ;; avoid detection of intermediate prompts - (ess-command (concat "{" str "}\n")) - (ess-command str))))) - (with-temp-buffer - (setq ess-local-process-name proc-name - ess-dialect dialect) - (insert-file-contents-literally file) - (if chunked - (let ((beg (point-min))) - (goto-char beg) - (while (re-search-forward "^ " nil t) - (funcall send-1 (buffer-substring beg (point))) - (setq beg (point))) - (funcall send-1 (buffer-substring (point) (point-max)))) - (funcall send-1 (buffer-string)))))) - -(defun ess-check-modifications nil - "Check whether loading this file would overwrite some ESS objects -which have been modified more recently than this file, and confirm -if this is the case." - ;; FIXME: this should really cycle through all top-level assignments in - ;; the buffer - ;;VS[02-04-2012|ESS 12.03]: this is sooo ugly - (when (> (length ess-change-sp-regexp) 0) - (and (buffer-file-name) ess-filenames-map - (let ((sourcemod (nth 5 (file-attributes (buffer-file-name)))) - (objname)) - (save-excursion - (goto-char (point-min)) - ;; Get name of assigned object, if we can find it - (setq objname - (and - (re-search-forward - "^\\s *\"?\\(\\(\\sw\\|\\s_\\)+\\)\"?\\s *[<_]" - nil - t) - (buffer-substring (match-beginning 1) - (match-end 1))))) - (and - sourcemod ; the file may have been deleted - objname ; may not have been able to - ; find name - (ess-modtime-gt (ess-object-modtime objname) sourcemod) - (not (y-or-n-p - (format - "The ESS object %s is newer than this file. Continue? " - objname))) - (error "Aborted")))))) - -(define-obsolete-function-alias 'ess-check-source #'ess-save-file "ESS 19.04") -(defun ess-save-file (file) - "If FILE (a string) has an unsaved buffer, offer to save it. -Return t if the buffer existed and was modified, but was not -saved. If `ess-save-silently' is non-nil, the buffer is -saved without offering." - (when-let ((buff (find-buffer-visiting file))) - (when (and (buffer-modified-p buff) - (or (eql ess-save-silently t) - (and (eql ess-save-silently 'auto) - (or (not compilation-ask-about-save) - (bound-and-true-p - ;; Only added in Emacs 26.1 - auto-save-visited-mode))) - (y-or-n-p - (format "Buffer %s is modified. Save? " - (buffer-name buff))))) - (with-current-buffer buff - (save-buffer))) - (buffer-modified-p buff))) - - -;;*;; Error messages - -(defun ess-parse-errors (&optional showerr _reset) - "Jump to error in last loaded ESS source file. -With prefix argument SHOWERR, only show the errors ESS reported. RESET -is for compatibility with `next-error' and is ignored." - (interactive "P") - (ess-make-buffer-current) - (let ((errbuff (get-buffer ess-error-buffer-name))) - (when (not errbuff) - (error "You need to do a load first!")) - (set-buffer errbuff) - (goto-char (point-max)) - ;; FIXME: R does not give "useful" error messages by default. We - ;; could try to use a more useful one, via - ;; options(error=essErrorHandler) - (cond ((re-search-backward ess-error-regexp nil t) - (let* ((filename (buffer-substring (match-beginning 3) (match-end 3))) - (fbuffer (get-file-buffer filename)) - (linenum - (string-to-number - (buffer-substring (match-beginning 2) (match-end 2)))) - (errmess (buffer-substring (match-beginning 1) (match-end 1)))) - (if showerr - (ess-display-temp-buffer errbuff) - (if fbuffer nil - (setq fbuffer (find-file-noselect filename)) - (with-current-buffer fbuffer - ;; TODO: ess-mode is surely wrong here, but I don't - ;; think we need this whole function anymore? - (when (fboundp 'ess-mode) - (ess-mode)))) - (pop-to-buffer fbuffer) - (ess-goto-line linenum)) - (princ errmess t))) - (t - (message "Not a syntax error.") - (ess-display-temp-buffer errbuff))))) - -(defun ess-error (msg) - "Something bad has happened. -Display the S buffer, and cause an error displaying MSG." - (declare (obsolete error "ESS 18.10")) - (display-buffer (process-buffer (get-process ess-local-process-name))) - (error msg)) - -(provide 'ess-inf) -;;; ess-inf.el ends here diff --git a/elpa/ess-20191014.1343/ess-jags-d.el b/elpa/ess-20191014.1343/ess-jags-d.el deleted file mode 100644 index fcf7b872..00000000 --- a/elpa/ess-20191014.1343/ess-jags-d.el +++ /dev/null @@ -1,254 +0,0 @@ -;;; ess-jags-d.el --- ESS[JAGS] dialect -*- lexical-binding: t; -*- - -;; Copyright (C) 2008-2011 Rodney Sparapani - -;; Author: Rodney Sparapani -;; Created: 13 March 2008 -;; Maintainer: ESS-help - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Code: - -(require 'ess-bugs-d) -(require 'ess-utils) -(require 'ess-inf) -(require 'ess-mode) - -(defvar ess-jags-command "jags" "Default JAGS program in PATH.") -(make-local-variable 'ess-jags-command) - -(defvar ess-jags-monitor '("") "Default list of variables to monitor.") -(make-local-variable 'ess-jags-monitor) - -(defvar ess-jags-thin 1 "Default thinning parameter.") -(make-local-variable 'ess-jags-thin) - -(defvar ess-jags-chains 1 "Default number of chains.") -(make-local-variable 'ess-jags-chains) - -(defvar ess-jags-burnin 10000 "Default burn-in.") -(make-local-variable 'ess-jags-burnin) - -(defvar ess-jags-update 10000 "Default number of updates after burnin.") -(make-local-variable 'ess-jags-update) - -(defvar ess-jags-system t "Default whether JAGS recognizes the system command.") - -(defvar ess-jags-font-lock-keywords - (list - ;; .jag files - (cons "#.*\n" font-lock-comment-face) - - (cons "^[ \t]*\\(model\\|var\\)\\>" - font-lock-keyword-face) - - (cons (concat "\\& " ess-bugs-file-root ".jog ") - ;else - "> " ess-bugs-file-root ".jog 2>&1 ") - - ; ;.txt not recognized by BOA and impractical to over-ride - ; "&& (rm -f " ess-bugs-file-root ".ind; " - ; "ln -s " ess-bugs-file-root "index.txt " ess-bugs-file-root ".ind; " - ; "for i in " ess-jags-temp-chains "; do; " - ; "rm -f " ess-bugs-file-root "$i.out; " - ; "ln -s " ess-bugs-file-root "chain$i.txt " ess-bugs-file-root "$i.out; done) " - - ess-bugs-batch-post-command) - - (comint-send-input) - )) - -(defun ess-jags-na-bug () - "ESS[JAGS]: Perform Next-Action for .jag" - - (if (equal 0 (buffer-size)) (ess-jags-switch-to-suffix ".jag") - ;else - (ess-save-and-set-local-variables) - (ess-jags-switch-to-suffix ".jmd" - ess-jags-chains ess-jags-monitor ess-jags-thin ess-jags-burnin ess-jags-update)) - ) - -;;;###autoload -(define-derived-mode ess-jags-mode ess-bugs-mode "ESS[JAGS]" - "Major mode for JAGS." - (setq-local comment-start "#") - (setq font-lock-defaults '(ess-jags-font-lock-keywords nil t)) - (setq ess-language "S") ; mimic S for ess-smart-underscore - (unless (and (fboundp 'w32-shell-dos-semantics) - (w32-shell-dos-semantics)) - (add-hook 'comint-output-filter-functions 'ess-bugs-exit-notify-sh)) - ) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Jj][Aa][Gg]\\'" . ess-jags-mode)) - -(provide 'ess-jags-d) - -;;; ess-jags-d.el ends here diff --git a/elpa/ess-20191014.1343/ess-julia.el b/elpa/ess-20191014.1343/ess-julia.el deleted file mode 100644 index 5f244236..00000000 --- a/elpa/ess-20191014.1343/ess-julia.el +++ /dev/null @@ -1,469 +0,0 @@ -;; ess-julia.el --- ESS julia mode and inferior interaction -*- lexical-binding: t; -*- -;; -;; Copyright (C) 2012-2015 Vitalie Spinu and the ESS Core team. -;; -;; Author: Vitalie Spinu -;; Maintainer: Vitalie Spinu -;; Created: 02-04-2012 (ESS 12.03) -;; Keywords: ESS, julia -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; This file is *NOT* part of GNU Emacs. -;; This file is part of ESS -;; -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3, or -;; (at your option) any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ -;; -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Commentary: -;; -;; Customize inferior-julia-program to point to your julia binary -;; and start the inferior with M-x julia. -;; -;; As of Sept 2015, this file depends heavily on julia-mode.el from the Julia -;; sources. If you install ESS using `make', this will work fine, otherwise -;; ensure that julia-mode.el is on your path before loading this file. -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Code: - -(require 'ess-help) -(require 'ess-inf) -(require 'ess-r-mode) -(require 'ess-utils) -(require 'julia-mode) - -(defvar ac-prefix) -(declare-function company-in-string-or-comment "company") -(declare-function company-doc-buffer "company") - -(defcustom inferior-julia-args "" - "String of arguments (see `julia --help') used when starting julia." - :group 'ess-julia - :type 'string) - -(eval-when-compile - (require 'cl-lib)) - -(defun ess-julia-send-string-function (process string _visibly) - "Send the Julia STRING to the PROCESS. -VISIBLY is not currently used." - (let ((file (concat temporary-file-directory "julia_eval_region.jl"))) - (with-temp-file file - (insert string)) - (process-send-string process (format ess-load-command file)))) - - -;;; HELP -(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "julia")) - (append (with-current-buffer (ess-command "ESS.all_help_topics()\n") - (split-string (buffer-string) "\n")) - (ess-julia--get-objects proc))) - -(defun ess-julia--retrive-topics (url) - (with-current-buffer (url-retrieve-synchronously url) - (require 'url) - (goto-char (point-min)) - (let (out) - (while (re-search-forward - "toctext[ \"]+href=\"\\([^>]+\\)\">\\([^<]+\\) ") - (inferior-ess-secondary-prompt . nil) - (inferior-ess-prompt . "\\w*> ") - (ess-local-customize-alist . 'ess-julia-customize-alist) - (inferior-ess-program . inferior-julia-program) - (ess-load-command . "include(expanduser(\"%s\"))\n") - (ess-funargs-command . "ESS.fun_args(\"%s\")\n") - (ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+") - (ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)") - (ess-error-regexp-alist . ess-julia-error-regexp-alist) - (ess-mode-completion-syntax-table . ess-julia-completion-syntax-table) - ;; (inferior-ess-objects-command . inferior-ess-r-objects-command) - ;; (inferior-ess-search-list-command . "search()\n") - (inferior-ess-help-command . "ESS.help(\"%s\")\n") - ;; (inferior-ess-help-command . "help(\"%s\")\n") - (ess-language . "julia") - (ess-dialect . "julia") - (ess-suffix . "jl") - (ess-dump-filename-template . (replace-regexp-in-string - "S$" ess-suffix ; in the one from custom: - ess-dump-filename-template-proto)) - (ess-mode-editing-alist . nil) - (ess-change-sp-regexp . nil );ess-r-change-sp-regexp) - (ess-help-sec-regex . ess-help-r-sec-regex) - (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) - (ess-function-pattern . ess-r-function-pattern) - (ess-object-name-db-file . "ess-jl-namedb.el" ) - (ess-smart-operators . ess-r-smart-operators) - (inferior-ess-exit-command . "exit()\n") - ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help? - (inferior-ess-language-start . nil) - (ess-STERM . "iESS") - (ess-editor . ess-r-editor) - (ess-pager . ess-r-pager) - (ess-getwd-command . "pwd()\n") - (ess-setwd-command . "cd(expanduser(\"%s\"))\n")) - "Variables to customize for Julia.") - -(cl-defmethod ess--help-web-search-override (cmd &context (ess-dialect "julia")) - "Offer to search the web for a Julia command." - (browse-url (format "https://docs.julialang.org/en/latest/search/?q=%s" cmd))) - -(defvar ess-julia-completion-syntax-table - (let ((table (copy-syntax-table ess-r-mode-syntax-table))) - (modify-syntax-entry ?. "_" table) - ;; (modify-syntax-entry ?: "_" table) - ;; (modify-syntax-entry ?$ "_" table) - (modify-syntax-entry ?@ "_" table) - table) - "Syntax table used for completion and help symbol lookup. -It makes underscores and dots word constituent chars.") - -(cl-defmethod ess-help-commands (&context (ess-dialect "julia")) - '((packages . "_ess_list_categories()\n") - (package-index . "_ess_print_index(\"%s\")\n") - (index-keyword-reg . "^\\(.*+\\):$*") - (index-start-reg . ":"))) - -(defvar ess-julia-mode-syntax-table (copy-syntax-table julia-mode-syntax-table)) - -(defvar ess-julia-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map ess-mode-map) - map) - "Keymap for `ess-julia-mode'.") - -;;;###autoload -(define-derived-mode ess-julia-mode julia-mode "ESS[julia]" - "Major mode for julia files." - :group 'ess-Julia - (setq-local ess-local-customize-alist ess-julia-customize-alist) - (setq ess-dialect "julia") - (ess-setq-vars-local ess-julia-customize-alist) - ;; eldoc - (add-function :before-until (local 'eldoc-documentation-function) - #'ess-julia-eldoc-function) - (when ess-use-eldoc (eldoc-mode)) - ;; auto-complete - (ess--setup-auto-complete '(ac-source-ess-julia-objects)) - ;; company - (ess--setup-company '(company-ess-julia-objects)) - ;; for emacs >= 24 - (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first - (add-hook 'completion-at-point-functions 'ess-julia-object-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-julia-latexsub-completion nil 'local) - (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))) - -;; Inferior mode -(defvar inferior-ess-julia-mode-syntax-table - (copy-syntax-table ess-julia-mode-syntax-table) - "Syntax table for `inferior-ess-julia-mode'.") - -(define-derived-mode inferior-ess-julia-mode inferior-ess-mode "iESS[julia]" - "Major mode for inferior julia processes." - :group 'ess-Julia - (ess-setq-vars-local ess-julia-customize-alist) - (setq-local comint-use-prompt-regexp t) - (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) - (setq ess-dialect "julia") - ;; eldoc - (add-function :before-until (local 'eldoc-documentation-function) - #'ess-julia-eldoc-function) - (when ess-use-eldoc (eldoc-mode)) - ;; auto-complete - (ess--setup-auto-complete '(ac-source-ess-julia-objects) t) - ;; company - (ess--setup-company '(company-ess-julia-objects) t) - (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first - (add-hook 'completion-at-point-functions 'ess-julia-object-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-julia-latexsub-completion nil 'local) - (setq comint-input-sender #'ess-julia-input-sender)) - -(defvar ess-julia-mode-hook nil) -(defvar ess-julia-post-run-hook nil - "Functions run in process buffer after starting julia process.") - -;;;###autoload -(defun run-ess-julia (&optional start-args) - "Start an inferior julia process. -Optional prefix START-ARGS (\\[universal-argument]) allows to set -command line arguments, such as --load=. This should be OS -agnostic. If you have certain command line arguments that should -always be passed to julia, put them in the variable -`inferior-julia-args'." - (interactive "P") - ;; get settings, notably inferior-julia-program : - (if (null inferior-julia-program) - (error "'inferior-julia-program' does not point to 'julia' or 'julia-basic' executable") - (ess-write-to-dribble-buffer ;; for debugging only - (format - "\n(julia): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n" - ess-dialect (current-buffer) start-args current-prefix-arg)) - (let* ((jl-start-args - (concat inferior-julia-args " " ; add space just in case - (if start-args - (read-string - (concat "Starting Args" - (if inferior-julia-args - (concat " [other than '" inferior-julia-args "']")) - " ? ")) - nil)))) - (let ((inf-buf (inferior-ess jl-start-args ess-julia-customize-alist))) - (with-current-buffer inf-buf - (ess--tb-start) - ;; Remove ` from julia's logo - (goto-char (point-min)) - (while (re-search-forward "`" nil t) - (replace-match "'")) - ;; Remove an offending unmatched parenthesis - (goto-char (point-min)) - (forward-line 4) - (when (re-search-forward "(" nil t) - (replace-match "|")) - (goto-char (point-max)) - ;; --> julia helpers from ../etc/ess-julia.jl : - (ess--inject-code-from-file (format "%sess-julia.jl" ess-etc-directory)) - (run-mode-hooks 'ess-julia-post-run-hook)) - inf-buf)))) - -;;;###autoload -(defalias 'julia #'run-ess-julia) - -(cl-defmethod ess--help-major-mode (&context (ess-dialect "julia")) - (ess-julia-help-mode)) - -(define-derived-mode ess-julia-help-mode ess-help-mode "ESS[Julia] Help" - "Major mode for Julia documentation." - :group 'ess-help - (let ((inhibit-read-only t)) - ;; Julia help buffers can contain color if julia starts with - ;; --color=yes - (ansi-color-apply-on-region (point-min) (point-max)))) - -(add-to-list 'auto-mode-alist '("\\.jl\\'" . ess-julia-mode)) - -(provide 'ess-julia) -;;; ess-julia.el ends here diff --git a/elpa/ess-20191014.1343/ess-mode.el b/elpa/ess-20191014.1343/ess-mode.el deleted file mode 100644 index 84a4b3f8..00000000 --- a/elpa/ess-20191014.1343/ess-mode.el +++ /dev/null @@ -1,672 +0,0 @@ -;;; ess-mode.el -- Emacs Speaks Statistics root mode. -*- lexical-binding: t; -*- -;; -;; Copyright (C) 1994-2018 ESS Core Team -;; Maintainer: ESS-core -;; -;; Keywords: languages -;; -;; This file is part of ESS -;; -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ -;; -;;; Commentary: -;; -;;; Code: - -(require 'ess) - -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) -(require 'ess-inf) - -;; Silence the byte compiler -(declare-function run-ess-r "ess-r-mode" (&optional start-args)) -(declare-function S+ "ess-sp6-d" (&optional proc-name)) -(declare-function SAS "ess-sas-d" ()) - -;; FIXME:This one should not be necessary -(declare-function ess-display-help-on-object "ess-help" (object &optional command)) - -;; ESS mode -;; Major mode definition - -;;*;; Hooks - -(defcustom ess-mode-hook nil - "Hook for customizing ESS each time it is entered." - :group 'ess-hooks - :type 'hook) - -(defvar ess-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [remap yank] #'ess-yank) - (define-key map "\C-c\C-r" #'ess-eval-region) - (define-key map "\C-c\M-r" #'ess-eval-region-and-go) - (define-key map "\C-c\C-b" #'ess-eval-buffer) - (define-key map "\C-c\M-b" #'ess-eval-buffer-and-go) - (define-key map (kbd "C-c C-") #'ess-eval-buffer-from-beg-to-here) - (define-key map (kbd "C-c C-") #'ess-eval-buffer-from-here-to-end) - (define-key map "\C-c\C-f" #'ess-eval-function) - (define-key map "\C-c\M-f" #'ess-eval-function-and-go) - (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) - (define-key map "\C-c\C-p" #'ess-eval-paragraph-and-step) - (define-key map "\C-c\M-p" #'ess-eval-paragraph-and-go) - (define-key map "\C-\M-x" #'ess-eval-region-or-function-or-paragraph) - (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) - (define-key map "\C-c\C-j" #'ess-eval-line) - (define-key map [(control return)] #'ess-eval-region-or-line-visibly-and-step) - (define-key map "\C-c\M-j" #'ess-eval-line-and-go) - ;; FIXME: The next three can only work in S/R - mode - (define-key map "\C-\M-a" #'ess-goto-beginning-of-function-or-para) - (define-key map "\C-\M-e" #'ess-goto-end-of-function-or-para) - (define-key map "\C-xnd" #'ess-narrow-to-defun-or-para) - (define-key map "\C-xnf" #'ess-narrow-to-defun-or-para) - (define-key map "\C-c\C-z" #'ess-switch-to-inferior-or-script-buffer) - (define-key map "\C-c\C-l" #'ess-load-file) - ;;; Make an alias because C-c C-l is taken up by comint in inferiors - (define-key map "\C-c\M-l" #'ess-load-file) - (define-key map "\C-c\C-v" #'ess-display-help-on-object) - (define-key map "\C-c\C-s" #'ess-switch-process) - (define-key map "\C-c\C-k" #'ess-force-buffer-current) - (define-key map "\C-c`" #'ess-show-traceback) - (define-key map [(control ?c) ?~] #'ess-show-call-stack) - (define-key map "\C-\M-q" #'ess-indent-exp) - (define-key map "{" #'skeleton-pair-insert-maybe) - (define-key map "}" #'skeleton-pair-insert-maybe) - (define-key map "\C-\M-h" #'ess-mark-function-or-para) - (define-key map "\t" #'ess-indent-or-complete) - (define-key map "\C-c\C-q" #'ess-quit) - (define-key map "\M-\r" #'ess-use-this-dir) - (define-key map "," #'ess-smart-comma) - (define-key map "\C-c\C-d" 'ess-doc-map) - (define-key map "\C-c\C-e" 'ess-extra-map) - (define-key map "\C-c\C-t" 'ess-dev-map) - map) - "Keymap for `ess-mode'.") - -;; Redefine substituted commands -(substitute-key-definition 'indent-new-comment-line - 'ess-indent-new-comment-line - ess-mode-map global-map) - -(defvar ess-extra-map - (let (ess-extra-map) - (define-prefix-command 'ess-extra-map) - (define-key ess-extra-map "\C-d" #'ess-dump-object-into-edit-buffer) - (define-key ess-extra-map "d" #'ess-dump-object-into-edit-buffer) - (define-key ess-extra-map "\C-e" #'ess-execute) - (define-key ess-extra-map "e" #'ess-execute) - (define-key ess-extra-map "\C-i" #'ess-install-library) - (define-key ess-extra-map "i" #'ess-install-library) - (define-key ess-extra-map "\C-l" #'ess-load-library) - (define-key ess-extra-map "l" #'ess-load-library) - (define-key ess-extra-map "\C-r" #'inferior-ess-reload) - (define-key ess-extra-map "r" #'inferior-ess-reload) - (define-key ess-extra-map "\C-s" #'ess-set-style) - (define-key ess-extra-map "s" #'ess-set-style) - (define-key ess-extra-map "\C-t" #'ess-build-tags-for-directory) - (define-key ess-extra-map "t" #'ess-build-tags-for-directory) - (define-key ess-extra-map "\C-w" #'ess-execute-screen-options) - (define-key ess-extra-map "w" #'ess-execute-screen-options) - (define-key ess-extra-map "/" #'ess-set-working-directory) - ess-extra-map) - "ESS extra map.") - -(easy-menu-define - ess-mode-menu ess-mode-map - "Menu for use in `ess-mode'." - '("ESS" ; ESS-mode - ["Load file" ess-load-file t] - ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t] - ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t] - ["Eval region | line" ess-eval-region-or-line-visibly-and-step t] - ["Enter expression" ess-execute t] - ;; sub menus - "------" - ("Process" - ["Goto end of process buffer" ess-switch-to-end-of-ESS t] - ["Switch to process buffer" ess-switch-to-inferior-or-script-buffer t] - ["Switch process" ess-switch-process t] - ;; ["Recreate R and S versions known to ESS" (ess-r-s-versions-creation+menu) t] - ("Start Process" - ["R" R :help "Start a new R process" :active t] - ["S" S :help "Start a new S process" :active t] - ["Sqpe" Sqpe ess-microsoft-p] ;; :help "Start a new Sqpe process" :active t - ["S+6-exisiting" S+6-existing ess-microsoft-p] ;; :help "Access an existing S process" :active t - ["SAS" SAS-menu t] ;; :help "Start a new SAS process" :active t - ;; The following menu item "Other" is a place-holder that will - ;; be replaced with the other versions of R and Sqpe that can be run. - ;; See `ess-r-define-runners' and ess-site.el - ("Other" - ["No other R or Sqpe versions" nil nil]) - ["About" - (ess-goto-info "Starting up") t] - ;; :help "Read about starting a new ESS process" :active t] - ) - ("Eval visibly " - :filter ess--generate-eval-visibly-submenu) - ["Quit process" ess-quit t] - ["Reload process" inferior-ess-reload t]) - "------" - ("ESS Eval" - ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t] - ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t] - ["Eval region | line & step" ess-eval-region-or-line-visibly-and-step t] - "-----" - ["Eval buffer" ess-eval-buffer t] - ["Eval buffer till here" ess-eval-buffer-from-beg-to-here t] - ["Eval buffer from here" ess-eval-buffer-from-here-to-end t] - ["Eval region" ess-eval-region t] - ["Eval function" ess-eval-function t] - ["Eval line" ess-eval-line t] - ["Eval line & step" ess-eval-line-and-step t] - ["Eval paragraph" ess-eval-paragraph t] - ["Eval paragraph & step" ess-eval-paragraph-and-step t] - ["About" (ess-goto-info "Evaluating code") t] - ) - ("Eval and Go" - ["Eval buffer" ess-eval-buffer-and-go t] - ["Eval region" ess-eval-region-and-go t] - ["Eval function" ess-eval-function-and-go t] - ["Eval line" ess-eval-line-and-go t] - ["Eval paragraph" ess-eval-paragraph-and-go t] - ["About" (ess-goto-info "Evaluating code") t] - ) - ("Motion" - ["Beginning of function or para" ess-goto-beginning-of-function-or-para t] - ["End of function or para" ess-goto-end-of-function-or-para t] - "-----" - ["Backward list" backward-list t] - ["Forward list" forward-list t] - ["Next parenthesis" down-list t] - ["Enclosing parenthesis" backward-up-list t] - ["Backward sexp" backward-sexp t] - ["Forward sexp" forward-sexp t] - ["About" (Info-goto-node "(Emacs)Lists") t] - ) - ("ESS Edit" - ["Edit new object" ess-dump-object-into-edit-buffer t] - ["Complete Filename" comint-replace-by-expanded-filename t] - ["Complete File or Object" ess-indent-or-complete t] - ["Kill sexp" kill-sexp t] - ["Mark function" ess-mark-function-or-para t] - ["Indent expression" ess-indent-exp t] - ["Indent line" ess-indent-command t] - ["Toggle Auto-Fill Mode" auto-fill-mode t] - ["Undo" undo t] - ["About" (ess-goto-info "Edit buffer") t] - ) - "------" - ("start-dev" :visible nil) - ("end-dev" :visible nil) - "------" - ("Font Lock" - :active ess-font-lock-keywords - :filter ess--generate-font-lock-submenu) - "------" - ["Describe" describe-mode t] - ["About editing" (ess-goto-info "Editing") t] - ["Read ESS info" (ess-goto-info "") t] - ["Send bug report" ess-submit-bug-report t])) - -;;;###autoload -(define-derived-mode ess-mode prog-mode "ESS" - "Major mode for editing ESS source. -Optional arg ALIST describes how to customize the editing mode. -Optional arg PROC-NAME is name of associated inferior process. - -\\{ess-mode-map} - -You can send text to the inferior ESS process from other buffers containing -ESS source. - `ess-eval-region' sends the current region to the ESS process. - `ess-eval-buffer' sends the current buffer to the ESS process. - `ess-eval-function' sends the current function to the ESS process. - `ess-eval-line' sends the current line to the ESS process. - `ess-switch-to-ESS' switches the current buffer to the ESS process buffer. - `ess-switch-to-end-of-ESS' switches the current buffer to the ESS process - buffer and puts point at the end of it. - - `ess-eval-region-and-go', `ess-eval-buffer-and-go', - `ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S - process buffer after sending their text. - - `ess-load-file' sources a file of commands to the ESS process. - -\\[ess-indent-command] indents for ESS code. -\\[backward-delete-char-untabify] converts tabs to spaces as it moves back. -Comments are indented in a similar way to Emacs-lisp mode: - `###' beginning of line - `##' the same level of indentation as the code - `#' the same column on the right, or to the right of such a - column if that is not possible.(default value 40). - \\[indent-for-comment] command automatically inserts such a - `#' in the right place, or aligns such a comment if it is - already inserted. -\\[ess-indent-exp] command indents each line of the syntactic unit following point. - -Variables controlling indentation style: - `ess-indent-offset' - Indentation of ESS statements within surrounding block. - The surrounding block's indentation is the indentation of the line on - which the open-brace appears. - `ess-offset-block' - Indentation of blocks opened with curly braces or anonymous parentheses. - `ess-offset-arguments' - Indentation of function arguments or bracket indices. - `ess-offset-arguments-newline' - Indentation of function arguments or bracket indices when the opening - delimiter is immediately followed by a newline. - `ess-offset-continued' - Indentation style for continued statements. - `ess-align-nested-calls' - Functions whose nested calls should be aligned. - `ess-align-arguments-in-calls' - Calls in which arguments should be aligned. - `ess-align-continuations-in-calls' - Whether ignore indentation after an operator in calls - `ess-align-blocks' - Blocks that should always be aligned vertically. - `ess-indent-from-lhs' - Whether function calls given as argument should be indented from the - parameter name. - `ess-indent-from-chain-start' - Whether to indent arguments from the first of several consecutive calls. - `ess-indent-with-fancy-comments' - Non-nil means distinguish between #, ##, and ### for indentation. - -Furthermore, \\[ess-set-style] command enables you to set up predefined ess-mode -indentation style. See `ess-style-alist' for predefined styles." - :group 'ess - ;; TODO: get rid of these and rely on modes to set variables properly - (when-let ((alist (buffer-local-value 'ess-local-customize-alist (current-buffer)))) - (ess-setq-vars-local alist)) - (when-let ((alist ess-mode-editing-alist)) - (ess-setq-vars-local alist)) - - ;; Keep out of the code. - (setq-local indent-tabs-mode nil) - - (setq mode-line-process - '(" [" - (:eval (ess--get-mode-line-indicator)) - ess--local-mode-line-process-indicator - "]")) - (add-hook 'ess-idle-timer-functions 'ess-synchronize-dirs nil 'local)) - -(defun ess--get-mode-line-indicator () - "Get `ess--mode-line-process-indicator' from process buffer. -Internal function to be used for dynamic mode-line display in -`ess-mode'." - (if ess-local-process-name - (let* ((proc (get-process ess-local-process-name)) - (buff (when proc (process-buffer proc)))) - (if (and proc (buffer-live-p buff)) - (with-current-buffer buff (mapcar 'eval ess--mode-line-process-indicator)) - "none")) - "none")) - - -;;; User commands in ess-mode - -(defun ess-install-library (&optional update package) - "Install PACKAGE for current dialect. -With UPDATE, update cached package list." - (interactive "P") - (ess-install-library--override update package)) - -(cl-defgeneric ess-install-library--override (update package) - "See `ess-install-library' for UPDATE, PACKAGE." - (when update (message "Don't know how to update for %s" ess-dialect)) - (error "Cannot install %s, not available for %s" package ess-dialect)) - - -;; Motion / manipulation commands - -(defun ess-goto-beginning-of-function-or-para () - "If inside a function go to the beginning of it. -Otherwise go to the beginning of paragraph." - (interactive) - (let ((start-pos (point)) - beg end) - (beginning-of-defun) - (setq beg (point)) - (end-of-defun) - (setq end (point)) - (goto-char beg) - (unless (and (< beg start-pos) - (> end start-pos)) - (let ((par-pos (save-excursion - (goto-char start-pos) - (forward-comment most-negative-fixnum) - (backward-paragraph) - (forward-comment most-positive-fixnum) - (point)))) - (if (< end par-pos) - (goto-char par-pos) - (goto-char beg)))))) - -(defun ess-goto-end-of-function-or-para () - "If inside a function go to end of it. -Otherwise go to the end of paragraph." - (interactive) - (let ((pos (point)) - beg end) - (end-of-defun) - (setq end (point)) - (beginning-of-defun) - (setq beg (point)) - (goto-char end) - (when (or (< beg pos) - (> end pos)) - (let ((par-pos (save-excursion - (goto-char pos) - (forward-comment most-positive-fixnum) - (forward-paragraph) - (point)))) - (when (<= par-pos beg) - (goto-char par-pos)))))) - -(defun ess-mark-function-or-para () - "Put mark at end of ESS function, point at beginning." - (interactive) - (ess-goto-beginning-of-function-or-para) - (push-mark (point)) - (ess-goto-end-of-function-or-para) - (exchange-point-and-mark)) - -(define-obsolete-function-alias 'ess-mark-function 'ess-mark-function-or-para "15.09") - -(defun ess-narrow-to-defun-or-para () - "Make text outside current function invisible. -If text is already narrowed, this is removed before narrowing to the -current function." - (interactive) - (save-excursion - (widen) - (let* ((beg (progn (ess-goto-beginning-of-function-or-para) - (point))) - (end (progn (ess-goto-end-of-function-or-para) - (point)))) - (narrow-to-region beg end)))) - -(define-obsolete-function-alias 'ess-narrow-to-defun 'ess-narrow-to-defun-or-para "15.09") - -(defun ess-indent-new-comment-line () - "Like `indent-new-comment-line' but accounts for roxygen comments." - (interactive) - (cond ((and (fboundp 'ess-roxy-indent-new-comment-line) - (string= ess-dialect "R")) - (ess-roxy-indent-new-comment-line)) - (t - (indent-new-comment-line)))) - - -;;; Formatting / indentation -(defvar-local ess--installed-style-vars nil - "A cons of the form (STYLE . VARS). -VARS is a list of all style vars which were not set explicitly to -buffer local values by the user in mode hooks.") - -(defun ess-set-style (&optional style _quiet) - "Set up the `ess-mode' style variables from the `ess-style' variable. -If STYLE argument is given, use that instead. It makes the ESS -indentation style variables buffer local. QUIET is for backward -compatibility and is ignored. - -In programs, when STYLE is nil, the `ess-style' is installed. In -this case, if `ess-style' is buffer local, all settings are -overwritten, otherwise only those settings which are not already -buffer local. For example, `ess-style' is buffer local when it is -set in .dir-locals and thus must have priority over the user -settings in the mode hook." - (interactive - (list (let ((styles (mapcar (lambda (x) (symbol-name (car x))) - ess-style-alist))) - (intern (ess-completing-read - "Set ESS mode indentation style" - styles nil t nil nil ess-style))))) - (let* ((keep-local (and (null style) - (not (local-variable-p 'ess-style)))) - (style (or style ess-style)) - (style-alist (or (cdr (assq style ess-style-alist)) - (error "Bad ESS style: %s" style))) - (vars (if keep-local - ;; Install, but Keep user's buffer-local settings. - (cl-loop for (var . _) in (cdr (assq 'DEFAULT ess-style-alist)) - unless (local-variable-p var) - collect var) - (mapcar #'car style-alist)))) - (when (called-interactively-p 'any) - (message "Set indentation style to %s" style)) - (mapc (lambda (var) - (make-local-variable var) - (set var (cdr (assq var style-alist)))) - vars) - style)) - -(defun ess-indent-command (&optional whole-exp) - "Indent current line as ESS code, or in some cases insert a tab character. -If `tab-always-indent' is non-nil, always indent current line. -Otherwise, indent the current line only if point is at the left -margin or in the line's indentation; otherwise insert a tab. If -given, WHOLE-EXP means indent rigidly all the lines of the -expression starting after point so that this line becomes -properly indented. The relative indentation among the lines of -the expression are preserved. - -If in a roxygen block at the beginning of the line with -`ess-roxy-hide-show-p' non-nil, call `ess-roxy-toggle-hiding' -instead of indenting." - (interactive "P") - (cond ((and (fboundp 'ess-roxy-entry-p) - (fboundp 'ess-roxy-toggle-hiding) - (bolp) - (ess-roxy-entry-p) - ess-roxy-hide-show-p) - (ess-roxy-toggle-hiding)) - (whole-exp - ;; If arg, always indent this line as S - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (funcall indent-line-function)) - beg end) - (save-excursion - (if tab-always-indent - (beginning-of-line)) - (setq beg (point)) - (backward-up-list 1) - (forward-list 1) - (setq end (point)) - (goto-char beg) - (forward-line 1) - (setq beg (point))) - (if (> end beg) - (indent-code-rigidly beg end shift-amt)))) - ((and (not tab-always-indent) - (save-excursion - (skip-chars-backward " \t") - (not (bolp)))) - (insert-tab)) - (t (funcall indent-line-function)))) - -(defun ess-indent-or-complete () - "When region is selected indent the region. -Otherwise, if `tab-always-indent' is 'complete, try to indent, if -code is already indented, complete instead. Also see -`ess-first-tab-never-complete'." - (interactive) - (if (use-region-p) - (indent-region (region-beginning) (region-end)) - (let ((shift (let ((indent (current-indentation))) - (ess-indent-command) - (- (current-indentation) indent)))) - (when (and (or (equal tab-always-indent 'complete) - ess-tab-complete-in-script) - (numberp shift) ;; can be nil if tab-always-indent is nil - (equal shift 0) - (or (eq last-command 'ess-indent-or-complete) - (null ess-first-tab-never-complete) - (and (eq ess-first-tab-never-complete 'unless-eol) - (looking-at "\\s-*$")) - (and (eq ess-first-tab-never-complete 'symbol) - (not (looking-at "\\w\\|\\s_"))) - (and (eq ess-first-tab-never-complete 'symbol-or-paren) - (not (looking-at "\\w\\|\\s_\\|\\s)"))) - (and (eq ess-first-tab-never-complete 'symbol-or-paren-or-punct) - (not (looking-at "\\w\\|\\s_\\|\\s)\\|\\s."))))) - (completion-at-point))))) - -(defun ess-indent-exp () - "Indent each line of the ESS grouping following point." - (interactive) - (cond ((and (fboundp 'ess-r-indent-exp) - (string= ess-dialect "R")) - (ess-r-indent-exp)) - (t - (save-excursion - (let ((start (point)) - (end (ignore-errors (forward-sexp 1) (point)))) - (when end - (indent-region start end))))))) - -(defun ess-indent-line () - "Indent current line as ESS code. -Return the amount the indentation changed by." - (declare (obsolete 'indent-line-function "ESS 19.04")) - (funcall indent-line-function)) - - -;;; Dump Objects - -(defun ess-dump-object-into-edit-buffer (object) - "Edit an ESS OBJECT in its own buffer. -Without a prefix argument, this simply finds the file pointed to by -`ess-source-directory'. If this file does not exist, or if a -prefix argument is given, a dump() command is sent to the ESS process to -generate the source buffer." - (interactive - (progn - (ess-force-buffer-current "Process to dump from: ") - (ess-read-object-name "Object to edit"))) - (let* ((dirname (file-name-as-directory - (if (stringp ess-source-directory) - ess-source-directory - (with-current-buffer (process-buffer (ess-get-process - ess-local-process-name)) - (ess-setq-vars-local ess-local-customize-alist) - (apply ess-source-directory nil))))) - (filename (concat dirname (convert-standard-filename (format ess-dump-filename-template object)))) - (old-buff (get-file-buffer filename))) - ;; If the directory doesn't exist, offer to create it - (unless (file-exists-p (directory-file-name dirname)) - (if (y-or-n-p (format "Directory %s does not exist. Create it? " dirname)) - (make-directory (directory-file-name dirname)) - (error "Directory %s does not exist" dirname))) - ;; Three options: - ;; (1) Pop to an existing buffer containing the file in question - ;; (2) Find an existing file - ;; (3) Create a new file by issuing a dump() command to S - ;; Force option (3) if there is a prefix arg - (cond (current-prefix-arg - (ess-dump-object object filename)) - (old-buff - (pop-to-buffer old-buff)) - ((file-exists-p filename) - (ess-find-dump-file-other-window filename) - (message "Read %s" filename)) - (t (ess-dump-object object filename))))) - -(defun ess-dump-object (object filename) - "Dump the ESS object OBJECT into file FILENAME." - (unless (file-writable-p filename) - (error "Can't dump %s as %f is not writeable" object filename)) - (let ((dump-cmd (format inferior-ess-dump-command object filename))) - ;; Make sure we start fresh - (when (get-file-buffer filename) - (kill-buffer (get-file-buffer filename))) - (ess-command dump-cmd) - (message "Dumped in %s" filename) - (ess-find-dump-file-other-window filename) - ;; PD, 1Apr97 - ;;This ensures that the object gets indented according to ess-mode, - ;;not as the R/S deparser does it. At the same time, it gets rid - ;;of the mess generated by sending TAB characters to the readline - ;;functions in R when you eval-buffer-*. - (indent-region (point-min-marker) (point-max-marker) nil) - (set-buffer-modified-p nil) ; no need to safe just because of indenting - ;; Don't make backups for temporary files; it only causes clutter. - ;; The ESS object itself is a kind of backup, anyway. - (unless ess-keep-dump-files - (make-local-variable 'make-backup-files) - (setq make-backup-files nil)) - ;; Don't get confirmation to delete dumped files when loading - (when (eq ess-keep-dump-files 'check) - (setq ess-keep-dump-files nil)) - ;; Delete the file if necessary - (when ess-delete-dump-files - (delete-file (buffer-file-name))))) - -(defun ess-find-dump-file-other-window (filename) - "Find ESS source file FILENAME in another window." - (unless (file-readable-p filename) - (ess-write-to-dribble-buffer - (format "%s does not exist. Bad dump, starting fresh." filename))) - ;; Generate a buffer with the dumped data - (find-file-other-window filename) - (auto-save-mode 1) ; Auto save in this buffer - (when (and ess-function-template - (goto-char (point-max)) - (re-search-backward ess-dumped-missing-re nil t)) - (replace-match ess-function-template t t) - (set-buffer-modified-p nil) ; Don't offer to save if killed now - (goto-char (point-min)) - (ignore-errors - ;; This may fail if there are no opens - (down-list 1)))) - - -;;; Runners - -(defun ess-define-runner (name dialect &optional path) - "Create a function NAME. -This function starts the inferior process with the specified -version. DIALECT can be \"R,\" \"S,\", \"SAS.\" If given, PATH -should be the absolute path to the program. It defaults to NAME." - (let ((name name) - (dialect dialect) - (path path)) - (fset (intern name) - (lambda (&optional start-args) - "Start this process version in an inferior ESS buffer. -Function defined using `ess-define-runner'." - (interactive "P") - (cond ((string= dialect "R") - (let ((inferior-ess-r-program (or path name))) - (require 'ess-r-mode) - (run-ess-r start-args))) - ((string= dialect "S") - (let ((inferior-S+-program (or path name))) - (require 'ess-sp6-d) - (S+))) - ((string= dialect "SAS") - (let ((inferior-SAS-program (or path name))) - (require 'ess-sas-d) - (SAS)))))))) - - - -(provide 'ess-mode) - -;;; ess-mode.el ends here diff --git a/elpa/ess-20191014.1343/ess-pkg.el b/elpa/ess-20191014.1343/ess-pkg.el deleted file mode 100644 index 5bdb9ac4..00000000 --- a/elpa/ess-20191014.1343/ess-pkg.el +++ /dev/null @@ -1,22 +0,0 @@ -(define-package "ess" "20191014.1343" "Emacs Speaks Statistics" - '((emacs "25.1") - (julia-mode "0.3")) - :authors - '(("David Smith" . "dsmith@stats.adelaide.edu.au") - ("A.J. Rossini" . "blindglobe@gmail.com") - ("Richard M. Heiberger" . "rmh@temple.edu") - ("Kurt Hornik" . "Kurt.Hornik@R-project.org") - ("Martin Maechler" . "maechler@stat.math.ethz.ch") - ("Rodney A. Sparapani" . "rsparapa@mcw.edu") - ("Stephen Eglen" . "stephen@gnu.org") - ("Sebastian P. Luque" . "spluque@gmail.com") - ("Henning Redestig" . "henning.red@googlemail.com") - ("Vitalie Spinu" . "spinuvit@gmail.com") - ("Lionel Henry" . "lionel.hry@gmail.com") - ("J. Alexander Branham" . "alex.branham@gmail.com")) - :maintainer - '("ESS Core Team" . "ESS-core@r-project.org") - :url "https://ess.r-project.org/") -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/ess-20191014.1343/ess-r-completion.el b/elpa/ess-20191014.1343/ess-r-completion.el deleted file mode 100644 index 2eeca6e5..00000000 --- a/elpa/ess-20191014.1343/ess-r-completion.el +++ /dev/null @@ -1,519 +0,0 @@ -;;; ess-r-completion.el --- R completion -*- lexical-binding: t; -*- -;; -;; Copyright (C) 2015 A.J. Rossini, Richard M. Heiberger, Martin Maechler, Kurt -;; Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. -;; -;; Author: Vitalie Spinu -;; Maintainer: ESS-core -;; -;; Keywords: languages, statistics -;; -;; This file is part of ESS. -;; -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ -;; -;;; Commentary: -;; -;;; Code: - - -;;; ElDoc - -(require 'cl-lib) -(require 'ess-inf) -(require 'ess-help) - -(eval-when-compile - (require 'subr-x)) - -(defvar ac-auto-start) -(defvar ac-prefix) -(defvar ac-point) -(defvar ac-use-comphist) -(declare-function company-begin-backend "company") -(declare-function company-doc-buffer "company") - -(defcustom ess-R-argument-suffix " = " - "Suffix appended by `ac-source-R' and `ac-source-R-args' to candidates." - :group 'ess-R - :type 'string) - -(defun ess-r-eldoc-function () - "Return the doc string, or nil. -If an ESS process is not associated with the buffer, do not try -to look up any doc strings." - (when (and eldoc-mode ess-can-eval-in-background) - (let* ((proc (ess-get-next-available-process)) - (funname (and proc (or (and ess-eldoc-show-on-symbol ;; Aggressive completion - (thing-at-point 'symbol)) - (car (ess--fn-name-start)))))) - (when funname - (let* ((args (ess-function-arguments funname proc)) - (bargs (cadr args)) - (doc (mapconcat (lambda (el) - (if (equal (car el) "...") - "..." - (concat (car el) "=" (cdr el)))) - bargs ", ")) - (margs (nth 2 args)) - (W (- (window-width (minibuffer-window)) (+ 4 (length funname)))) - doc1) - (when doc - (setq doc (ess-eldoc-docstring-format funname doc)) - (when (and margs (< (length doc1) W)) - (setq doc1 (concat doc (propertize " || " 'face font-lock-function-name-face))) - (while (and margs (< (length doc1) W)) - (let ((head (pop margs))) - (unless (assoc head bargs) - (setq doc doc1 - doc1 (concat doc1 head "=, "))))) - (when (equal (substring doc -2) ", ") - (setq doc (substring doc 0 -2))) - (when (and margs (< (length doc) W)) - (setq doc (concat doc " {--}")))) - doc)))))) - -(defun ess-eldoc-docstring-format (funname doc) - (save-match-data - (let* (;; (name (symbol-name sym)) - (truncate (or (not (eq t eldoc-echo-area-use-multiline-p)) - (eq ess-eldoc-abbreviation-style 'aggressive))) - ;; Subtract 1 from window width since will cause a wraparound and - ;; resize of the echo area. - (W (1- (- (window-width (minibuffer-window)) - (+ 2 (length funname)))))) - (setq doc - (if (or (<= (length doc) W) - (null ess-eldoc-abbreviation-style) - (eq 'none ess-eldoc-abbreviation-style)) - doc - ;;MILD filter - (setq doc (replace-regexp-in-string "TRUE" "T" doc)) - (setq doc (replace-regexp-in-string "FALSE" "F" doc)) - (if (or (<= (length doc) W) - (eq 'mild ess-eldoc-abbreviation-style)) - doc - ;;NORMAL filter (deal with long defaults) - (setq doc (replace-regexp-in-string - ;; function calls inside default docs foo(xxxx{..}) - "([^)]\\{8\\}\\([^)]\\{4,\\}\\))" - "{.}" doc nil nil 1)) - (if (<= (length doc) W) - doc - (setq doc (replace-regexp-in-string - " +[^ \t=,\"\]+=[^ \t]\\{10\\}\\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)" - "{.}," doc nil nil 1)) - (if (<= (length doc) W) - doc - (setq doc (replace-regexp-in-string - " +[^ \t=,\"]+=\\([^ \t]\\{10,\\}\\)\\(,\\|\\'\\)" - "{.}," doc nil nil 1)) - (if (or (<= (length doc) W) - (eq 'normal ess-eldoc-abbreviation-style)) - doc - ;;STRONG filter (replace defaults) - (setq doc (replace-regexp-in-string - " *[^ \t=,\"\\]* = \\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)" - "{.}," doc nil nil 1)) - (if (<= (length doc) W) - doc - (setq doc (replace-regexp-in-string - "\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+=\\|\\'\\)" - "" doc nil nil 1)) - (setq doc (replace-regexp-in-string - "\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+,\\|\\'\\)" - "" doc nil nil 1)) - (if (or (<= (length doc) W) - (eq 'strong ess-eldoc-abbreviation-style)) - doc - ;;AGGRESSIVE filter (truncate what is left) - (concat (substring doc 0 (- W 4)) "{--}"))))))))) - (when (and truncate - (> (length doc) W)) - (setq doc (concat (substring doc 0 (- W 4)) "{--}"))) - (format "%s: %s" (propertize funname 'face 'font-lock-function-name-face) doc)))) - - -;;; OBJECTS - -(defun ess-r-object-completion () - "Return completions at point in a format required by `completion-at-point-functions'." - (if (ess-make-buffer-current) - (let* ((funstart (cdr (ess--fn-name-start))) - (completions (ess-r-get-rcompletions funstart)) - (token (pop completions))) - (when completions - (list (- (point) (length token)) (point) - completions))) - (when (string-match "complete" (symbol-name last-command)) - (message "No ESS process associated with current buffer") - nil))) - -(defun ess-complete-object-name () - "Perform completion on object preceding point. -Uses `ess-r-complete-object-name' when `ess-use-R-completion' is non-nil, -and `ess-internal-complete-object-name' otherwise." - (interactive) - (if (ess-make-buffer-current) - (if ess-use-R-completion - (ess-r-complete-object-name) - (ess-internal-complete-object-name)) - ;; else give a message on second invocation - (when (string-match "complete" (symbol-name last-command)) - (message "No ESS process associated with current buffer") - nil))) - -(define-obsolete-function-alias 'ess-list-object-completions #'ess-complete-object-name "ESS 19.04") - -;; This one is needed for R <= 2.6.x -- hence *not* obsoleting it -(defun ess-internal-complete-object-name () - "Perform completion on `ess-language' object preceding point. -The object is compared against those objects known by -`ess-get-object-list' and any additional characters up to ambiguity are -inserted. Completion only works on globally-known objects (including -elements of attached data frames), and thus is most suitable for -interactive `command-line' entry, and not so much for function editing -since local objects (e.g. argument names) aren't known. - -Use \\[ess-resynch] to re-read the names of the attached directories. -This is done automatically (and transparently) if a directory is -modified (S only!), so the most up-to-date list of object names is always -available. However attached dataframes are *not* updated, so this -command may be necessary if you modify an attached dataframe." - (ess-make-buffer-current) - (if (memq (char-syntax (preceding-char)) '(?w ?_)) - (let* ((comint-completion-addsuffix nil) - (bounds (ess-bounds-of-symbol)) - (beg (car bounds)) - (end (cdr bounds)) - (full-prefix (buffer-substring beg end)) - (pattern full-prefix) - ;; See if we're indexing a list with `$' - (listname (if (string-match "\\(.+\\)\\$\\(\\(\\sw\\|\\s_\\)*\\)$" - full-prefix) - (progn - (setq pattern - (if (not (match-beginning 2)) "" - (substring full-prefix - (match-beginning 2) - (match-end 2)))) - (substring full-prefix (match-beginning 1) - (match-end 1))))) - ;; are we trying to get a slot via `@' ? - (classname (if (string-match "\\(.+\\)@\\(\\(\\sw\\|\\s_\\)*\\)$" - full-prefix) - (progn - (setq pattern - (if (not (match-beginning 2)) "" - (substring full-prefix - (match-beginning 2) - (match-end 2)))) - (ess-write-to-dribble-buffer - (format "(ess-C-O-Name : slots..) : patt=%s" - pattern)) - (substring full-prefix (match-beginning 1) - (match-end 1))))) - (components (if listname - (ess-object-names listname) - (if classname - (ess-slot-names classname) - ;; Default case: It hangs here when - ;; options(error=recover) : - (ess-get-object-list ess-current-process-name))))) - ;; always return a non-nil value to prevent history expansions - (or (completion-in-region beg end components) 'none)))) - -(defun ess-r-get-rcompletions (&optional start end prefix allow-3-dots) - "Call R internal completion utilities (rcomp) for possible completions. -Optional START and END delimit the entity to complete, default to -bol and point. If PREFIX is given, perform completion on -PREFIX. First element of the returned list is the completion -token. Needs version of R >= 2.7.0." - (let* ((start (or start - (if prefix - 0 - (save-excursion (comint-bol nil) (point))))) - (end (or end (if prefix (length prefix) (point)))) - (prefix (or prefix (buffer-substring start end))) - ;; (opts1 (if no-args "op<-rc.options(args=FALSE)" "")) - ;; (opts2 (if no-args "rc.options(op)" "")) - (call1 (format ".ess_get_completions(\"%s\", %d, \"%s\")" - (ess-quote-special-chars prefix) - (- end start) - ess-R-argument-suffix)) - (cmd (if allow-3-dots - (concat call1 "\n") - (concat "local({ r <- " call1 "; r[r != '...='] })\n")))) - (ess-get-words-from-vector cmd))) - -(defun ess-r-complete-object-name () - "Completion in R via R's completion utilities (formerly 'rcompgen'). -To be used instead of ESS' completion engine for R versions >= 2.7.0." - (let ((possible-completions (ess-r-get-rcompletions)) - token-string) - (when possible-completions - (setq token-string (pop possible-completions)) - (or (completion-in-region (- (point) (length token-string)) - (point) - possible-completions) - 'none)))) - -(defvar ess--cached-sp-objects nil) - -(defun ess--get-cached-completions (prefix &optional _point) - (if (string-match-p "[]:$@[]" prefix) - ;; call proc for objects - (cdr (ess-r-get-rcompletions nil nil prefix)) - ;; else, get cached list of objects - (with-ess-process-buffer 'no-error ;; use proc buf alist - (ess-when-new-input last-cached-completions - (if (and ess--cached-sp-objects - (not (process-get *proc* 'sp-for-ac-changed?))) - ;; if global cache is already there, only re-read local .GlobalEnv - (progn - (unless ess-sl-modtime-alist - ;; initialize if empty - (setq ess-sl-modtime-alist '((".GlobalEnv" nil)))) - ;; fixme: Make adaptive. Not on all remotes are slow; For lots of - ;; objects in .GlobalEnv,locals could also be slow. - (unless (file-remote-p default-directory) - (ess-extract-onames-from-alist ess-sl-modtime-alist 1 'force))) - (if ess--cached-sp-objects - (ess-get-modtime-list 'ess--cached-sp-objects 'exclude-first) - (ess-get-modtime-list) - (setq ess--cached-sp-objects (cdr ess-sl-modtime-alist))) - ;; reread new package, but not rda, much faster and not needed anyways - (process-put *proc* 'sp-for-ac-changed? nil))) - (apply 'append - (cl-cddar ess-sl-modtime-alist) ; .GlobalEnv - (mapcar 'cddr ess--cached-sp-objects))))) - - -;;; ARGUMENTS - -(defvar ess-r--funargs-pre-cache - '(("plot" - (("graphics") - (("x" . "") ("y" . "NULL") ("type" . "p") ("xlim" . "NULL") ("ylim" . "NULL") ("log" . "") ("main" . "NULL") ("sub" . "NULL") ("xlab" . "NULL") ("ylab" . "NULL") - ("ann" . "par(\"ann\")") ("axes" . "TRUE") ("frame.plot" . "axes") ("panel.first" . "NULL") ("panel.last" . "NULL") ("asp" . "NA") ("..." . "")) - ("x" "y" "..." "ci" "type" "xlab" "ylab" "ylim" "main" "ci.col" "ci.type" "max.mfrow" "ask" "mar" "oma" "mgp" "xpd" "cex.main" "verbose" "scale" "xlim" "log" "sub" "ann" "axes" "frame.plot" - "panel.first" "panel.last" "asp" "center" "edge.root" "nodePar" "edgePar" "leaflab" "dLeaf" "xaxt" "yaxt" "horiz" - "zero.line" "verticals" "col.01line" "pch" "legend.text" "formula" "data" "subset" "to" "from" "newpage" "vp" "labels" - "hang" "freq" "density" "angle" "col" "border" "lty" "add" "predicted.values" "intervals" "separator" "col.predicted" - "col.intervals" "col.separator" "lty.predicted" "lty.intervals" "lty.separator" "plot.type" "main2" "par.fit" "grid" - "panel" "cex" "dimen" "abbrev" "which" "caption" "sub.caption" "id.n" "labels.id" "cex.id" "qqline" "cook.levels" - "add.smooth" "label.pos" "cex.caption" "rows" "levels" "conf" "absVal" "ci.lty" "xval" "do.points" "col.points" "cex.points" - "col.hor" "col.vert" "lwd" "set.pars" "range.bars" "col.range" "xy.labels" "xy.lines" "nc" "yax.flip" "mar.multi" "oma.multi"))) - ("print" - (("base") - (("x" . "") ("digits" . "NULL") ("quote" . "TRUE") ("na.print" . "NULL") ("print.gap" . "NULL") ("right" . "FALSE") ("max" . "NULL") ("useSource" . "TRUE") ("..." . "")) - ("x" "..." "digits" "signif.stars" "intercept" "tol" "se" "sort" "verbose" "indent" "style" ".bibstyle" "prefix" "vsep" "minlevel" "quote" "right" "row.names" "max" "na.print" "print.gap" - "useSource" "diag" "upper" "justify" "title" "max.levels" "width" "steps" "showEnv" "newpage" "vp" "cutoff" "max.level" "give.attr" "units" "abbrCollate" "print.x" "deparse" "locale" "symbolic.cor" - "loadings" "zero.print" "calendar")))) - "Alist of cached arguments for time consuming functions.") - - -;;; HELP - -(defun ess-r-get-object-help-string (sym) - "Help string for ac." - (let ((proc (ess-get-next-available-process))) - (if (null proc) - "No free ESS process found" - (let ((buf (get-buffer-create " *ess-command-output*"))) - (when (string-match ":+\\(.*\\)" sym) - (setq sym (match-string 1 sym))) - (with-current-buffer (process-buffer proc) - (ess-with-current-buffer buf - (ess--flush-help-into-current-buffer sym nil))) - (with-current-buffer buf - (ess-help-underline) - (goto-char (point-min)) - (buffer-string)))))) - -(defun ess-r-get-arg-help-string (sym &optional proc) - "Help string for ac." - (setq sym (replace-regexp-in-string " *= *\\'" "" sym)) - (let ((proc (or proc (ess-get-next-available-process)))) - (if (null proc) - "No free ESS process found" - (let ((fun (car ess--fn-name-start-cache))) - (with-current-buffer (ess-command (format ".ess_arg_help('%s','%s')\n" sym fun) - nil nil nil nil proc) - (goto-char (point-min)) - (forward-line) - (buffer-substring-no-properties (point) (point-max))))))) - - -;;; COMPANY -;;; https://company-mode.github.io/ - -(defun company-R-objects (command &optional arg &rest ignored) - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-R-objects)) - (prefix (unless (ess-inside-string-or-comment-p) - (let ((start (ess-symbol-start))) - (when start - (buffer-substring-no-properties start (point)))))) - (candidates (let ((proc (ess-get-next-available-process))) - (when proc - (with-current-buffer (process-buffer proc) - (all-completions arg (ess--get-cached-completions arg)))))) - (doc-buffer (company-doc-buffer (ess-r-get-object-help-string arg))))) - -(defun company-R-args (command &optional arg &rest ignored) - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-R-args)) - (prefix (unless (ess-inside-string-or-comment-p) - (let ((start (ess-arg-start))) - (when start - (let ((prefix (buffer-substring-no-properties start (point)))) - (if ess-company-arg-prefix-length - (cons prefix (>= (length prefix) - ess-company-arg-prefix-length)) - prefix)))))) - (candidates (let* ((proc (ess-get-next-available-process)) - (args (delete "..." (nth 2 (ess-function-arguments - (car ess--fn-name-start-cache) proc)))) - (args (mapcar (lambda (a) (concat a ess-R-argument-suffix)) - args))) - (all-completions arg args))) - (meta (let ((proc (ess-get-next-available-process))) - (when (and proc - (with-current-buffer (process-buffer proc) - (not (file-remote-p default-directory)))) - ;; fixme: ideally meta should be fetched with args - (let ((doc (ess-r-get-arg-help-string arg proc))) - (replace-regexp-in-string "^ +\\| +$" "" - (replace-regexp-in-string "[ \t\n]+" " " doc)))))) - (sorted t) - (require-match 'never) - (doc-buffer (company-doc-buffer (ess-r-get-arg-help-string arg))))) - -(defun company-R-library (command &optional arg &rest ignored) - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-R-library)) - (prefix (and (member (car (ess--fn-name-start)) - '("library" "require")) - (let ((start (ess-symbol-start))) - (and start (buffer-substring start (point)))))) - (candidates (all-completions arg (ess-installed-packages))) - (annotation "") - (duplicates nil) - (sorted t))) - -;; FIXME: There's a lot of overlap between `ess-r-package-completion' -;; and `company-R-library'. Can we merge them somehow? -(defun ess-r-package-completion () - "Return installed packages if in a call to library or require. -Return format suitable for `completion-at-point-functions'." - (when (member (car (ess--fn-name-start)) - '("library" "require")) - (list (ess-symbol-start) - (point) - (ess-installed-packages) - :annotation-function - (lambda (_) " ")))) - - -;;; AC SOURCES -;;; http://cx4a.org/software/auto-complete/index.html -;; auto-complete is de-facto unmaintained, users should switch to `company-mode'. - -(defvar ac-source-R - '((prefix . ess-ac-start) - ;; (requires . 0) ::) - (candidates . ess-ac-candidates) - ;; (action . ess-ac-action-args) ;; interfere with ac-fallback mechanism on RET (which is extremely annoying in inferior buffers) - (document . ess-ac-help)) - "Combined ad-completion source for R function arguments and R objects.") -(make-obsolete-variable 'ac-source-R "Use company-mode instead" "ESS 19.04") - -(defun ess-ac-start () - (when (ess-process-live-p) - (or (ess-arg-start) - (ess-symbol-start)))) -(make-obsolete-variable 'ess-ac-start "Use company-mode instead" "ESS 19.04") - -(defun ess-ac-candidates () - "OBJECTS + ARGS." - (let ((args (with-no-warnings - ;; suppress obsolete warnings - (ess-ac-args)))) - ;; sort of intrusive but right - (if (and ac-auto-start - (< (length ac-prefix) ac-auto-start)) - args - (if args - (append args (with-no-warnings - ;; suppress obsolete warnings - (ess-ac-objects t))) - (with-no-warnings - ;; suppress obsolete warnings - (ess-ac-objects)))))) -(make-obsolete-variable 'ess-ac-candidates "Use company-mode instead" "ESS 19.04") - -(defun ess-ac-help (sym) - (if (string-match-p "= *\\'" sym) - (ess-r-get-arg-help-string sym) - (ess-r-get-object-help-string sym))) -(make-obsolete-variable 'ess-ac-help "Use company-mode instead" "ESS 19.04") - -;; OBJECTS -(defvar ac-source-R-objects - '((prefix . ess-symbol-start) - ;; (requires . 2) - (candidates . ess-ac-objects) - (document . ess-r-get-object-help-string)) - "Auto-completion source for R objects.") -(make-obsolete-variable 'ac-source-R-objects "Use company-mode instead" "ESS 19.04") - -(defun ess-ac-objects (&optional no-kill) - "Get all cached objects." - (declare (obsolete "Use company-mode instead" "ESS 19.04")) - (let ((aprf ac-prefix)) - (when (and aprf (ess-process-live-p)) - (unless no-kill ;; workaround - (kill-local-variable 'ac-use-comphist)) - (ess--get-cached-completions aprf ac-point)))) - -;; ARGS -(defvar ac-source-R-args - '((prefix . ess-arg-start) - ;; (requires . 0) - (candidates . ess-ac-args) - ;; (action . ess-ac-action-args) - (document . ess-r-get-arg-help-string)) - "Auto-completion source for R function arguments.") -(make-obsolete-variable 'ac-source-R-args "Use company-mode instead" "ESS 19.04") - -(defun ess-ac-args () - "Get the args of the function when inside parentheses." - (declare (obsolete "Use company-mode-instead" "ESS 19.04")) - (when (and ess--fn-name-start-cache ;; set in a call to ess-arg-start - (ess-process-live-p)) - (let ((args (nth 2 (ess-function-arguments (car ess--fn-name-start-cache))))) - (if args - (setq-local ac-use-comphist nil) - (kill-local-variable 'ac-use-comphist)) - (delete "..." args) - (mapcar (lambda (a) (concat a ess-R-argument-suffix)) - args)))) - -(provide 'ess-r-completion) - -;;; ess-r-completion.el ends here diff --git a/elpa/ess-20191014.1343/ess-r-flymake.el b/elpa/ess-20191014.1343/ess-r-flymake.el deleted file mode 100644 index dc00a3a1..00000000 --- a/elpa/ess-20191014.1343/ess-r-flymake.el +++ /dev/null @@ -1,254 +0,0 @@ -;;; ess-r-flymake.el --- A ess-r Flymake backend -*- lexical-binding: t; -*- -;; -;; Copyright (C) 2018 J. Alexander Branham (alex DOT branham AT gmail DOT com) -;; Copyright (C) 2018 ESS-core team -;; Maintainer: ESS-core -;; -;; This file is NOT part of GNU Emacs. -;; -;; This is free software; you can redistribute it and/or modify it under -;; the terms of the GNU General Public License as published by the Free -;; Software Foundation; either version 3, or (at your option) any later -;; version. -;; -;; This is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -;; for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -;; MA 02110-1301 USA. -;; -;;; Commentary: -;; -;; Flymake is the built-in Emacs package that supports on-the-fly -;; syntax checking. This file adds support for this in ess-r-mode by -;; relying on the lintr package, available on CRAN and currently -;; hosted at https://github.com/jimhester/lintr. -;; -;; It is enabled by default. -;; -;;; Code: - -(eval-when-compile (require 'cl-lib)) -(require 'ess-inf) -(require 'flymake) - -;; Appease the byte compiler for Emacs 25. Remove after dropping -;; support for Emacs 25. -(declare-function flymake-diag-region "flymake") -(declare-function flymake-make-diagnostic "flymake") -(declare-function flymake--overlays "flymake") - -(defcustom ess-r-flymake-linters - '("closed_curly_linter = NULL" - "commas_linter = NULL" - "commented_code_linter = NULL" - "infix_spaces_linter = NULL" - "line_length_linter = NULL" - "object_length_linter = NULL" - "object_name_linter = NULL" - "object_usage_linter = NULL" - "open_curly_linter = NULL" - "pipe_continuation_linter = NULL" - "single_quotes_linter = NULL" - "spaces_inside_linter = NULL" - "spaces_left_parentheses_linter = NULL" - "trailing_blank_lines_linter = NULL" - "trailing_whitespace_linter = NULL") - "Default linters to use. -Can be either a string with R expression to be used as -is (e.g. 'lintr::default_linters'). Or a list of strings where -each element is passed as argument to 'lintr::with_defaults'." - :group 'ess-R - :type '(choice string (repeat string)) - :package-version '(ess . "18.10")) - -(defcustom ess-r-flymake-lintr-cache t - "If non-nil, cache lintr results." - :group 'ess-R - :type 'boolean - :package-version '(ess . "18.10")) - -(defvar-local ess-r--flymake-proc nil) - -(defvar-local ess-r--lintr-file nil - "Location of the .lintr file for this buffer.") - -(defvar ess-r--flymake-def-linter - (replace-regexp-in-string - "[\n\t ]+" " " - "esslint <- function(str, ...) { - if (!suppressWarnings(require(lintr, quietly=T))) { - cat('@@error: @@`lintr` package not installed') - } else { - if (packageVersion('lintr') <= '1.0.3') { - cat('@@error: @@Need `lintr` version > v1.0.3') - } else { - tryCatch(lintr::lint(commandArgs(TRUE), ...), - error = function(e) { - cat('@@warning: @@', e) - }) - } - } -};")) - -(defun ess-r--find-lintr-file () - "Return the absolute path to the .lintr file. -Check first the current directory, then the project root, then -the user's home directory. Return nil if we couldn't find a .lintr file." - (let ((cur-dir-file (expand-file-name ".lintr" default-directory)) - (ess-proj-file (and (fboundp 'ess-r-package-project) - (ess-r-package-project) - (expand-file-name ".lintr" (cdr (ess-r-package-project))))) - (proj-file (and (project-current) - (project-roots (project-current)) - (expand-file-name ".lintr" (car (project-roots (project-current)))))) - (home-file (expand-file-name ".lintr" (getenv "HOME")))) - (cond (;; current directory - (file-readable-p cur-dir-file) - cur-dir-file) - ;; Project root according to `ess-r-package-project' - ((and ess-proj-file - (file-readable-p ess-proj-file)) - ess-proj-file) - ;; Project root according to `project-roots' - ((and proj-file - (file-readable-p proj-file))) - ;; Home directory - ((file-readable-p home-file) - home-file)))) - -(defun ess-r--flymake-linters () - "If `ess-r-flymake-linters' is a string, use that. -Otherwise, construct a string to pass to lintr::with_defaults." - (replace-regexp-in-string - "[\n\t ]+" " " - (if (stringp ess-r-flymake-linters) - ess-r-flymake-linters - (concat "lintr::with_defaults(" - (mapconcat #'identity - ess-r-flymake-linters - ", ") - ")")))) - -(defun ess-r--flymake-msg-type (str) - "Transform STR into log level." - (cond ((string= str "error: ") :error) - ((string= str "warning: ") :warning) - ((string= str "style: ") :note) - (t (error "Invalid msg type %s" str)))) - -(defun ess-r--flymake-check-errors () - "Check for critical errors and return non-nil if such occurred." - (goto-char (point-min)) - (when (re-search-forward "@@\\(\\(error\\|warning\\): \\)@@" nil t) - (let ((type (ess-r--flymake-msg-type (match-string 1))) - (msg (buffer-substring-no-properties (match-end 0) (point-max)))) - (flymake-log type msg) - (eq type :error)))) - -(defun ess-r--flymake-parse-output (msg-buffer src-buffer report-fn) - "Parse the content of MSG-BUFFER for lint locations. -SRC-BUFFER is the original source buffer. Collect all messages -into a list and call REPORT-FN on it." - (with-current-buffer msg-buffer - (if (ess-r--flymake-check-errors) - (with-current-buffer src-buffer - ;; we are in the sentinel here; don't throw but remove our hook instead - (remove-hook 'flymake-diagnostic-functions 'ess-r-flymake t)) - (goto-char (point-min)) - (cl-loop - while (search-forward-regexp - ;; Regex to match the output lint() gives us. - (rx line-start ":" - ;; row - (group-n 1 (one-or-more num)) ":" - ;; column - (group-n 2 (one-or-more num)) ": " - ;; type - (group-n 3 (| "style: " "warning: " "error: ")) - ;; msg - (group-n 4 (one-or-more not-newline)) line-end) - nil t) - for msg = (match-string 4) - for (beg . end) = (let ((line (string-to-number (match-string 1))) - (col (string-to-number (match-string 2)))) - (flymake-diag-region src-buffer line col)) - for type = (ess-r--flymake-msg-type (match-string 3)) - collect (flymake-make-diagnostic src-buffer beg end type msg) - into diags - finally (funcall report-fn diags))))) - -(defun ess-r-flymake (report-fn &rest _args) - "A Flymake backend for ESS-R modes. Relies on the lintr package. -REPORT-FN is flymake's callback function." - (unless (executable-find inferior-ess-r-program) - (error "Cannot find program '%s'" inferior-ess-r-program)) - ;; Kill the process if earlier check was found. The sentinel of the earlier - ;; check will detect this. - (when (process-live-p ess-r--flymake-proc) - (kill-process ess-r--flymake-proc)) - (if (and (eql ess-use-flymake 'process) - (not (ess-process-live-p))) - (progn - (funcall report-fn nil) - (mapc #'delete-overlay (flymake--overlays))) - (let ((src-buffer (current-buffer))) - (setq ess-r--flymake-proc - (make-process - :name "ess-r-flymake" :noquery t :connection-type 'pipe - :buffer (generate-new-buffer " *ess-r-flymake*") - :command (list inferior-R-program - "--no-save" "--no-restore" "--no-site-file" "--no-init-file" "--slave" - "-e" (concat - (when ess-r--lintr-file - (concat "options(lintr.linter_file = \"" ess-r--lintr-file "\");")) - ess-r--flymake-def-linter - ;; commandArgs(TRUE) returns everything after - ;; --args as a character vector - "esslint(commandArgs(TRUE)" - (unless ess-r--lintr-file - (concat ", linters = " (ess-r--flymake-linters))) - (when ess-r-flymake-lintr-cache - ", cache = TRUE") - ")") - "--args" (buffer-substring-no-properties - (point-min) (point-max))) - :sentinel - (lambda (proc _event) - (cond - ((eq 'exit (process-status proc)) - (unwind-protect - (if (eq proc (buffer-local-value 'ess-r--flymake-proc src-buffer)) - (ess-r--flymake-parse-output (process-buffer proc) src-buffer report-fn) - (flymake-log :warning "Canceling obsolete check %s" proc)) - (kill-buffer (process-buffer proc)))) - ((not (eq 'run (process-status proc))) - (kill-buffer (process-buffer proc)))))))))) - -(defun ess-r-setup-flymake () - "Setup flymake for ESS. -Activate flymake only if `ess-use-flymake' is non-nil." - (when ess-use-flymake - (when (< emacs-major-version 26) - (error "ESS-flymake requires Emacs version 26 or later")) - (when (string= "R" ess-dialect) - (setq ess-r--lintr-file (ess-r--find-lintr-file)) - (add-hook 'flymake-diagnostic-functions #'ess-r-flymake nil t) - ;; Try not to enable flymake if flycheck is already running: - (unless (bound-and-true-p flycheck-mode) - (flymake-mode))))) - -;; Enable flymake in Emacs 26+ -(when (<= 26 emacs-major-version) - (if (eval-when-compile (<= 26 emacs-major-version)) - (add-hook 'ess-r-mode-hook #'ess-r-setup-flymake) - (when ess-use-flymake - (display-warning 'ess "ESS was compiled with older version of Emacs;\n `ess-r-flymake' won't be available")))) - -(provide 'ess-r-flymake) - -;;; ess-r-flymake.el ends here diff --git a/elpa/ess-20191014.1343/ess-r-mode.el b/elpa/ess-20191014.1343/ess-r-mode.el deleted file mode 100644 index 64aed8e2..00000000 --- a/elpa/ess-20191014.1343/ess-r-mode.el +++ /dev/null @@ -1,2784 +0,0 @@ -;;; ess-r-mode.el --- R customization - -;; Copyright (C) 1997--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2017 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: A.J. Rossini -;; Created: 12 Jun 1997 -;; Maintainer: ESS-core - -;; Keywords: languages, statistics - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This file defines all the R customizations for ESS. See ess-s-lang.el -;; for general S language customizations. - -;;; Code: - -(eval-when-compile - (require 'subr-x)) -(require 'cl-lib) -(require 'compile) -(require 'ess-mode) -(require 'ess-help) -(require 'ess-s-lang) -(require 'ess-roxy) -(require 'ess-r-completion) -(require 'ess-r-syntax) -(require 'ess-r-package) -(require 'ess-trns) -(require 'ess-r-xref) -(when (>= emacs-major-version 26) (require 'ess-r-flymake)) ; Flymake rewrite in Emacs 26 - -(declare-function ess-rdired "ess-rdired" ()) - -(define-obsolete-variable-alias 'R-mode-hook 'ess-r-mode-hook "19.04") -(defcustom ess-r-mode-hook nil - "Hook run when entering `ess-r-mode'." - :options '(electric-layout-local-mode) - :type 'hook - :group 'ess-R) - - -(defcustom ess-r-fetch-ESSR-on-remotes nil - "If non-nil, fetch ESSR from the GitHub repository. -Otherwise source from local ESS installation. When 'ess-remote, -fetch only with `ess-remote'. When t, always fetch from remotes. -Change this variable when loading ESSR code on remotes fails -systematically. - -Fetching happens once per new ESSR version. The archive is stored -in ~/.config/ESSR/ folder. You can download and place it there -manually if the remote has restricted network access." - :type '(choice (const nil :tag "Never") - (const 'ess-remote :tag "With ess-remote only") - (const t :tag "Always")) - :group 'ess-R) - -;; Silence the byte compiler -(defvar add-log-current-defun-header-regexp) - -;; TODO: Refactor so as to not rely on dynamic scoping. After that -;; refactor, also remove the file-local-variable byte-compile-warnings -;; (not lexical) at the bottom. -(defvar block) -(defvar containing-sexp) -(defvar indent-point) -(defvar infinite) -(defvar last-newline) -(defvar last-pos) -(defvar offset) -(defvar prefix-break) -(defvar prev-containing-sexp) -(defvar start-pos) -(defvar style) -(defvar type) - -(define-obsolete-variable-alias 'ess-r-versions 'ess-r-runner-prefixes "ESS 19.04") -(defcustom ess-r-runner-prefixes - (let ((r-ver '("R-1" "R-2" "R-3" "R-devel" "R-patched"))) - (if (eq system-type 'darwin) (append r-ver '("R32" "R64")) r-ver)) - "List of partial strings for versions of R to access within ESS. -Each string specifies the start of a filename. If a filename -beginning with one of these strings is found on variable -`exec-path', a command for that version of R is made available. -For example, if the file \"R-1.8.1\" is found and this variable -includes the string \"R-1\", a function called `R-1.8.1' will be -available to run that version of R. If duplicate versions of the -same program are found (which happens if the same path is listed -on variable `exec-path' more than once), they are ignored by -calling `delete-dups'. Set this variable to nil to disable -searching for other versions of R. Setting this variable directly -does not take effect; use either \\[customize-option] or set the -value by using `ess-r-runners-reset'." - :group 'ess-R - :type '(repeat string) - :set #'ess-r-runners-reset - ;; Use `custom-initialize-default' since we call - ;; `ess-r-define-runners' at the end of this file directly. - :initialize #'custom-initialize-default) - - - -;;*;; Mode definition - -;;;*;;; UI (Keymaps / Menus) -(defvar ess-dev-map - (let (ess-dev-map) - (define-prefix-command 'ess-dev-map) - (define-key ess-dev-map "\C-s" #'ess-r-set-evaluation-env) - (define-key ess-dev-map "s" #'ess-r-set-evaluation-env) - (define-key ess-dev-map "T" #'ess-toggle-tracebug) - (define-key ess-dev-map "\C-l" #'ess-r-devtools-load-package) - (define-key ess-dev-map "l" #'ess-r-devtools-load-package) - (define-key ess-dev-map "`" #'ess-show-traceback) - (define-key ess-dev-map "~" #'ess-show-call-stack) - (define-key ess-dev-map "\C-w" #'ess-watch) - (define-key ess-dev-map "w" #'ess-watch) - (define-key ess-dev-map "\C-d" #'ess-debug-flag-for-debugging) - (define-key ess-dev-map "d" #'ess-debug-flag-for-debugging) - (define-key ess-dev-map "\C-u" #'ess-debug-unflag-for-debugging) - (define-key ess-dev-map "u" #'ess-debug-unflag-for-debugging) - (define-key ess-dev-map "" #'ess-debug-unflag-for-debugging) - (define-key ess-dev-map "\C-b" #'ess-bp-set) - (define-key ess-dev-map "b" #'ess-bp-set) - (define-key ess-dev-map "" #'ess-bp-set-conditional) - (define-key ess-dev-map "B" #'ess-bp-set-conditional) - (define-key ess-dev-map "\C-L" #'ess-bp-set-logger) - (define-key ess-dev-map "L" #'ess-bp-set-logger) - (define-key ess-dev-map "\C-o" #'ess-bp-toggle-state) - (define-key ess-dev-map "o" #'ess-bp-toggle-state) - (define-key ess-dev-map "\C-k" #'ess-bp-kill) - (define-key ess-dev-map "k" #'ess-bp-kill) - (define-key ess-dev-map "\C-K" #'ess-bp-kill-all) - (define-key ess-dev-map "K" #'ess-bp-kill-all) - (define-key ess-dev-map "\C-n" #'ess-bp-next) - (define-key ess-dev-map "n" #'ess-bp-next) - (define-key ess-dev-map "i" #'ess-debug-goto-input-event-marker) - (define-key ess-dev-map "I" #'ess-debug-goto-input-event-marker) - (define-key ess-dev-map "\C-p" #'ess-bp-previous) - (define-key ess-dev-map "p" #'ess-bp-previous) - (define-key ess-dev-map "\C-e" #'ess-debug-toggle-error-action) - (define-key ess-dev-map "e" #'ess-debug-toggle-error-action) - (define-key ess-dev-map "0" #'ess-electric-selection) - (define-key ess-dev-map "1" #'ess-electric-selection) - (define-key ess-dev-map "2" #'ess-electric-selection) - (define-key ess-dev-map "3" #'ess-electric-selection) - (define-key ess-dev-map "4" #'ess-electric-selection) - (define-key ess-dev-map "5" #'ess-electric-selection) - (define-key ess-dev-map "6" #'ess-electric-selection) - (define-key ess-dev-map "7" #'ess-electric-selection) - (define-key ess-dev-map "8" #'ess-electric-selection) - (define-key ess-dev-map "9" #'ess-electric-selection) - (define-key ess-dev-map "?" #'ess-tracebug-show-help) - ess-dev-map) - "Keymap for commands related to development and debugging.") - -(defvar ess-r-package-check-map - (let (ess-r-package-check-map) - (define-prefix-command 'ess-r-package-check-map) - (define-key ess-r-package-check-map "\C-c" #'ess-r-devtools-check-package) - (define-key ess-r-package-check-map "c" #'ess-r-devtools-check-package) - (define-key ess-r-package-check-map "\C-w" #'ess-r-devtools-check-with-winbuilder) - (define-key ess-r-package-check-map "w" #'ess-r-devtools-check-with-winbuilder) - (define-key ess-r-package-check-map "h" #'ess-r-rhub-check-package) - ess-r-package-check-map) - "Keymap for R package checks.") - -(defvar ess-r-package-dev-map - (let (ess-r-package-dev-map) - (define-prefix-command 'ess-r-package-dev-map) - (define-key ess-r-package-dev-map "\C-s" #'ess-r-set-evaluation-env) - (define-key ess-r-package-dev-map "s" #'ess-r-set-evaluation-env) - (define-key ess-r-package-dev-map "\C-a" #'ess-r-devtools-execute-command) - (define-key ess-r-package-dev-map "a" #'ess-r-devtools-execute-command) - (define-key ess-r-package-dev-map "\C-e" #'ess-r-devtools-execute-command) - (define-key ess-r-package-dev-map "e" #'ess-r-devtools-execute-command) - (define-key ess-r-package-dev-map "\C-b" #'ess-r-devtools-build) - (define-key ess-r-package-dev-map "b" #'ess-r-devtools-build) - (define-key ess-r-package-dev-map "\C-c" 'ess-r-package-check-map) - (define-key ess-r-package-dev-map "c" 'ess-r-package-check-map) - (define-key ess-r-package-dev-map "\C-d" #'ess-r-devtools-document-package) - (define-key ess-r-package-dev-map "d" #'ess-r-devtools-document-package) - (define-key ess-r-package-dev-map "g" #'ess-r-devtools-install-github) - (define-key ess-r-package-dev-map "\C-i" #'ess-r-devtools-install-package) - (define-key ess-r-package-dev-map "i" #'ess-r-devtools-install-package) - (define-key ess-r-package-dev-map "\C-l" #'ess-r-devtools-load-package) - (define-key ess-r-package-dev-map "l" #'ess-r-devtools-load-package) - (define-key ess-r-package-dev-map "\C-t" #'ess-r-devtools-test-package) - (define-key ess-r-package-dev-map "t" #'ess-r-devtools-test-package) - (define-key ess-r-package-dev-map "\C-u" #'ess-r-devtools-unload-package) - (define-key ess-r-package-dev-map "u" #'ess-r-devtools-unload-package) - ess-r-package-dev-map)) - -(easy-menu-define ess-roxygen-menu nil - "Roxygen submenu." - '("Roxygen" - :visible (and ess-dialect (string-match "^R" ess-dialect)) - ["Update/Generate Template" ess-roxy-update-entry t] - ["Preview Rd" ess-roxy-preview-Rd t] - ["Preview HTML" ess-roxy-preview-HTML t] - ["Preview text" ess-roxy-preview-text t] - ["Hide all" ess-roxy-hide-all t] - ["Toggle Roxygen Prefix" ess-roxy-toggle-roxy-region t])) - -(easy-menu-define ess-tracebug-menu nil - "Tracebug submenu." - '("Tracebug" - :visible (and ess-dialect (string-match "^R" ess-dialect)) - ;; :enable ess-local-process-name - ["Active?" ess-toggle-tracebug - :style toggle - :selected (or (and (ess-process-live-p) - (ess-process-get 'tracebug)) - ess-use-tracebug)] - ["Show traceback" ess-show-traceback (ess-process-live-p)] - ["Show call stack" ess-show-call-stack (ess-process-live-p)] - ["Watch" ess-watch (and (ess-process-live-p) - (ess-process-get 'tracebug))] - ["Error action cycle" ess-debug-toggle-error-action (and (ess-process-live-p) - (ess-process-get 'tracebug))] - "----" - ["Flag for debugging" ess-debug-flag-for-debugging ess-local-process-name] - ["Unflag for debugging" ess-debug-unflag-for-debugging ess-local-process-name] - "----" - ["Set BP" ess-bp-set t] - ["Set conditional BP" ess-bp-set-conditional t] - ["Set logger BP" ess-bp-set-logger t] - ["Kill BP" ess-bp-kill t] - ["Kill all BPs" ess-bp-kill-all t] - ["Next BP" ess-bp-next t] - ["Previous BP" ess-bp-previous t] - "-----" - ["About" ess-tracebug-show-help t])) - -(easy-menu-define ess-r-package-menu nil - "Package Development submenu." - '("Package development" - :visible (and ess-dialect (string-match "^R" ess-dialect)) - ["Active?" ess-r-package-mode - :style toggle - :selected ess-r-package-mode] - ["Select package for evaluation" ess-r-set-evaluation-env t])) - -(easy-menu-add-item ess-mode-menu nil ess-roxygen-menu "end-dev") -(easy-menu-add-item ess-mode-menu nil ess-r-package-menu "end-dev") -(easy-menu-add-item ess-mode-menu nil ess-tracebug-menu "end-dev") -(easy-menu-add-item inferior-ess-mode-menu nil ess-r-package-menu "end-dev") -(easy-menu-add-item inferior-ess-mode-menu nil ess-tracebug-menu "end-dev") - -(defvar ess-r-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-=") #'ess-cycle-assign) - (define-key map "\M-?" #'ess-complete-object-name) - (define-key map (kbd "C-c C-.") 'ess-rutils-map) - map)) - -(defvar ess-r-mode-syntax-table - (let ((table (copy-syntax-table S-syntax-table))) - ;; Letting Emacs treat backquoted names and %ops% as strings solves - ;; many problems with regard to nested strings and quotes - (modify-syntax-entry ?` "\"" table) - (modify-syntax-entry ?% "\"" table) - ;; Underscore is valid in R symbols - (modify-syntax-entry ?_ "_" table) - (modify-syntax-entry ?: "." table) - (modify-syntax-entry ?@ "." table) - (modify-syntax-entry ?$ "." table) - table) - "Syntax table for `ess-r-mode'.") - - -(defvar ess-r-completion-syntax-table - (let ((table (copy-syntax-table ess-r-mode-syntax-table))) - (modify-syntax-entry ?. "_" table) - (modify-syntax-entry ?: "_" table) - (modify-syntax-entry ?$ "_" table) - (modify-syntax-entry ?@ "_" table) - table) - "Syntax table used for completion and help symbol lookup. -It makes underscores and dots word constituent chars.") - -(defvar ess-r-namespaced-load-verbose t - "Whether to display information on namespaced loading. -When t, loading a file into a namespaced will output information -about which objects are exported and which stay hidden in the -namespace.") - -(defun ess-r-font-lock-syntactic-face-function (state) - (if (nth 3 state) - ;; string case - (let ((string-end (save-excursion - (ess-goto-char (nth 8 state)) - (ess-forward-sexp) - (point)))) - (cond - ((eq (nth 3 state) ?%) - (if (eq (point) (1- string-end)) - (when (cdr (assq 'ess-fl-keyword:operators ess-R-font-lock-keywords)) - 'ess-operator-face) - (if (cdr (assq 'ess-R-fl-keyword:%op% ess-R-font-lock-keywords)) - 'ess-%op%-face - 'default))) - ((save-excursion - (and (cdr (assq 'ess-R-fl-keyword:fun-defs ess-R-font-lock-keywords)) - (ess-goto-char string-end) - (ess-looking-at "<-") - (ess-goto-char (match-end 0)) - (ess-looking-at "function\\b" t))) - font-lock-function-name-face) - ((save-excursion - (and (cdr (assq 'ess-fl-keyword:fun-calls ess-R-font-lock-keywords)) - (ess-goto-char string-end) - (ess-looking-at "("))) - ess-function-call-face) - ((eq (nth 3 state) ?`) - 'default) - (t - font-lock-string-face))) - font-lock-comment-face)) - -(defvar ess-r--non-fn-kwds - '("in" "else" "break" "next" "repeat")) - -(defvar-local ess-r--keyword-regexp nil) -(defun ess-r--find-fl-keyword (limit) - "Search for R keyword and set the match data. -To be used as part of `font-lock-defaults' keywords." - (unless ess-r--keyword-regexp - (let (fn-kwds non-fn-kwds) - (dolist (kw ess-R-keywords) - (if (member kw ess-r--non-fn-kwds) - (push kw non-fn-kwds) - (push kw fn-kwds))) - (setq ess-r--keyword-regexp - (concat "\\(" - (regexp-opt non-fn-kwds 'words) - "\\)\\|\\(" - (regexp-opt fn-kwds 'words) - "\\)")))) - (let (out) - (while (and (not out) - (re-search-forward ess-r--keyword-regexp limit t)) - (save-match-data - (setq out (if (match-beginning 1) - ;; Non-function-like keywords: Always fontified - ;; except for `in` for which we check it's part - ;; of a `for` construct. Ideally we'd check that - ;; other keywords like `break` or `next` are - ;; part of the right syntactic construct but - ;; that requires robust and efficient detection - ;; of complete expressions. - (if (string= (match-string 1) "in") - (save-excursion - (goto-char (match-beginning 1)) - (and (ess-backward-up-list) - (forward-word -1) - (looking-at "for\\s-*("))) - t) - ;; Function-like keywords: check if they are - ;; followed by an open paren - (looking-at "\\s-*("))))) - out)) - -(define-obsolete-variable-alias 'R-customize-alist 'ess-r-customize-alist "ESS 18.10.2") -(defvar ess-r-customize-alist - (append - '((ess-local-customize-alist . 'ess-r-customize-alist) - (ess-dialect . "R") - (ess-suffix . "R") - (ess-traceback-command . ess-r-traceback-command) - (ess-call-stack-command . ess-r-call-stack-command) - (ess-mode-completion-syntax-table . ess-r-completion-syntax-table) - (ess-build-eval-message-function . #'ess-r-build-eval-message) - (ess-dump-filename-template . ess-r-dump-filename-template) - (ess-change-sp-regexp . ess-r-change-sp-regexp) - (ess-help-sec-regex . ess-help-r-sec-regex) - (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) - (ess-function-pattern . ess-r-function-pattern) - (ess-object-name-db-file . "ess-r-namedb.el") - (ess-smart-operators . ess-r-smart-operators) - (inferior-ess-program . inferior-ess-r-program) - (inferior-ess-objects-command . inferior-ess-r-objects-command) - (inferior-ess-search-list-command . "search()\n") - (inferior-ess-help-command . inferior-ess-r-help-command) - (inferior-ess-exit-command . "q()") - (ess-error-regexp-alist . ess-r-error-regexp-alist) - (ess-describe-object-at-point-commands . 'ess-r-describe-object-at-point-commands) - (ess-STERM . "iESS") - (ess-editor . ess-r-editor) - (ess-pager . ess-r-pager)) - S-common-cust-alist) - "Variables to customize for R.") - -(cl-defmethod ess-build-tags-command (&context (ess-dialect "R")) - "Return tags command for R." - "rtags('%s', recursive = TRUE, pattern = '\\\\.[RrSs](rw)?$',ofile = '%s')") - -(defvar ess-r-traceback-command - "local({cat(geterrmessage(), \ -'---------------------------------- \n', \ -fill=TRUE); try(traceback(), silent=TRUE)})\n") - -(defvar ess-r-call-stack-command "traceback(1)\n") - -(defvar ess-r-dump-filename-template - (replace-regexp-in-string - "S$" "R" ess-dump-filename-template-proto)) - -(defvar ess-r-ac-sources - '(ac-source-R)) - -(defvar ess-r-company-backends - '((company-R-library company-R-args company-R-objects :separate))) - -(defconst ess-help-r-sec-regex "^[A-Z][A-Za-z].+:$" - "Reg(ular) Ex(pression) of section headers in help file.") - -(defconst ess-help-r-sec-keys-alist - '((?a . "\\s *Arguments:") - (?d . "\\s *Description:") - (?D . "\\s *Details:") - (?t . "\\s *Details:") - (?e . "\\s *Examples:") - (?n . "\\s *Note:") - (?r . "\\s *References:") - (?s . "\\s *See Also:") - (?u . "\\s *Usage:") - (?v . "\\s *Value[s]?") ; - ) - "Alist of (key . string) pairs for use in help section searching.") - -(defvar ess-r-error-regexp-alist '(R R1 R2 R3 R4 R-recover) - "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.") - -(dolist (l '(;; Takes precedence over R1 below in English locales, and allows spaces in file path - (R "\\(\\(?: at \\|(@\\)\\([^#()\n]+\\)[#:]\\([0-9]+\\)\\)" 2 3 nil 2 1) - ;; valgrind style (stl_numeric.h:183) - (R1 "(\\([^ ):\n]+\\):\\([0-9]+\\)?)" 1 2 nil 2) - (R2 "(\\(\\w+ \\([^())\n]+\\)#\\([0-9]+\\)\\))" 2 3 nil 2 1) - ;; Precedes R4 and allows spaces in file path, Starts at bol or with ": " (patterns 3,4,5,6,9) - (R3 "\\(?:^ *\\|: ?\\)\\([^-+[:digit:] \t\n]:?[^: \t\n]*\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\)?" 1 2 3 2 1) - ;; Don't start with digit; no spaces - (R4 "\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1) - (R-recover " *[0-9]+: +\\([^:\n\t]+?\\)#\\([0-9]+:\\)" 1 2 nil 2 1))) - (cl-pushnew l compilation-error-regexp-alist-alist)) - -(define-obsolete-variable-alias 'ess-r-versions-created 'ess-r-created-runners "ESS 18.10") -(defvar ess-r-created-runners nil - "List of R-versions found from `ess-r-runner-prefixes' on the system.") - - -;;;*;;; Mode init - -(define-obsolete-variable-alias 'ess-R-post-run-hook 'ess-r-post-run-hook "ESS 18.10.2") -(defvar ess-r-post-run-hook nil - "Functions run in process buffer after the initialization of R process.") - -;;;###autoload -(defun run-ess-r (&optional start-args) - "Call 'R', the 'GNU S' system from the R Foundation. -Optional prefix (\\[universal-argument]) allows to set command line arguments, such as ---vsize. This should be OS agnostic. -If you have certain command line arguments that should always be passed -to R, put them in the variable `inferior-R-args'. - -START-ARGS can be a string representing an argument, a list of -such strings, or any other non-nil value. In the latter case, you -will be prompted to enter arguments interactively." - (interactive "P") - (ess-write-to-dribble-buffer ;; for debugging only - (format - "\n(R): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n" - ess-dialect (current-buffer) start-args current-prefix-arg)) - (unless (or (file-remote-p default-directory) - (and ess-startup-directory - (file-remote-p ess-startup-directory)) - ;; TODO: Once we drop Emacs 26 support, can probably - ;; just use the REMOTE argument of `executable-find'. - (executable-find inferior-ess-r-program)) - (display-warning 'ess (format "%s could not be found on the system. Try running `run-ess-r-newest' instead, which searches your system for R." inferior-ess-r-program) :error) - (user-error "%s program not found" inferior-ess-r-program)) - (let* ((r-always-arg - (if (or ess-microsoft-p (eq system-type 'cygwin)) - "--ess " - ;; else: "Unix alike" - (if (not ess-R-readline) "--no-readline "))) - (start-args - (cond ((stringp start-args) - start-args) - ((and start-args - (listp start-args) - (cl-every 'stringp start-args)) - (mapconcat 'identity start-args " ")) - (start-args - (read-string - (concat "Starting Args" - (if r-always-arg - (concat " [other than '" r-always-arg "']")) - " ? "))))) - (r-start-args - (concat r-always-arg - inferior-R-args " " ; add space just in case - start-args)) - (debug (string-match-p " -d \\| --debugger=" r-start-args)) - use-dialog-box) - (when (or ess-microsoft-p - (eq system-type 'cygwin)) - (setq use-dialog-box nil) - (when ess-microsoft-p ;; default-process-coding-system would break UTF locales on Unix - (setq default-process-coding-system '(undecided-dos . undecided-dos)))) - - (let ((inf-buf (inferior-ess r-start-args ess-r-customize-alist debug))) - (with-current-buffer inf-buf - (ess-process-put 'funargs-pre-cache ess-r--funargs-pre-cache) - (if debug - (progn - ;; We need to use callback, because R might start with a gdb process - (ess-process-put 'callbacks '(inferior-ess-r--init-callback)) - ;; Trigger the callback - (process-send-string (get-buffer-process inf-buf) "r\n")) - (ess-wait-for-process) - (R-initialize-on-start) - (comint-goto-process-mark)) - (ess-write-to-dribble-buffer - (format "(R): inferior-ess-language-start=%s\n" - inferior-ess-language-start))) - ;; FIXME: Current ob-R expects current buffer set to process buffer - (set-buffer inf-buf)))) - -;;;###autoload -(defalias 'R #'run-ess-r) - -(defun inferior-ess-r--adjust-startup-directory (dir dialect) - "Adjust startup directory DIR if DIALECT is R. -If in a package project, prefer the tests directory but only if -the package directory was selected in the first place." - (if (string= dialect "R") - (let* ((project-dir (cdr (ess-r-package-project))) - (tests-dir (expand-file-name (file-name-as-directory "tests") - project-dir))) - (if (and project-dir - (string= project-dir dir) - (string= default-directory tests-dir)) - tests-dir - dir)) - dir)) - -(defun inferior-ess-r--init-callback (_proc _name) - (R-initialize-on-start)) - -(defun R-initialize-on-start () - "This function is run after the first R prompt. -Executed in process buffer." - (ess-command (format - "if(identical(getOption('pager'), - file.path(R.home(), 'bin', 'pager'))) - options(pager='%s')\n" - inferior-ess-pager)) - (ess-r-load-ESSR) - (when inferior-ess-language-start - (ess-command (concat inferior-ess-language-start "\n"))) - ;; tracebug - (when ess-use-tracebug (ess-tracebug 1)) - (add-hook 'ess-presend-filter-functions 'ess-R-scan-for-library-call nil 'local) - (run-hooks 'ess-r-post-run-hook)) - -(defun ess-r--skip-function () - ;; Assumes the point is at function start - (if (looking-at-p ess-r-set-function-start) - (forward-list 1) ; get over the entire setXyz(...) - (forward-list 1) ; get over arguments - (if (looking-at-p "[ \t\n]*{") - (forward-sexp 1) ;; move over {...} - ;; {..}-less case - (skip-chars-forward " \t\n") - (goto-char (cadr (ess-continuations-bounds)))))) - -;; `beginning-of-defun' protocol: -;; 1) assumes that defuns are at the top level (e.g. always moves to bol) -(defun ess-r-beginning-of-defun (&optional arg) - "Move to beginning a top level function. -ARG is as in `beginning-of-defun'." - (ess-r-beginning-of-function arg t)) - -;; `end-of-defun' protocol: -;; 1) Uses beginning-of-defun-function with negative arg -;; 2) Assumes that beginning-of-defun-function with -1 arg finds current defun -;; when point is just in front of the function -(defun ess-r-end-of-defun (&optional arg) - "End of top level function. -ARG is as in `end-of-defun'." - (ess-r-end-of-function arg t)) - -(defun ess-r-beginning-of-function (&optional arg top-level) - "Leave (and return) the point at the beginning of the current ESS function. -When ARG is positive, search for beginning of function backward, -otherwise forward. Value of ARG is currently ignored. Return the -new position, or nil if no-match. If TOP-LEVEL is non-nil, search -for top-level functions only." - (setq arg (or arg 1)) - (let ((start-point (point)) - done) - ;; In case we are at the start of a function, skip past new lines. - (when (> arg 0) - ;; Start search from a forward position in order to capture current - ;; function start. But not when arg < 0; see end-of-defun protocol above. - (forward-line 2)) - (while (and (not done) - (re-search-backward ess-r-function-pattern nil t arg)) - (unless (ess-inside-string-or-comment-p) - (setq done - (if top-level - (= (car (syntax-ppss (match-beginning 0))) 0) - t)) - (if (< arg 0) - ;; move to match-end to avoid the infloop in re-search-backward - (goto-char (if done (match-beginning 0) (match-end 0))) - ;; Backward regexp match stops at the minimal match (e.g. partial - ;; function name), so we need a bit more work here. - (beginning-of-line) - (re-search-forward ess-r-function-pattern) - (goto-char (match-beginning 0)) - (when (<= start-point (point)) - (setq done nil))))) - (if done - (point) - (goto-char start-point) - nil))) - -(defun ess-r-end-of-function (&optional arg top-level) - "Leave the point at the end of the current function. -When ARG is positive, search for end of function forward, -otherwise backward. Move to point and return point if search was -successful, otherwise nil. If TOP-LEVEL is non-nil, search for -top level functions only." - (setq arg (or arg 1)) - (let* ((start-pos (point)) - (search-fn (lambda (lim) - (let ((foundp nil)) - (while (and (not foundp) - (re-search-forward ess-r-function-pattern nil t)) - (when (< arg 0) - ;; re-search-backward is a forward search - ;; internally, so we need to bol in order to avoid - ;; the infloop - (beginning-of-line)) - (setq foundp - (unless (ess-inside-string-or-comment-p) - (if top-level - (= 0 (car (save-excursion (syntax-ppss (match-beginning 0))))) - (>= (point) lim))))) - (if foundp - (progn (goto-char (match-beginning 0)) - (ess-r--skip-function)) - (goto-char start-pos)))))) - (ess-r-beginning-of-function 1 top-level) - (if (< (point) start-pos) - ;; Moved back. We were either inside a function or after a function. - (progn - (ess-r--skip-function) - ;; For negative ARG we are done. - (when (and (> arg 0) - (<= (point) start-pos)) - (funcall search-fn start-pos))) - ;; No function before point; search forward on positive ARG. - (when (> arg 0) - (funcall search-fn start-pos))))) - -;;;###autoload -(define-derived-mode ess-r-mode ess-mode "ESS[R]" - "Major mode for editing R source. See `ess-mode' for more help." - :group 'ess-R - (ess-setq-vars-local ess-r-customize-alist) - (setq-local ess-font-lock-keywords 'ess-R-font-lock-keywords) - (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-ignore-fill-prefix t) - (setq-local indent-line-function #'ess-r-indent-line) - (setq-local comment-indent-function #'ess-calculate-indent) - (setq-local add-log-current-defun-header-regexp "^\\(.+\\)\\s-+<-[ \t\n]*function") - (setq-local font-lock-syntactic-face-function #'ess-r-font-lock-syntactic-face-function) - (setq-local electric-layout-rules '((?{ . after))) - ;; indentation - (add-hook 'hack-local-variables-hook #'ess-set-style nil t) - ;; eldoc - (add-function :before-until (local 'eldoc-documentation-function) - #'ess-r-eldoc-function) - (when ess-use-eldoc (eldoc-mode)) - ;; auto-complete - (ess--setup-auto-complete ess-r-ac-sources) - ;; company - (ess--setup-company ess-r-company-backends) - (setq-local prettify-symbols-alist ess-r-prettify-symbols) - (setq font-lock-defaults '(ess-build-font-lock-keywords nil nil ((?\. . "w") (?\_ . "w")))) - (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first - (add-hook 'completion-at-point-functions 'ess-r-object-completion nil 'local) - (add-hook 'completion-at-point-functions #'ess-r-package-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) - (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local) - - (if (fboundp 'ess-add-toolbar) (ess-add-toolbar)) - ;; imenu is needed for `which-function' - (setq imenu-generic-expression ess-imenu-S-generic-expression) - (when ess-imenu-use-S - (imenu-add-to-menubar "Imenu-R")) - (setq-local beginning-of-defun-function #'ess-r-beginning-of-defun) - (setq-local end-of-defun-function #'ess-r-end-of-defun) - (ess-roxy-mode)) -;;;###autoload -(defalias 'R-mode 'ess-r-mode) -;;;###autoload -(defalias 'r-mode 'ess-r-mode) - - -;;;###autoload -(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . ess-r-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . ess-r-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . ess-r-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . ess-r-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("CITATION\\'" . ess-r-mode)) - - -;;*;; Miscellaneous - -(defun ess-R-arch-2-bit (arch) - "Translate R's architecture shortcuts/directory names to 'bits'. -ARCH \"32\" or \"64\" (for now)." - (if (string= arch "i386") "32" - ;; else: - "64")) - -(defun ess-rterm-arch-version (long-path &optional give-cons) - "Find a name for LONG-PATH, an absolute path to R on Windows. -Returns either Name, a string, or a (Name . Path) cons, such as - -(\"R-2.12.1-64bit\" . \"C:/Program Files/R/R-2.12.1/bin/x64/Rterm.exe\") - -\"R-x.y.z/bin/Rterm.exe\" will return \"R-x.y.z\", for R-2.11.x and older. -\"R-x.y.z/bin/i386/Rterm.exe\" will return \"R-x.y.z-32bit\", for R-2.12.x and newer. -\"R-x.y.z/bin/x64/Rterm.exe\" will return \"R-x.y.z-64bit\", for R-2.12.x and newer." - (let* ((dir (directory-file-name (file-name-directory long-path))) - (dir2 (directory-file-name (file-name-directory dir))) - (v-1up (file-name-nondirectory dir));; one level up - (v-2up (file-name-nondirectory dir2));; two levels up; don't want "bin" ... - (v-3up (file-name-nondirectory ;; three levels up; no "bin" for i386, x64 ... - (directory-file-name (file-name-directory dir2)))) - (val (if (string= v-2up "bin") - (concat v-3up "-" (ess-R-arch-2-bit v-1up) "bit") - ;; pre R-2.12.x, or when there's no extra arch-specific sub directory: - v-2up))) - (if give-cons - (cons val long-path) - val))) - -(defun ess-r-define-runners (&optional verbose) - "Generate functions for starting other versions of R. -See `ess-r-runner-prefixes' for strings that determine which functions -are created. On MS Windows, this works using -`ess-rterm-version-paths' instead. - -The functions will normally be placed on the menubar and stored -as `ess-r-created-runners' upon ESS initialization." - (when ess-r-runner-prefixes - (let ((versions - ;; Find which versions of R we want. Remove the pathname, leaving just - ;; the name of the executable. - (if ess-microsoft-p - (mapcar (lambda (v) (car (ess-rterm-arch-version v 'give-cons))) - ess-rterm-version-paths) - (delete-dups - (mapcar #'file-name-nondirectory - (apply #'nconc - (mapcar #'ess-find-exec-completions - ess-r-runner-prefixes))))))) - ;; Iterate over each string in VERSIONS, creating a new defun each time. - (setq ess-r-created-runners versions) - (if verbose - (message "Recreated %d R versions known to ESS: %s" - (length versions) versions)) - (if ess-microsoft-p - (cl-mapcar (lambda (v p) (ess-define-runner v "R" p)) versions ess-rterm-version-paths) - (mapc (lambda (v) (ess-define-runner v "R")) versions)) - ;; Add to menu - (when ess-r-created-runners - ;; new-menu will be a list of 3-vectors, of the form: - ;; ["R-1.8.1" R-1.8.1 t] - (let ((new-menu (mapcar (lambda(x) (vector x (intern x) t)) - ess-r-created-runners))) - (easy-menu-add-item ess-mode-menu '("Start Process") - (cons "Other" new-menu)) - (easy-menu-add-item inferior-ess-mode-menu '("Process") - (cons "R processes" new-menu))))))) - -(defun ess-r-redefine-runners (&optional verbose) - "Regenerate runners, i.e. `M-x R-*` possibilities. - Call `fmakunbound' on all elements of `ess-r-created-runners', then define new runners." - (interactive "P") - (dolist (f ess-r-created-runners) - (fmakunbound (intern f))) - (setq ess-r-created-runners nil) - (ess-r-define-runners verbose)) - -(defun ess-r-runners-reset (sym val) - "Regenerate runners. -Set SYM to VAL and call `ess-r-redefine-runners'." - (set-default sym val) - (ess-r-redefine-runners)) - -(define-obsolete-function-alias - 'ess-r-versions-create 'ess-r-define-runners "ESS 18.10") - -(defvar ess-newest-R nil - "Stores the newest version of R that has been found. -Used as a cache, within `ess-find-newest-R'. Do not use this value -directly, but instead call the function \\[ess-find-newest-R].") - - -(defcustom ess-prefer-higher-bit t - "Non-nil means prefer higher bit architectures of R. -e.g. prefer 64 bit over 32 bit. This is currently used only -by the code on Windows for finding the newest version of R." - :group 'ess-R - :type 'boolean) - -(defun ess-rterm-prefer-higher-bit () - "Optionally remove 32bit Rterms from being candidate for `run-ess-r-newest'. -Return the list of candidates for being `run-ess-r-newest'. Filtering is -done iff `ess-prefer-higher-bit' is non-nil. This is used only by -Windows when running `ess-find-newest-R'." - (if ess-prefer-higher-bit - ;; filter out 32 bit elements - (let ((filtered - (delq nil - (mapcar (lambda (x) (unless (string-match "/i386/Rterm.exe" x) x)) - ess-rterm-version-paths)))) - (if (null filtered) - ;; if none survived filtering, keep the original list - ess-rterm-version-paths - filtered)) - ess-rterm-version-paths)) - -(defun run-ess-r-newest (&optional start-args) - "Find the newest version of R available, and run it. -Subsequent calls to `run-ess-r-newest' will run that version, -rather than searching again for the newest version. Providing -START-ARGS (interactively, with \\[universal-argument]) will -prompt for command line arguments." - (interactive "P") - (unless ess-newest-R - (message "Finding all versions of R on your system...") - (setq ess-newest-R - (ess-find-newest-date - (mapcar #'ess-r-version-date - (if ess-microsoft-p - (ess-rterm-prefer-higher-bit) - (add-to-list 'ess-r-created-runners inferior-ess-r-program)))))) - (let ((inferior-ess-r-program ess-newest-R)) - (run-ess-r start-args))) - -(defalias 'R-newest 'run-ess-r-newest) - -;; (ess-r-version-date "R-2.5.1") (ess-r-version-date "R-patched") -;; (ess-r-version-date "R-1.2.1") (ess-r-version-date "R-1.8.1") -;; Windows: -;; (ess-r-version-date "C:/Program Files (x86)/R/R-2.11.1/bin/Rterm.exe") -;; Note that for R-devel, ver-string is something like -;; R version 2.6.0 Under development (unstable) (2007-07-14 r42234) -;; Antique examples are 'R 1.0.1 (April 14, 2000)' or 'R 1.5.1 (2002-06-17).' -(defun ess-r-version-date (rver) - "Return the date of the version of R named RVER. -The date is returned as a date string. If the version of R could -not be found from the output of the RVER program, \"-1\" is -returned." - (let ((date "-1") - (ver-string (shell-command-to-string - ;; here, MS Windows (shell-command) needs a short name: - (concat (if (and ess-microsoft-p - ;; silence byte compiler warns about w32-fns - (fboundp 'w32-short-file-name)) - (w32-short-file-name rver) - rver) - " --version")))) - (when (string-match - "R \\(version \\)?[1-9][^\n]+ (\\(2[0-9-]+\\)\\( r[0-9]+\\)?)" - ver-string) - (setq date (match-string 2 ver-string))) - (cons date rver))) - -(defun ess-current-R-version () - "Get the version of R currently running in the ESS buffer as a string." - (ess-make-buffer-current) - (car (ess-get-words-from-vector "as.character(.ess.Rversion)\n"))) - -(defun ess-current-R-at-least (version) - "Is the version of R (in the ESS buffer) at least (\">=\") VERSION ? -Examples: (ess-current-R-at-least '2.7.0) - or (ess-current-R-at-least \"2.5.1\")" - (ess-make-buffer-current) - (string= "TRUE" - (car (ess-get-words-from-vector - (format "as.character(.ess.Rversion >= \"%s\")\n" version))))) -(defun ess-find-newest-date (rvers) - "Find the newest version of R given in the a-list RVERS. -Each element of RVERS is a dotted pair (date . R-version), where -date is given as e.g.\"2007-11-30\" so that we can compare dates -as strings. If a date is listed as \"-1\", that version of R -could not be found. - -If the value returned is nil, no valid newest version of R could be found." - (let (new-r this-r - (new-time "0")) - (while rvers - (setq this-r (car rvers) - rvers (cdr rvers)) - (when (string< new-time (car this-r)) - (setq new-time (car this-r) - new-r (cdr this-r)))) - new-r)) - -(defun ess-find-rterm (&optional ess-R-root-dir bin-Rterm-exe) - "Find the full path of all occurrences of Rterm.exe under the ESS-R-ROOT-DIR. -If ESS-R-ROOT-DIR is nil, construct it by looking for an -occurrence of Rterm.exe in the `exec-path'. If there are no -occurrences of Rterm.exe in the `exec-path', then use -`ess-program-files' (which evaluates to something like -\"c:/progra~1/R/\" in English locales) which is the default -location for the R distribution. If BIN-RTERM-EXE is nil, then -use \"bin/Rterm.exe\"." - (if (not ess-R-root-dir) - (let ((Rpath (executable-find "Rterm"))) - (setq ess-R-root-dir - (expand-file-name - (if Rpath - (concat (file-name-directory Rpath) "../../") - (concat ess-program-files "/R/")))) - (ess-write-to-dribble-buffer - (format "(ess-find-rterm): ess-R-root-dir = '%s'\n" ess-R-root-dir)))) - - (if (not bin-Rterm-exe) (setq bin-Rterm-exe "bin/Rterm.exe")) - - (when (file-directory-p ess-R-root-dir) ; otherwise file-name-all-.. errors - (setq ess-R-root-dir - (replace-regexp-in-string "[\\]" "/" ess-R-root-dir)) - (let ((R-ver - (ess-drop-non-directories - (ess-flatten-list - (mapcar (lambda (r-prefix) - (file-name-all-completions r-prefix ess-R-root-dir)) - (append '("rw") ess-r-runner-prefixes)))))) - (mapcar (lambda (dir) - (let ((R-path - (concat ess-R-root-dir - (replace-regexp-in-string "[\\]" "/" dir) - bin-Rterm-exe))) - (if (file-exists-p R-path) R-path))) - R-ver)))) - -(cl-defmethod ess-font-lock-keywords (&context (major-mode ess-r-transcript-mode)) - 'ess-R-font-lock-keywords) - -;;;###autoload -(define-derived-mode ess-r-transcript-mode ess-transcript-mode "ESS R Transcript" - "A Major mode for R transcript files." - :syntax-table ess-r-mode-syntax-table - :group 'ess - (ess-setq-vars-local ess-r-customize-alist) - (setq-local comint-prompt-regexp inferior-S-prompt) - (setq-local ess-font-lock-keywords 'ess-R-font-lock-keywords) - (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) - (setq-local paragraph-ignore-fill-prefix t) - (setq-local indent-line-function #'ess-r-indent-line) - (setq-local add-log-current-defun-header-regexp "^\\(.+\\)\\s-+<-[ \t\n]*function") - (setq-local font-lock-syntactic-face-function #'ess-r-font-lock-syntactic-face-function) - (setq-local prettify-symbols-alist ess-r-prettify-symbols) - (setq font-lock-defaults '(ess-build-font-lock-keywords - nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))) - -(fset 'r-transcript-mode 'ess-r-transcript-mode) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Rr]out" . ess-r-transcript-mode)) -;;;###autoload -(add-to-list 'interpreter-mode-alist '("Rscript" . ess-r-mode)) -;;;###autoload -(add-to-list 'interpreter-mode-alist '("r" . ess-r-mode)) - -(defun ess-r-fix-T-F (&optional from quietly) - "Change T/F into TRUE and FALSE cautiously. -Do not change in comments and strings. Start at FROM, which -defaults to point, and change to end of buffer. When QUIETLY, do -not issue messages." - (interactive "d\nP"); point and prefix (C-u) - (save-excursion - (goto-char from) - (ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)T\\>" "\\1TRUE" - 'fixcase nil (not quietly)) - (goto-char from) - (ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)F\\>" "\\1FALSE" - 'fixcase nil (not quietly)))) -(define-obsolete-function-alias 'R-fix-T-F 'ess-r-fix-T-F - "ESS 18.10") - -(defvar ess--packages-cache nil - "Cache var to store package names. -Used by `ess-r-install-library'.") - -(defvar ess--CRAN-mirror nil - "CRAN mirror name cache.") - -(cl-defmethod ess-install-library--override (update package &context (ess-dialect "R")) - "Prompt and install R PACKAGE. -With argument UPDATE, update cached packages list." - (inferior-ess-r-force) - (when (equal "@CRAN@" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n"))) - (ess-set-CRAN-mirror ess--CRAN-mirror) - (ess-wait-for-process (get-process ess-current-process-name)) - (unless package (setq update t))) - (when (or update - (not ess--packages-cache)) - (message "Fetching R packages ... ") - (setq ess--packages-cache - (ess-get-words-from-vector "print(rownames(available.packages()), max=1e6)\n"))) - (let* ((ess-eval-visibly-p t) - (package (or package - (ess-completing-read "Package to install" ess--packages-cache)))) - (process-send-string (get-process ess-current-process-name) - (format "install.packages('%s')\n" package)) - (display-buffer (buffer-name (ess-get-process-buffer))))) - -(defun ess-setRepositories () - "Call setRepositories()." - (interactive) - (if (not (string-match "^R" ess-dialect)) - (message "Sorry, not available for %s" ess-dialect) - (ess-eval-linewise "setRepositories(FALSE)\n"))) - -(defun ess-set-CRAN-mirror (&optional mirror) - "Set cran MIRROR." - (interactive) - (let ((mirror-cmd "local({r <- getOption('repos'); r['CRAN'] <- '%s';options(repos=r)})\n")) - (if mirror - (ess-command (format mirror-cmd mirror)) - (when-let ((M1 (ess-get-words-from-vector "local({out <- getCRANmirrors(local.only=TRUE); print(paste(out$Name,'[',out$URL,']', sep=''))})\n")) - (mirror (ess-completing-read "Choose CRAN mirror" M1 nil t)) - (url (car (cl-member mirror M1 :test #'string=)))) - (setq ess--CRAN-mirror (progn (string-match "\\(.*\\)\\[\\(.*\\)\\]$" url) - (match-string 2 url))) - (ess-command (format mirror-cmd ess--CRAN-mirror))))) - (message "CRAN mirror: %s" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n")))) -(define-obsolete-function-alias 'ess-setCRANMiror 'ess-set-CRAN-mirror "ESS 18.10") - -(defun ess-r-check-install-package (pkg) - "Check if package PKG is installed and offer to install if not." - (unless (ess-boolean-command (format "print(requireNamespace('%s', quietly = TRUE))\n" pkg)) - (if (y-or-n-p (format "Package '%s' is not installed. Install? " pkg)) - (ess-eval-linewise (format "install.packages('%s')\n" pkg)) - (signal 'quit nil)))) - -(define-obsolete-function-alias 'ess-r-sos #'ess-help-web-search "ESS 19.04") - -(cl-defmethod ess--help-web-search-override (cmd &context (ess-dialect "R")) - (ess-r-check-install-package "sos") - (ess-eval-linewise (format "sos::findFn(\"%s\", maxPages=10)" cmd))) - - -(defun ess-R-scan-for-library-call (string) - "Detect `library/require' call in STRING and update tracking vars. -Placed into `ess-presend-filter-functions' for R dialects." - (when (string-match-p "\\blibrary(\\|\\brequire(" string) - (ess--mark-search-list-as-changed)) - string) - -(cl-defmethod ess-installed-packages (&context (ess-dialect "R")) - ;;; FIXME? .packages() does not cache; installed.packages() does but is slower first time - (ess-get-words-from-vector "print(.packages(T), max=1e6)\n")) - -(cl-defmethod ess-load-library--override (pack &context (ess-dialect "R")) - "Load an R package." - (ess-eval-linewise (format "library('%s')\n" pack))) - -(define-obsolete-function-alias 'ess-library 'ess-load-library "ESS[12.09-1]") - -;;; smart-comma was a bad idea -(eval-after-load "eldoc" - '(eldoc-add-command "ess-smart-comma")) - - -;;*;; Interaction with R - -;;;*;;; Evaluation - -(defun ess-r-arg (param value &optional wrap) - (let ((value (if wrap - (concat "'" value "'") - value))) - (concat ", " param " = " value))) - -(defun ess-r-build-args (visibly output namespace) - (let ((visibly (ess-r-arg "visibly" (if visibly "TRUE" "FALSE"))) - (output (ess-r-arg "output" (if output "TRUE" "FALSE"))) - (pkg (when namespace (ess-r-arg "package" namespace t))) - (verbose (when (and namespace - ess-r-namespaced-load-verbose) - (ess-r-arg "verbose" "TRUE")))) - (concat visibly output pkg verbose))) - -(cl-defmethod ess-build-eval-command--override (string &context (ess-dialect "R") - &optional visibly output file &rest args) - "R method to build eval command." - (let* ((namespace (caar args)) - (namespace (unless ess-debug-minor-mode - (or namespace (ess-r-get-evaluation-env)))) - (cmd (if namespace ".ess.ns_eval" ".ess.eval")) - (file (when file (ess-r-arg "file" file t))) - (rargs (ess-r-build-args visibly output namespace))) - (concat cmd "(\"" string "\"" rargs file ")\n"))) - -(cl-defmethod ess-build-load-command (string &context (ess-dialect "R") - &optional visibly output file &rest _args) - (let* ((namespace (or file (ess-r-get-evaluation-env))) - (cmd (if namespace ".ess.ns_source" ".ess.source")) - (rargs (ess-r-build-args visibly output namespace))) - (concat cmd "('" string "'" rargs ")\n"))) - -(defun ess-r-build-eval-message (message) - (let ((env (cond (ess-debug-minor-mode - (substring-no-properties ess-debug-indicator 1)) - ((ess-r-get-evaluation-env))))) - (if env - (format "[%s] %s" env message) - message))) - -(defvar-local ess-r-evaluation-env nil - "Environment into which code should be evaluated. -When this variable is nil, code is evaluated in the current -environment. Currently only packages can be set as evaluation -environments. Use `ess-r-set-evaluation-env' to set this -variable.") - -(defun ess-r-get-evaluation-env () - "Get current evaluation env." - (or ess-r-evaluation-env - (and ess-current-process-name - (ess-get-process-variable 'ess-r-evaluation-env)))) - -(defun ess-r-set-evaluation-env (&optional arg) - "Select a package namespace for evaluation of R code. - -Call interactively with a prefix argument to disable evaluation -in a namespace. When calling from a function, ARG can be a -string giving the package to select, any other non-nil value to -disable, or nil to prompt for a package. - -If `ess-r-prompt-for-attached-pkgs-only' is non-nil, prompt only for -attached packages." - (interactive "P") - (let ((env (cond ((stringp arg) arg) - ((null arg) (ess-r--select-package-name)) - (t "*none*")))) - (if (equal env "*none*") - (let ((cur-env (ess-r-get-evaluation-env))) - ;; fixme: does not work if env is set at process level - (setq ess-r-evaluation-env nil) - (delq 'ess-r--evaluation-env-mode-line ess--local-mode-line-process-indicator) - (message (format "Evaluation in %s disabled" (propertize cur-env 'face font-lock-function-name-face)))) - (setq ess-r-evaluation-env env) - (add-to-list 'ess--local-mode-line-process-indicator 'ess-r--evaluation-env-mode-line t) - (message (format "Evaluating in %s" (propertize env 'face font-lock-function-name-face)))) - (force-mode-line-update))) - -(defvar-local ess-r--evaluation-env-mode-line - '(:eval (let ((env (ess-r-get-evaluation-env))) - (if env - (format " %s" - (propertize (if (equal env (ess-r-package-name)) - "pkg" - env) - 'face 'mode-line-emphasis)) - "")))) -(put 'ess-r--evaluation-env-mode-line 'risky-local-variable t) - -(defvar ess-r-namespaced-load-only-existing t - "Whether to load only objects already existing in a namespace.") - -(cl-defmethod ess-load-file--override (file &context (ess-dialect "R")) - (cond - ;; Namespaced evaluation - ((ess-r-get-evaluation-env) - (ess-r-load-file-namespaced file)) - ;; Evaluation into current env via .ess.source() - (t - (let ((command (ess-build-load-command file nil t))) - (ess-send-string (ess-get-process) command))))) - -(defun ess-r-load-file-namespaced (&optional file) - "Load FILE into a package namespace. - -This prompts for a package when no package is currently -selected (see `ess-r-set-evaluation-env')." - (ess-force-buffer-current "R process to use: ") - (let* ((pkg-name (ess-r-get-evaluation-env)) - (command (ess-build-load-command file nil t pkg-name))) - (ess-send-string (ess-get-process) command))) - -(cl-defmethod ess-send-region--override (process start end visibly message type - &context (ess-dialect "R")) - (cond - ;; Namespaced evaluation - ((ess-r-get-evaluation-env) - (ess-r-send-region-namespaced process start end visibly message)) - ;; Evaluation into current env - (t - (ess-send-string process (buffer-substring start end) visibly message type)))) - -(defun ess-r-send-region-namespaced (proc start end &optional visibly message) - "Ask for for the package and devSource region into it." - (or (ess-r-get-evaluation-env) - (ess-r-set-evaluation-env)) - (message (ess-r-build-eval-message (or message "Eval region"))) - (ess-send-string proc (buffer-substring start end) visibly message)) - - -;;;*;;; Help - -(defun ess-r-namespaced-object-p (object) - (string-match "^[[:alnum:].]+::" object)) - -(defun ess-r-build-help-command--qualified (object) - (when (ess-r-namespaced-object-p object) - (let* ((pkg-name (substring object (match-beginning 0) (- (match-end 0) 2))) - (object (concat "'" (substring object (match-end 0)) "'")) - (pkg (ess-r-arg "package" pkg-name t))) - (concat ".ess.help(" object pkg ")\n")))) - -(defun ess-r-build-help-command--get-package-dir (object) - ;; Ugly hack to avoid tcl/tk dialogues - (let ((pkgs (ess-get-words-from-vector - (format "as.character(utils::help('%s'))\n" object)))) - (when (> (length pkgs) 1) - (ess-completing-read "Choose location" pkgs nil t)))) - -(defun ess-r-build-help-command--unqualified (object) - (if (eq ess-help-type 'index) - ;; we are in index page, qualify with namespace - (ess-r-build-help-command--qualified (format "%s::%s" ess-help-object object)) - (let ((pkg-dir (ess-r-build-help-command--get-package-dir object)) - (command (format inferior-ess-r-help-command object))) - (if pkg-dir - ;; Invoking `print.help_files_with_topic' - (format "do.call(structure, c('%s', attributes(%s)))\n" pkg-dir command) - command)))) - -(cl-defmethod ess-build-help-command (object &context (ess-dialect "R")) - (or (ess-r-build-help-command--qualified object) - (ess-r-build-help-command--unqualified object))) - -(defconst inferior-ess-r--input-help (format "^ *help *(%s)" ess-help-arg-regexp)) -(defconst inferior-ess-r--input-?-help-regexp "^ *\\(?:\\(?1:[a-zA-Z ]*?\\?\\{1,2\\}\\) *\\(?2:.+\\)\\)") -(defconst inferior-ess-r--page-regexp (format "^ *page *(%s)" ess-help-arg-regexp)) - -(defun ess-help-r--process-help-input (proc string) - (let ((help-match (and (string-match inferior-ess-r--input-help string) - (match-string 2 string))) - (help-?-match (and (string-match inferior-ess-r--input-?-help-regexp string) - string)) - (page-match (and (string-match inferior-ess-r--page-regexp string) - (match-string 2 string)))) - (when (or help-match help-?-match page-match) - (cond (help-match - (ess-display-help-on-object help-match) - (process-send-string proc "\n")) - (help-?-match - (ess-help-r--display-help-? string help-?-match) - (process-send-string proc "\n")) - (page-match - (switch-to-buffer-other-window - (ess-command (concat page-match "\n") - (get-buffer-create (concat page-match ".rt")))) - (ess-r-transcript-mode) - (process-send-string proc "\n"))) - t))) - -(defun ess-help-r--display-help-? (string help-?-match) - (cond ((string-match "\\?\\?\\(.+\\)" help-?-match) - (ess--display-indexed-help-page (concat help-?-match "\n") - "^\\([^ \t\n]+::[^ \t\n]+\\)[ \t\n]+" - (format "*ess-apropos[%s](%s)*" - ess-current-process-name (match-string 1 help-?-match)) - 'appropos)) - ((string-match "^ *\\? *\\([^ \t]+\\)$" help-?-match) - (ess-display-help-on-object (match-string 1 help-?-match))) - ;; Anything else we send to process almost unchanged - (t - (let ((help-?-match (and (string-match inferior-ess-r--input-?-help-regexp string) - (format "%s%s" (match-string 1 string) - (ess-help-r--sanitize-topic (match-string 2 string)))))) - (ess-display-help-on-object help-?-match "%s\n"))))) - -(defun ess-help-r--sanitize-topic (string) - "Enclose help topic STRING into `` to avoid ?while ?if etc hangs." - (if (string-match "\\([^:]*:+\\)\\(.*\\)$" string) ; treat foo::bar correctly - (format "%s`%s`" (match-string 1 string) (match-string 2 string)) - (format "`%s`" string))) - - -;;;*;;; Utils for inferior R process - -(defun inferior-ess-r-input-sender (proc string) - (save-current-buffer - (or (ess-help-r--process-help-input proc string) - (inferior-ess-input-sender proc string)))) - -(defun ess-r-load-ESSR () - "Load ESSR functionality." - (cond - ((file-remote-p (ess-get-process-variable 'default-directory)) - (if (eq ess-r-fetch-ESSR-on-remotes t) - (ess-r--fetch-ESSR-remote) - (ess-r--load-ESSR-remote))) - ((and (bound-and-true-p ess-remote)) - (if ess-r-fetch-ESSR-on-remotes - (ess-r--fetch-ESSR-remote) - (ess-r--load-ESSR-remote t))) - (t (ess-r--load-ESSR-local)))) - -(defun ess-r--load-ESSR-local () - (let* ((src-dir (expand-file-name "ESSR/R" ess-etc-directory)) - (cmd (format "local({ - source('%s/.load.R', local=TRUE) #define load.ESSR - .ess.load.ESSR('%s') - })\n" - src-dir src-dir))) - (with-current-buffer (ess-command cmd) - (let ((msg (buffer-string))) - (when (> (length msg) 1) - (message (format "Messages while loading ESSR: %s" msg))))))) - -(defun ess-r--load-ESSR-remote (&optional chunked) - (ess-command (format ".ess.ESSRversion <- '%s'\n" essr-version)) - (with-temp-message "Loading ESSR into remote ..." - (let ((src-dir (expand-file-name "ESSR/R" ess-etc-directory))) - (dolist (file (directory-files src-dir t "\\.R$")) - (ess--inject-code-from-file file chunked))))) - -(defun ess-r--fetch-ESSR-remote () - (let ((loader (ess-file-content (expand-file-name "ESSR/LOADREMOTE" ess-etc-directory)))) - (unless (ess-boolean-command (format loader essr-version) nil 0.1) - (let* ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string))) - (src-dir (expand-file-name "ESSR/R" ess-etc-directory)) - (files (directory-files src-dir t "\\.R$"))) - (message (format "Couldn't load ESSR.rds. Injecting from local.\n Error: %s\n" errmsg)) - (ess-r--load-ESSR-remote))))) - -(cl-defmethod ess-quit--override (arg &context (ess-dialect "R")) - "With ARG, do not offer to save the workspace." - (let ((cmd (format "base::q('%s')\n" (if arg "no" "default"))) - (sprocess (ess-get-process ess-current-process-name))) - (when (not sprocess) (error "No ESS process running")) - (ess-cleanup) - (ess-send-string sprocess cmd t))) - -(defcustom inferior-ess-r-reload-hook nil - "Hook run when reloading the R inferior buffer." - :type 'hook - :group 'ess-R) - -(cl-defmethod inferior-ess-reload--override (start-name start-args &context (ess-dialect "R")) - "Call `run-ess-r' with START-ARGS. -Then run `inferior-ess-r-reload-hook'." - (let ((inferior-ess-r-program start-name)) - (run-ess-r start-args)) - (run-hooks 'inferior-ess-r-reload-hook)) - -(defun inferior-ess-r-force (&optional prompt force no-autostart ask-if-1) - (setq-local ess-dialect "R") - (ess-force-buffer-current prompt force no-autostart ask-if-1)) - - -;;*;; Editing Tools - -;;;*;;; Indentation Engine - -;; Written by Lionel Henry in mid 2015 - -(defun ess-r-indent-line () - "Indent current line as ESS R code. -Return the amount the indentation changed by." - (when-let ((indent (ess-calculate-indent))) - (let ((case-fold-search nil) - (pos (- (point-max) (point))) - beg shift-amt) - (beginning-of-line) - (setq beg (point)) - (skip-chars-forward " \t") - (setq shift-amt (- indent (current-column))) - (if (zerop shift-amt) - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - (delete-region beg (point)) - (indent-to indent) - ;; If initial point was within line's indentation, - ;; position after the indentation. - ;; Else stay at same point in text. - (when (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos)))) - shift-amt))) - -(defun ess-r-indent-exp () - (save-excursion - (when current-prefix-arg - (ess-climb-to-top-level)) - (let* ((bounds (ess-continuations-bounds)) - (end (cadr bounds)) - (beg (if current-prefix-arg - (car bounds) - (forward-line) - (point)))) - (indent-region beg end)))) - -(defun ess-indent-call (&optional start) - (save-excursion - (when (ess-escape-calls) - (setq start (or start (point))) - (skip-chars-forward "^[(") - (forward-char) - (ess-up-list) - (indent-region start (point))))) - -(defun ess-offset (offset) - (setq offset (eval (intern (concat "ess-offset-" (symbol-name offset))))) - (when (and (not (eq offset nil)) - (listp offset) - (or (numberp (cadr offset)) - (eq (cadr offset) t) - (error "Malformed offset"))) - (setq offset (cadr offset))) - (cond ((numberp offset) - offset) - ((null offset) - 0) - (t - ess-indent-offset))) - -(defun ess-offset-type (offset) - (setq offset (eval (intern (concat "ess-offset-" (symbol-name offset))))) - (if (listp offset) - (car offset) - offset)) - -(defun ess-overridden-blocks () - (append (when (memq 'fun-decl ess-align-blocks) - (list (car ess-prefixed-block-patterns))) - (when (memq 'control-flow ess-align-blocks) - (append (cdr ess-prefixed-block-patterns) - '("}?[ \t]*else"))))) - -(defun ess-calculate-indent () - "Return appropriate indentation for current line as ESS code. -In usual case returns an integer: the column to indent to. -Returns nil if line starts inside a string, t if in a comment." - (save-excursion - (beginning-of-line) - (let* ((indent-point (point)) - (state (syntax-ppss)) - (containing-sexp (cadr state)) - (prev-containing-sexp (car (last (butlast (nth 9 state)))))) - (back-to-indentation) - (cond - ;; Strings - ((ess-inside-string-p) - (current-indentation)) - ;; Comments - ((ess-calculate-indent--comments)) - ;; Indentation of commas - ((looking-at ",") - (ess-calculate-indent--comma)) - ;; Arguments: Closing - ((ess-call-closing-p) - (ess-calculate-indent--call-closing-delim)) - ;; Block: Contents (easy cases) - ((ess-calculate-indent--block-relatively)) - ;; Block: Prefixed block - ((ess-calculate-indent--prefixed-block-curly)) - ;; Continuations - ((ess-calculate-indent--continued)) - ;; Block: Overridden contents - ((ess-calculate-indent--aligned-block)) - ;; Block: Opening - ((ess-block-opening-p) - (ess-calculate-indent--block-opening)) - ;; Bare line - ((and (null containing-sexp) - (not (ess-unbraced-block-p))) - 0) - ;; Block: Closing - ((ess-block-closing-p) - (ess-calculate-indent--block 0)) - ;; Block: Contents - ((ess-block-p) - (ess-calculate-indent--block)) - ;; Arguments: Nested calls override - ((ess-calculate-indent--nested-calls)) - ;; Arguments: Contents - (t - (ess-calculate-indent--args)))))) - -(defun ess-calculate-indent--comments () - (when ess-indent-with-fancy-comments - (cond - ;; ### or #! - ((or (looking-at "###") - (and (looking-at "#!") - (= 1 (line-number-at-pos)))) - 0) - ;; Single # comment - ((looking-at "#[^#']") - comment-column)))) - -(defun ess-calculate-indent--comma () - (when (ess-inside-call-p) - (let ((indent (save-excursion - (ess-calculate-indent--args))) - (unindent (progn (skip-chars-forward " \t") - ;; return number of skipped chars - (skip-chars-forward ", \t")))) - (- indent unindent)))) - -(defun ess-calculate-indent--call-closing-delim () - (cond ((save-excursion - (ess-skip-blanks-backward t) - (eq (char-before) ?,)) - (ess-calculate-indent--args nil)) - ((save-excursion - (and (ess-ahead-operator-p) - (or (ess-ahead-definition-op-p) - (not ess-align-continuations-in-calls)))) - (ess-calculate-indent--continued)) - (t - (ess-calculate-indent--args 0)))) - -(defun ess-calculate-indent--block-opening () - (cond - ;; Block is an argument in a function call - ((when containing-sexp - (ess-at-containing-sexp - (ess-behind-call-opening-p "[[(]"))) - (ess-calculate-indent--block 0)) - ;; Top-level block - ((null containing-sexp) 0) - ;; Block is embedded in another block - ((ess-at-containing-sexp - (+ (current-indentation) - (ess-offset 'block)))))) - -(defun ess-calculate-indent--aligned-block () - ;; Check for `else' opening - (if (and (memq 'control-flow ess-align-blocks) - (looking-at "else\\b") - (ess-climb-if-else)) - (progn - (when (looking-at "else\\b") - (ess-skip-curly-backward)) - (current-column)) - ;; Check for braced and unbraced blocks - (ess-save-excursion-when-nil - (let ((offset (if (looking-at "[{})]") - 0 (ess-offset 'block)))) - (when (and (cond - ;; Unbraced blocks - ((ess-climb-block-prefix)) - ;; Braced blocks - (containing-sexp - (when (ess-at-containing-sexp - (looking-at "{")) - (ess-escape-prefixed-block)))) - (cl-some 'looking-at - (ess-overridden-blocks))) - (+ (current-column) offset)))))) - -(defun ess-calculate-indent--block-relatively () - (ess-save-excursion-when-nil - (let ((offset (if (looking-at "[})]") 0 (ess-offset 'block))) - (start-line (line-number-at-pos))) - (cond - ;; Braceless block continuations: only when not in a call - ((ess-save-excursion-when-nil - (and (not (looking-at "{")) - (ess-goto-char (ess-unbraced-block-p)) - (not (looking-at "function\\b")) - (or (null containing-sexp) - (ess-at-containing-sexp - (not (looking-at "(")))))) - (ess-maybe-climb-broken-else 'same-line) - (ess-skip-curly-backward) - (+ (current-column) - (ess-offset 'block))) - ;; Don't indent relatively other continuations - ((ess-ahead-continuation-p) - nil) - ;; If a block already contains an indented line, we can indent - ;; relatively from that first line - ((ess-save-excursion-when-nil - (and (not (looking-at "}")) - containing-sexp - (goto-char containing-sexp) - (looking-at "{") - (progn - (forward-line) - (back-to-indentation) - (/= (line-number-at-pos) start-line)) - (not (looking-at "[ \t]*\\(#\\|$\\)")) - (save-excursion - (or (ess-jump-expression) - (ess-jump-continuations)) - (< (line-number-at-pos) start-line)))) - (current-column)) - ;; If a block is not part of a call, we can indent relatively - ;; from the opening {. First check that enclosing { is first - ;; thing on line - ((and containing-sexp - (not (ess-unbraced-block-p)) - (goto-char containing-sexp) - (ess-block-opening-p) - (equal (point) (save-excursion - (back-to-indentation) - (point)))) - (+ (current-column) offset)))))) - -(defun ess-arg-block-p () - (unless (or (null containing-sexp) - ;; Unbraced blocks in a { block are not arg blocks - (and (ess-unbraced-block-p) - (ess-at-containing-sexp - (looking-at "{")))) - (cond - ;; Unbraced body - ((ess-at-indent-point - (and (ess-unbraced-block-p) - (goto-char containing-sexp) - (ess-behind-call-opening-p "[[(]"))) - 'body) - ;; Indentation of opening brace as argument - ((ess-at-containing-sexp - (ess-behind-call-opening-p "[[(]")) - 'opening) - ;; Indentation of body or closing brace as argument - ((ess-at-containing-sexp - (and (or (looking-at "{") - (ess-behind-block-paren-p)) - prev-containing-sexp - (goto-char prev-containing-sexp) - (ess-behind-call-opening-p "[[(]"))) - 'body)))) - -(defun ess-calculate-indent--block (&optional offset) - (let ((arg-block (ess-arg-block-p))) - (cond (arg-block - (ess-calculate-indent--arg-block offset arg-block)) - (t - ;; Block is not part of an arguments list. Climb over any - ;; block opening (function declaration, etc) to indent from - ;; starting indentation. - (or (ess-climb-block-prefix) - (and (goto-char containing-sexp) - (ess-climb-block-prefix))) - (+ (current-indentation) (or offset (ess-offset 'block))))))) - -(defun ess-calculate-indent--arg-block (offset arg-block) - (let* ((block-type (cond ((or (ess-at-containing-sexp - (and (eq arg-block 'body) - (ess-climb-block-prefix "function"))) - (ess-at-indent-point - (and (eq arg-block 'opening) - (ess-backward-sexp 2) - (looking-at "function\\b")))) - 'fun-decl) - ((ess-at-indent-point - (ess-unbraced-block-p)) - 'unbraced) - ((ess-at-containing-sexp - (not (ess-ahead-attached-name-p))) - 'bare-block) - (t))) - (call-pos (if (and (not (eq block-type 'unbraced)) - (not (eq arg-block 'opening))) - (goto-char prev-containing-sexp) - (prog1 containing-sexp - (goto-char indent-point))))) - (ess-calculate-indent--args offset (ess-offset-type 'block) - call-pos indent-point block-type))) - -;; This function is currently the speed bottleneck of the indentation -;; engine. This is due to the need to call (ess-maximum-args-indent) -;; to check if some previous arguments have been pushed off from their -;; natural indentation: we need to check the whole call. This is very -;; inefficient especially when indenting a region containing a large -;; function call (e.g. some dplyr's data cleaning code). Should be -;; solved by implementing a cache as in (syntax-ppss), though it's -;; probably not worth the work. -(defun ess-calculate-indent--args (&optional offset type call-pos to block) - (let* ((call-pos (or call-pos containing-sexp)) - (max-col (prog1 (unless (eq type 'prev-line) - (ess-maximum-args-indent call-pos to)) - (goto-char call-pos))) - (override (and ess-align-arguments-in-calls - (save-excursion - (ess-climb-object) - (cl-some 'looking-at - ess-align-arguments-in-calls)))) - (type-sym (cond (block 'block) - ((looking-at "[[:blank:]]*[([][[:blank:]]*\\($\\|#\\)") - 'arguments-newline) - (t 'arguments))) - (type (or type - (and override 'open-delim) - (ess-offset-type type-sym))) - (offset (or offset - (and (not block) (eq type 'open-delim) 0) - (ess-offset type-sym))) - (indent - (cond - ;; Indent from opening delimiter - ((eq type 'open-delim) - (ess-calculate-indent--args-open-delim)) - ;; Indent from attached name - ((eq type 'prev-call) - (ess-calculate-indent--args-prev-call)) - ;; Indent from previous line indentation - ((eq type 'prev-line) - (ess-calculate-indent--args-prev-line)) - (t - (error "Malformed offset"))))) - (if max-col - (ess-adjust-argument-indent indent offset max-col block) - (+ indent offset)))) - -(defun ess-calculate-indent--args-open-delim () - (forward-char) - (current-column)) - -(defun ess-calculate-indent--args-prev-call () - ;; Handle brackets chains such as ][ (cf data.table) - (ess-climb-chained-delims) - ;; Handle call chains - (if ess-indent-from-chain-start - (while (and (ess-backward-sexp) - (when (looking-back "[[(][ \t,]*" (line-beginning-position)) - (goto-char (match-beginning 0))))) - (ess-backward-sexp)) - (when ess-indent-from-lhs - (ess-climb-lhs)) - (if (and nil - (eq block 'fun-decl) - (not (eq arg-block 'opening)) - (not (eq (ess-offset-type type-sym) 'open-delim))) - (+ (ess-offset 'block) (current-column)) - (current-column))) - -(defun ess-calculate-indent--args-prev-line () - (ess-at-indent-point - (cond - ;; Closing delimiters are actually not indented at - ;; prev-line, but at opening-line - ((looking-at "[]})]") - (ess-up-list -1) - (when (looking-at "{") - (ess-climb-block-prefix)) - (current-indentation)) - ;; Function blocks need special treatment - ((and (eq type 'prev-line) - (eq block 'fun-decl)) - (goto-char containing-sexp) - (ess-climb-block-prefix) - (current-indentation)) - ;; Regular case - (t - ;; Find next non-empty line to indent from - (while (and (= (forward-line -1) 0) - (looking-at "[ \t]*\\($\\|#\\)"))) - (goto-char (ess-code-end-position)) - ;; Climb relevant structures - (unless (ess-climb-block-prefix) - (when (eq (char-before) ?,) - (forward-char -1)) - (ess-climb-expression) - (ess-climb-continuations)) - ;; The following ensures that only the first line - ;; counts. Otherwise consecutive statements would get - ;; increasingly more indented. - (when (and block - containing-sexp - (not (eq block 'unbraced)) - (save-excursion - (/= (line-number-at-pos) - (progn (goto-char containing-sexp) - (line-number-at-pos))))) - (setq offset 0)) - (current-indentation))))) - -;; Indentation of arguments needs to keep track of how previous -;; arguments are indented. If one of those has a smaller indentation, -;; we push off the current line from its natural indentation. For -;; block arguments, we still need to push off this column so we ignore -;; it. -(defun ess-adjust-argument-indent (base offset max-col push) - (if push - (+ (min base max-col) offset) - (min (+ base offset) max-col))) - -;; When previous arguments are shifted to the left (can happen in -;; several situations) compared to their natural indentation, the -;; following lines should not get indented past them. The following -;; function checks the minimum indentation for all arguments of the -;; current function call or bracket indexing. -(defun ess-maximum-args-indent (&optional from to) - (let* ((to (or to (point))) - (to-line (line-number-at-pos to)) - (from-line (progn - (goto-char (1+ (or from containing-sexp))) - (line-number-at-pos))) - max-col) - (while (< (line-number-at-pos) to-line) - (forward-line) - (back-to-indentation) - ;; Ignore the line with the function call, the line to be - ;; indented, and empty lines. - (unless (or (>= (line-number-at-pos) to-line) - (looking-at "[ \t]*\\($\\|#\\)")) - (let ((indent (cond - ;; First line: minimum indent is right after ( - ((= (line-number-at-pos) from-line) - (save-excursion - (goto-char (1+ containing-sexp)) - (current-column))) - ;; Handle lines starting with a comma - ((save-excursion - (looking-at ",")) - (+ (current-indentation) 2)) - (t - (current-indentation))))) - (setq max-col (min indent (or max-col indent)))))) - max-col)) - -;; Move to leftmost side of a call (either the first letter of its -;; name or its closing delim) -(defun ess-move-to-leftmost-side () - (when (or (looking-at "[({]") - (ess-behind-call-p)) - (ess-save-excursion-when-nil - (let ((start-col (current-column))) - (skip-chars-forward "^{[(") - (forward-char) - (ess-up-list) - (forward-char -1) - (< (current-column) start-col))))) - -(defun ess-max-col () - (let ((max-col (point))) - (save-excursion - (while (< (point) indent-point) - (unless (and ess-indent-with-fancy-comments - (looking-at "### ")) - (setq max-col (min max-col (current-column)))) - (forward-line) - (back-to-indentation))) - max-col)) - -(defun ess-calculate-indent--prefixed-block-curly () - (when (looking-at "{") - (ess-save-excursion-when-nil - (let ((block-type (ess-climb-block-prefix))) - (cond ((ess-save-excursion-when-nil - (and (memq 'fun-decl-opening ess-indent-from-lhs) - (string= block-type "function") - (ess-climb-operator) - (ess-behind-assignment-op-p) - (ess-climb-expression))) - (current-column)) - ((= (save-excursion - (back-to-indentation) - (point)) - (point)) - (ess-calculate-indent--continued))))))) - -(defun ess-calculate-indent--continued () - "If a continuation line, return an indent of this line, otherwise nil." - (save-excursion - (let* ((cascade (eq (ess-offset-type 'continued) 'cascade)) - (climbed (ess-climb-continuations cascade)) - max-col) - (when climbed - (cond - ;; Overridden calls - ((and ess-align-continuations-in-calls - (not (eq climbed 'def-op)) - containing-sexp - (save-excursion - (goto-char containing-sexp) - (looking-at "[[(]"))) - (setq max-col (ess-max-col)) - (ess-move-to-leftmost-side) - (+ (min (current-column) max-col) - (if (eq climbed 'def-op) - (ess-offset 'continued) - 0))) - ;; Regular case - (t - (let ((first-indent (or (eq climbed 'def-op) - (save-excursion - (when (ess-ahead-closing-p) - (ess-climb-expression)) - (not (ess-climb-continuations cascade)))))) - ;; Record all indentation levels between indent-point and - ;; the line we climbed. Some lines may have been pushed off - ;; their natural indentation. These become the new - ;; reference. - (setq max-col (ess-max-col)) - ;; Indenting continuations from the front of closing - ;; delimiters looks better - (when - (ess-ahead-closing-p) - (backward-char)) - (+ (min (current-column) max-col) - (cond - ((eq (ess-offset-type 'continued) 'cascade) - (ess-offset 'continued)) - (first-indent - (ess-offset 'continued)) - (t - 0)))))))))) - -(defun ess-calculate-indent--nested-calls () - (when ess-align-nested-calls - (let ((calls (mapconcat 'identity ess-align-nested-calls "\\|")) - match) - (save-excursion - (and containing-sexp - (looking-at (concat "\\(" calls "\\)(")) - (setq match (match-string 1)) - (goto-char containing-sexp) - (looking-at "(") - (ess-backward-sexp) - (looking-at (concat match "(")) - (current-column)))))) - - -;;;*;;; Call filling engine - -;; Unroll arguments to a single line until closing marker is found. -(defun ess-fill--unroll-lines (bounds &optional jump-cont) - (let* ((last-pos (point-min)) - (containing-sexp (ess-containing-sexp-position)) - prefix-break) - (goto-char (car bounds)) - (goto-char (ess-code-end-position)) - (while (and (/= (point) last-pos) - (< (line-end-position) - (cadr bounds)) - (not prefix-break)) - (setq last-pos (point)) - ;; Check whether we ended up in a sub call. In this case, jump - ;; over it, otherwise, join lines. - (let ((contained-sexp (ess-containing-sexp-position))) - (cond ((and contained-sexp - containing-sexp - (not (= containing-sexp contained-sexp))) - (goto-char (1+ contained-sexp)) - (ess-up-list)) - ;; Jump over continued statements - ((and jump-cont (ess-ahead-operator-p 'strict)) - (ess-climb-token) - (ess-jump-continuations)) - ;; Jump over comments - ((looking-at "#") - (forward-line) - (funcall indent-line-function)) - (t - (join-line 1)))) - (goto-char (ess-code-end-position))) - (goto-char (car bounds)))) - -(defvar ess-fill--orig-pos nil - "Original position of cursor.") - -(defvar ess-fill--orig-state nil - "Backup of original code to cycle back to original state.") - -(defvar ess-fill--second-state nil - "Backup of code produce by very first cycling. -If this is equal to orig-state, no need to cycle back to original -state.") - -(defvar ess-fill--style-level nil - "Filling style used in last cycle.") - -(defun ess-fill--substring (bounds) - (buffer-substring (car bounds) (marker-position (cadr bounds)))) - -;; Detect repeated commands -(defun ess-fill-style (type bounds) - (let ((max-level - ;; This part will be simpler once we have the style alist - (cond ((eq type 'calls) - ;; No third style either when ess-offset-arguments is - ;; set to 'open-delim, or when ess-fill-calls-newlines - ;; is nil and no numeric prefix is given - (if (and (not (eq (ess-offset-type 'arguments) - 'open-delim)) - (or ess-fill-calls-newlines - (numberp current-prefix-arg))) - 3 - 2)) - ((eq type 'continuations) - 2)))) - (if (not (memq last-command '(fill-paragraph-or-region - fill-paragraph))) - (progn - ;; Record original state on first cycling - (setq ess-fill--orig-state (ess-fill--substring bounds)) - (setq ess-fill--orig-pos (point)) - (setq ess-fill--second-state nil) - (setq ess-fill--style-level 1)) - ;; Also record state on second cycling - (when (and (= ess-fill--style-level 1) - (null ess-fill--second-state)) - (setq ess-fill--second-state (ess-fill--substring bounds))) - (cond ((>= ess-fill--style-level max-level) - (let ((same-last-and-orig (string= (ess-fill--substring bounds) - ess-fill--orig-state)) - (same-2nd-and-orig (string= ess-fill--orig-state - ess-fill--second-state))) - ;; Avoid cycling to the same state twice - (cond ((and same-last-and-orig - same-2nd-and-orig) - (setq ess-fill--style-level 2)) - ((or same-last-and-orig - same-2nd-and-orig) - (setq ess-fill--style-level 1)) - (t - (setq ess-fill--style-level 0))))) - (ess-fill--style-level - (setq ess-fill--style-level (1+ ess-fill--style-level)))))) - ess-fill--style-level) - -(defun ess-fill-args (&optional style) - (let ((start-pos (point-min)) - (bounds (ess-args-bounds 'marker)) - ;; Set undo boundaries manually - (undo-inhibit-record-point t) - last-pos last-newline prefix-break - infinite) - (when (not bounds) - (error "Could not find function bounds")) - (setq style (or style (ess-fill-style 'calls bounds))) - (if (= style 0) - (progn - (delete-region (car bounds) (marker-position (cadr bounds))) - (insert ess-fill--orig-state) - ;; Restore the point manually. (save-excursion) wouldn't - ;; work here because we delete the text rather than just - ;; modifying it. - (goto-char ess-fill--orig-pos) - (message "Back to original formatting")) - (when ess-blink-refilling - (ess-blink-region (nth 2 bounds) - (1+ (marker-position (cadr bounds))))) - (undo-boundary) - (save-excursion - (ess-fill--unroll-lines bounds t) - (cond - ;; Some styles start with first argument on a newline - ((and (memq style '(2 4)) - ess-fill-calls-newlines - (not (looking-at "[ \t]*#"))) - (newline-and-indent)) - ;; Third level, start a newline after N arguments - ((and (= style 3) - (not (looking-at "[ \t]*#"))) - (let ((i (if (numberp current-prefix-arg) - current-prefix-arg - 1))) - (while (and (> i 0) - (ess-jump-arg) - (ess-jump-char ",")) - (setq i (1- i)))) - (newline-and-indent))) - (ess-fill-args--roll-lines) - ;; Reindent surrounding context - (ess-indent-call (car bounds))) - ;; Signal marker for garbage collection - (set-marker (cadr bounds) nil) - (undo-boundary)))) - -(defun ess-fill-args--roll-lines () - (while (and (not (looking-at "[])]")) - (/= (point) (or last-pos 1)) - (not infinite)) - (setq prefix-break nil) - ;; Record start-pos as future breaking point to avoid breaking - ;; at `=' sign - (while (looking-at "[ \t]*[\n#]") - (forward-line) - (back-to-indentation)) - (setq start-pos (point)) - (while (and (< (current-column) fill-column) - (not (looking-at "[])]")) - (/= (point) (or last-pos 1)) - ;; Break after one pass if prefix is active - (not prefix-break)) - (when (memq style '(2 3)) - (setq prefix-break t)) - (ess-jump-token ",") - (setq last-pos (point)) - ;; Jump expression and any continuations. Reindent all lines - ;; that were jumped over - (let ((cur-line (line-number-at-pos)) - end-line) - (cond ((ess-jump-arg) - (setq last-newline nil)) - ((ess-token-after= ",") - (setq last-newline nil) - (setq last-pos (1- (point))))) - (save-excursion - (when (< cur-line (line-number-at-pos)) - (setq end-line (line-number-at-pos)) - (ess-goto-line (1+ cur-line)) - (while (and (<= (line-number-at-pos) end-line) - (/= (point) (point-max))) - (funcall indent-line-function) - (forward-line)))))) - (when (or (>= (current-column) fill-column) - prefix-break - ;; Ensures closing delim on a newline - (and (= style 4) - (looking-at "[ \t]*[])]") - (setq last-pos (point)))) - (if (and last-pos (/= last-pos start-pos)) - (goto-char last-pos) - (ess-jump-char ",")) - (cond ((looking-at "[ \t]*[#\n]") - (forward-line) - (funcall indent-line-function) - (setq last-newline nil)) - ;; With levels 2 and 3, closing delim goes on a newline - ((looking-at "[ \t]*[])]") - (when (and (memq style '(2 3 4)) - ess-fill-calls-newlines - (not last-newline)) - (newline-and-indent) - ;; Prevent indenting infinitely - (setq last-newline t))) - ((not last-newline) - (newline-and-indent) - (setq last-newline t)) - (t - (setq infinite t)))))) - -(defun ess-fill-continuations (&optional style) - (let ((bounds (ess-continuations-bounds 'marker)) - (undo-inhibit-record-point t) - (last-pos (point-min)) - last-newline infinite) - (when (not bounds) - (error "Could not find statements bounds")) - (setq style (or style (ess-fill-style 'continuations bounds))) - (if (= style 0) - (progn - (delete-region (car bounds) (marker-position (cadr bounds))) - (insert ess-fill--orig-state) - (goto-char ess-fill--orig-pos) - (message "Back to original formatting")) - (when ess-blink-refilling - (ess-blink-region (car bounds) (marker-position (cadr bounds)))) - (undo-boundary) - (save-excursion - (ess-fill--unroll-lines bounds) - (while (and (< (point) (cadr bounds)) - (/= (point) (or last-pos 1)) - (not infinite)) - (setq last-pos (point)) - (when (and (ess-jump-expression) - (indent-according-to-mode) - (not (> (current-column) fill-column))) - (setq last-newline nil)) - (ess-jump-operator) - (if (or (and (> (current-column) fill-column) - (goto-char last-pos)) - (= style 2)) - (progn - (ess-jump-operator) - (unless (= (point) (cadr bounds)) - (when last-newline - (setq infinite t)) - (newline-and-indent) - (setq last-newline t))) - (setq last-newline nil))) - (ess-indent-call (car bounds))) - (set-marker (cadr bounds) nil) - (undo-boundary)))) - - - -;;;*;;; Inferior R mode - -(defvar inferior-ess-r-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\M-\r" #'ess-dirs) - (define-key map (kbd "C-c C-=") #'ess-cycle-assign) - (define-key map (kbd "C-c C-.") 'ess-rutils-map) - map) - "Keymap for `inferior-ess-r-mode'.") - -;; TOTHINK: Prevent string delimiting characters from messing up output in the -;; inferior buffer -(defvar inferior-ess-r-mode-syntax-table - (let ((table (copy-syntax-table ess-r-mode-syntax-table))) - (modify-syntax-entry ?% "." table) - (modify-syntax-entry ?\' "." table) - table) - "Syntax table for `inferior-ess-r-mode'.") - -(define-derived-mode inferior-ess-r-mode inferior-ess-mode "iESS" - "Major mode for interacting with inferior R processes." - :group 'ess-proc - (ess-setq-vars-local ess-r-customize-alist) - (setq-local ess-font-lock-keywords 'inferior-ess-r-font-lock-keywords) - (setq-local comint-process-echoes (eql ess-eval-visibly t)) - (setq-local comint-prompt-regexp inferior-S-prompt) - (setq comint-input-sender 'inferior-ess-r-input-sender) - (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first - (add-hook 'completion-at-point-functions 'ess-r-object-completion nil 'local) - (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local) - (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local) - ;; eldoc - (add-function :before-until (local 'eldoc-documentation-function) - #'ess-r-eldoc-function) - (when ess-use-eldoc (eldoc-mode)) - ;; auto-complete - (ess--setup-auto-complete ess-r-ac-sources t) - ;; company - (ess--setup-company ess-r-company-backends t) - (setq comint-get-old-input #'inferior-ess-get-old-input) - (add-hook 'comint-input-filter-functions 'ess-search-path-tracker nil 'local)) - - - -;;;*;;; R Help mode - -(defvar ess-r-help-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map (make-composed-keymap button-buffer-map - ess-help-mode-map)) - (define-key map "s<" #'beginning-of-buffer) - (define-key map "s>" #'end-of-buffer) - (define-key map "sa" #'ess-skip-to-help-section) - (define-key map "sd" #'ess-skip-to-help-section) - (define-key map "sD" #'ess-skip-to-help-section) - (define-key map "st" #'ess-skip-to-help-section) - (define-key map "se" #'ess-skip-to-help-section) - (define-key map "sn" #'ess-skip-to-help-section) - (define-key map "sr" #'ess-skip-to-help-section) - (define-key map "ss" #'ess-skip-to-help-section) - (define-key map "su" #'ess-skip-to-help-section) - (define-key map "sv" #'ess-skip-to-help-section) - map) - "Keymap for `ess-r-help-mode'.") - -(cl-defmethod ess--help-major-mode (&context (ess-dialect "R")) - (ess-r-help-mode)) - -(define-derived-mode ess-r-help-mode ess-help-mode "R Help" - "Major mode for help buffers." - :group 'ess-help - (setq ess-dialect "R" - ess-help-sec-regex ess-help-r-sec-regex - ess-help-sec-keys-alist ess-help-r-sec-keys-alist ; TODO: Still necessary? - inferior-ess-help-command inferior-ess-r-help-command) - (ess-r-help-add-links)) - -(defun ess-r-help-usage-objects () - "Return a list of objects in the usage section for the current help buffer. -In other words, if in the help buffer for \"qt\", return - -'((\"dt\" \"x\" \"df\" \"ncp\" \"log\") - (\"pt\" \"q\" \"df\" \"ncp\" \"lower.tail\" \"log.p\") - (\"qt\" \"p\" \"df\" \"ncp\" \"lower.tail\" \"log.p\") - (\"rt\" \"n\" \"df\" \"ncp\")). - -If the current buffer does not have a usage section, return nil." - (unless (derived-mode-p 'ess-r-help-mode) - (error "Not an R help buffer")) - (save-excursion - (save-restriction - (let (usage-objects) - (widen) - (goto-char (point-min)) - ;; Narrow the buffer to just the "Usage" section - (when-let ((usage-beg (re-search-forward "^Usage:" nil t)) - (usage-end (re-search-forward "^[^[:space:]]" nil t))) - (forward-line -1) - (narrow-to-region usage-beg (point)) - (goto-char (point-min)) - ;; Match objects until a parens - (while (re-search-forward (rx bol (0+ whitespace) (not (syntax comment-delimiter)) - (group (1+ (not (any "("))))) - usage-end t) - (push (match-string-no-properties 1) usage-objects) - ;; Skip past function arguments - (forward-list))) - (when usage-objects - ;; Get arguments: - (setq usage-objects - (mapcar (lambda (u) (cons u (ess-get-words-from-vector (concat "names(formals(" u "))\n")))) - usage-objects))) - (nreverse usage-objects))))) - -(define-button-type 'ess-r-help-link - 'follow-link t - 'action (lambda (_) (ess-r-help-button-action))) - -(defun ess-r-help-button-action () - "Display help for button at point." - (let ((text (get-text-property (point) 'ess-r-help-link-text))) - (ess-display-help-on-object text))) - -(defun ess-r-help-add-links () - "Add links to the help buffer." - (let ((help-topics (when (ess-process-live-p) - (ess-help-get-topics ess-local-process-name))) - (inhibit-read-only t) - (usage-objects (ess-flatten-list (ess-r-help-usage-objects)))) - (save-excursion - ;; Search for fancy quotes only. If users have - ;; options(useFancyQuotes) set to something other than TRUE this - ;; probably won't work. If it's FALSE, R outputs ascii ', but - ;; searching through the whole buffer takes too long. - (while (re-search-forward "‘\\([^[:space:]]+?\\)’" nil t) - (let* ((text (match-string 1)) - (text (if (string-match-p ".*()\\'" text) - (substring text nil (- (length text) 2)) - text))) - (when (and (member text help-topics) - (not (member text usage-objects)) - (not (member text usage-objects))) - (delete-region (match-beginning 0) (match-end 0)) - (insert-text-button text - 'ess-r-help-link-text text - 'type 'ess-r-help-link - 'help-echo (format "mouse-2, RET: Help on %s" text)))))))) - -(cl-defmethod ess--display-vignettes-override (all &context (ess-dialect "R")) - "Display R vignettes in ess-help-like buffer.. -With (prefix) ALL non-nil, use `vignette(*, all=TRUE)`, i.e., -from all installed packages, which can be very slow." - (inferior-ess-r-force) - (let* ((vslist (with-current-buffer - (ess-command - (format ".ess_vignettes(%s)\n" (if all "TRUE" ""))) - (goto-char (point-min)) - (when (re-search-forward "(list" nil t) - (goto-char (match-beginning 0)) - (ignore-errors (eval (read (current-buffer))))))) - (proc-name ess-current-process-name) - (alist ess-local-customize-alist) - (remote (file-remote-p default-directory)) - (buff (get-buffer-create (format "*[%s]vignettes*" ess-dialect))) - (inhibit-modification-hooks t) - (inhibit-read-only t)) - (with-current-buffer buff - (setq buffer-read-only nil) - (delete-region (point-min) (point-max)) - (ess-setq-vars-local (eval alist)) - (setq ess-local-process-name proc-name) - (ess--help-major-mode) - (setq ess-help-sec-regex "^\\w+:$" - ess-help-type 'vignettes) - (set-buffer-modified-p 'nil) - (goto-char (point-min)) - (dolist (el vslist) - (let ((pack (car el))) - (insert (format "\n\n%s:\n\n" (propertize pack 'face 'underline))) - (dolist (el2 (cdr el)) - (let ((path (if remote - (with-no-warnings - ;; Have to wrap this in with-no-warnings because - ;; otherwise the byte compiler complains about - ;; calling tramp-make-tramp-file-name with an - ;; incorrect number of arguments on Both 26+ and 25 emacses. - (if (>= emacs-major-version 26) - (with-parsed-tramp-file-name default-directory nil - (tramp-make-tramp-file-name method user domain host port (nth 1 el2))) - (with-parsed-tramp-file-name default-directory nil - (tramp-make-tramp-file-name method user host (nth 1 el2))))) - (nth 1 el2)))) - (insert-text-button "Pdf" - 'mouse-face 'highlight - 'action (if remote - #'ess--action-open-in-emacs - #'ess--action-R-open-vignette) - 'follow-link t - 'vignette (file-name-sans-extension (nth 2 el2)) - 'package pack - 'help-echo (concat path "/doc/" (nth 2 el2))) - (insert " ") - (insert-text-button "Rnw" - 'mouse-face 'highlight - 'action #'ess--action-open-in-emacs - 'follow-link t - 'help-echo (concat path "/doc/" (nth 3 el2))) - (insert " ") - (insert-text-button "R" - 'mouse-face 'highlight - 'action #'ess--action-open-in-emacs - 'follow-link t - 'help-echo (concat path "/doc/" (nth 4 el2))) - (insert (format "\t%s\n" (nth 0 el2))))))) - (goto-char (point-min)) - (insert (propertize "\t\t**** Vignettes ****\n" 'face 'bold-italic)) - (unless (eobp) (delete-char 1)) - (setq buffer-read-only t)) - (ess-display-help buff))) - - - -;; Support for listing R packages - -(define-obsolete-variable-alias 'ess-rutils-buf 'ess-r-package-menu-buf "ESS 19.04") -(define-obsolete-variable-alias 'ess-rutils-mode-map 'ess-r-package-menu-mode-map "ESS 19.04") -(define-obsolete-function-alias 'ess-rutils-mode #'ess-r-package-menu-mode "ESS 19.04") - -(defvar ess-rutils-map - (let ((map (define-prefix-command 'ess-rutils-map))) - (define-key map "l" #'ess-r-package-list-local-packages) - (define-key map "r" #'ess-r-package-list-available-packages) - (define-key map "u" #'ess-r-package-update-packages) - (define-key map "o" #'ess-rdired) - (define-key map "d" #'ess-change-directory) - (define-key map "H" #'ess-rutils-html-docs) - map)) - -(easy-menu-define ess-rutils-mode-menu inferior-ess-mode-menu - "Package management." - '("Package management" - ["List local packages" ess-r-package-list-local-packages t] - ["List available packages" ess-r-package-list-available-packages t] - ["Update packages" ess-r-package-update-packages t])) - -(easy-menu-add-item inferior-ess-mode-menu nil ess-rutils-mode-menu "Utils") -(easy-menu-add-item ess-mode-menu nil ess-rutils-mode-menu "Process") - -(defvar ess-r-package-menu-buf "*R packages*" - "Name of buffer to display R packages in.") - -(defvar ess-r-package-menu-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "l" #'ess-r-package-load) - (define-key map "i" #'ess-r-package-mark-install) - (define-key map "x" #'ess-r-package-execute-marks) - (define-key map "u" #'ess-r-package-unmark) - map) - "Keymap for `ess-rutils-mode'.") - -(define-derived-mode ess-r-package-menu-mode tabulated-list-mode "R utils" - "Major mode for `ess-rutils-local-pkgs' and `ess-rutils-repos-pkgs'." - :group 'ess-R - (setq ess-dialect "R") - (setq mode-name (concat "R packages: " ess-local-process-name)) - (setq tabulated-list-padding 2) - (setq tabulated-list-format - `[("Name" 10 t) - ("Description" 50 nil) - ("Version" 5 t)]) - (tabulated-list-init-header)) - -(define-obsolete-function-alias 'ess-rutils-local-pkgs #'ess-r-package-list-local-packages "ESS 19.04") - -(defun ess-r-package-list-local-packages () - "List all packages in all libraries." - (interactive) - (ess-r-package--list-packages (concat ".ess.rutils.ops <- options(width = 10000);" - "print(installed.packages(fields=c(\"Title\"))[, c(\"Title\", \"Version\")]);" - "options(.ess.rutils.ops); rm(.ess.rutils.ops);" - "\n"))) - -(defun ess-r-package--list-packages (cmd) - "Use CMD to list packages." - (let ((process ess-local-process-name) - des-col-beginning des-col-end entries) - (with-current-buffer (ess-command cmd (get-buffer-create " *ess-rutils-pkgs*")) - (goto-char (point-min)) - (delete-region (point) (1+ (point-at-eol))) - ;; Now we have a buffer with package name, description, and - ;; version. description and version are surrounded by quotes, - ;; description is separated by whitespace. - (re-search-forward "\\>[[:space:]]+") - (setq des-col-beginning (current-column)) - (goto-char (point-at-eol)) - ;; Unless someone has a quote character in their package version, - ;; two quotes back will be the end of the package description. - (dotimes (_ 2) (search-backward "\"")) - (re-search-backward "[[:space:]]*") - (setq des-col-end (current-column)) - (beginning-of-line) - (while (not (eobp)) - (beginning-of-line) - (let* ((name (string-trim (buffer-substring - (point) - (progn (forward-char (1- des-col-beginning)) - (point))))) - (description (string-trim (buffer-substring - (progn (forward-char 1) - (point)) - (progn (forward-char (- des-col-end des-col-beginning)) - (point))))) - (version (buffer-substring - (progn (end-of-line) - (search-backward "\"") - (search-backward "\"") - (forward-char 1) - (point)) - (progn (search-forward "\"") - (backward-char 1) - (point))))) - (push - (list name - `[(,name - help-echo "mouse-2, RET: help on this package" - action ess-rutils-help-on-package) - ,description - ,version]) - entries) - (forward-line))) - (pop-to-buffer ess-rutils-buf) - (setq ess-local-process-name process) - (setq tabulated-list-entries entries) - (ess-r-package-menu-mode) - (tabulated-list-print)))) - -(define-obsolete-function-alias 'ess-rutils-loadpkg #'ess-r-package-load "ESS 19.04") -(defun ess-r-package-load () - "Load package from a library." - (interactive) - (ess-execute (concat "library('" (tabulated-list-get-id) - "', character.only = TRUE)") - 'buffer)) - -(defun ess-rutils-help-on-package (&optional _button) - "Display help on the package at point." - (interactive) - ;; FIXME: Should go to a help buffer - (ess-execute (concat "help(" (tabulated-list-get-id) ", package = '" - (tabulated-list-get-id)"')") - 'buffer)) - -(define-obsolete-function-alias 'ess-rutils-repos-pkgs #'ess-r-package-list-available-packages "ESS 19.04") -(defun ess-r-package-list-available-packages () - "List available packages. -Use the repositories as listed by getOptions(\"repos\") in the -current R session." - (interactive) - (ess-r-package--list-packages (concat ".ess.rutils.ops <- options(width = 10000);" - "print(available.packages(fields=c(\"Title\"))[, c(\"Title\", \"Version\")]);" - "options(.ess.rutils.ops); rm(.ess.rutils.ops);" - "\n"))) - -(define-obsolete-function-alias 'ess-rutils-mark-install #'ess-r-package-mark-install "ESS 19.04") -(defun ess-r-package-mark-install () - "Mark the current package for installing." - (interactive) - (tabulated-list-put-tag "i" t)) - -(define-obsolete-function-alias 'ess-rutils-unmark #'ess-r-package-unmark "ESS 19.04") -(defun ess-r-package-unmark () - "Unmark the packages." - (interactive) - (tabulated-list-put-tag " " t)) - -(define-obsolete-function-alias 'ess-rutils-execute-marks #'ess-r-package-execute-marks "ESS 19.04") -(defun ess-r-package-execute-marks () - "Perform all marked actions." - (interactive) - ;; Install - (save-excursion - (let ((cmd "install.packages(c(") - pkgs) - (goto-char (point-min)) - (while (not (eobp)) - (when (looking-at-p "i") - (setq pkgs (concat "\"" (tabulated-list-get-id) "\", " pkgs)) - (tabulated-list-put-tag " ")) - (forward-line)) - (if pkgs - (progn (setq pkgs (substring pkgs 0 (- (length pkgs) 2))) - (setq cmd (concat cmd pkgs "))")) - (ess-execute cmd 'buffer)) - (message "No packages marked for install"))))) - -(define-obsolete-function-alias 'ess-rutils-update-pkgs #'ess-r-package-update-packages "ESS 19.04") -(defun ess-r-package-update-packages (lib repo) - "Update packages in library LIB and repo REPO. -This also uses checkBuilt=TRUE to rebuild installed packages if -needed." - (interactive - (list (ess-completing-read "Library to update: " (ess-get-words-from-vector - "as.character(.libPaths())\n")) - (ess-completing-read "Repo: " (ess-get-words-from-vector - "as.character(getOption(\"repos\"))\n")))) - (ess-execute (format "update.packages(lib.loc='%s', repos='%s', ask=FALSE, checkBuilt=TRUE)" lib repo) 'buffer)) - -(define-obsolete-function-alias 'ess-rutils-apropos #'ess-display-help-apropos "ESS 19.04") - -;; Miscellaneous helper functions - -(defun ess-rutils-rm-all () - "Remove all R objects." - (interactive) - (when (y-or-n-p "Delete all objects? ") - (ess-execute "rm(list=ls())" 'buffer))) - -(defun ess-rutils-load-wkspc (file) - "Load workspace FILE into R." - (interactive "fFile with workspace to load: ") - (ess-execute (concat "load('" file "')") 'buffer)) - -(defun ess-rutils-save-wkspc (file) - "Save FILE workspace as file.RData." - (interactive "FSave workspace to file (no extension): ") - (ess-execute (concat "save.image('" file ".RData')") 'buffer)) - -(defun ess-rutils-quit () - "Kill the ess-rutils buffer and return to the iESS buffer." - (interactive) - (ess-switch-to-end-of-ESS) - (kill-buffer ess-rutils-buf)) - -(defun ess-rutils-html-docs (&optional remote) - "Use `browse-url' to navigate R html documentation. -Documentation is produced by a modified help.start(), that -returns the URL produced by GNU R's http server. If called with a -prefix, the modified help.start() is called with update=TRUE. The -optional REMOTE argument should be a string with a valid URL for -the 'R_HOME' directory on a remote server (defaults to NULL)." - (interactive) - (let* ((update (if current-prefix-arg "update=TRUE" "update=FALSE")) - (remote (if (or (and remote (not (string= "" remote)))) - (concat "remote=" remote) "remote=NULL")) - (proc ess-local-process-name) - (rhtml (format ".ess_help_start(%s, %s)\n" update remote))) - (with-temp-buffer - (ess-command rhtml (current-buffer) nil nil nil (get-process proc)) - (let* ((begurl (search-backward "http://")) - (endurl (search-forward "index.html")) - (url (buffer-substring-no-properties begurl endurl))) - (browse-url url))))) - -(defun ess-rutils-rsitesearch (string) - "Search the R archives for STRING, and show results using `browse-url'. -If called with a prefix, options are offered (with completion) -for matches per page, sections of the archives to search, -displaying results in long or short formats, and sorting by any -given field. Options should be separated by value of -`crm-default-separator'." - (interactive "sSearch string: ") - (let ((site "https://search.r-project.org/cgi-bin/namazu.cgi?query=") - (okstring (replace-regexp-in-string " +" "+" string))) - (if current-prefix-arg - (let ((mpp (concat - "&max=" - (completing-read - "Matches per page: " - '(("20" 1) ("30" 2) ("40" 3) ("50" 4) ("100" 5))))) - (format (concat - "&result=" - (completing-read - "Format: " '(("normal" 1) ("short" 2)) - nil t "normal" nil "normal"))) - (sortby (concat - "&sort=" - (completing-read - "Sort by: " - '(("score" 1) ("date:late" 2) ("date:early" 3) - ("field:subject:ascending" 4) - ("field:subject:decending" 5) - ("field:from:ascending" 6) ("field:from:decending" 7) - ("field:size:ascending" 8) ("field:size:decending" 9)) - nil t "score" nil "score"))) - (restrict (concat - "&idxname=" - (mapconcat - 'identity - (completing-read-multiple - "Limit search to: " - '(("Rhelp02a" 1) ("functions" 2) - ("docs" 3) ("Rhelp01" 4)) - nil t "Rhelp02a,functions,docs" nil - "Rhelp02a,functions,docs") "&idxname=")))) - (browse-url (concat site okstring mpp format sortby restrict))) - (browse-url (concat site okstring "&max=20&result=normal&sort=score" - "&idxname=Rhelp02a&idxname=functions&idxname=docs"))))) - -(defun ess-rutils-help-search (string) - "Search for STRING using help.search()." - (interactive "sString to search for? ") - (let ((proc ess-local-process-name)) - (pop-to-buffer "foobar") - (ess-command (concat "help.search('" string "')\n") - (current-buffer) nil nil nil (get-process proc)))) - -(make-obsolete 'ess-rutils-rhtml-fn "overwrite .ess_help_start instead." "ESS 18.10") - - -;; Create functions that can be called for running different versions -;; of R. -;; FIXME: Should be set in ess-custom -(setq ess-rterm-version-paths - (ess-flatten-list - (delete-dups - (if (not ess-directory-containing-R) - (if (getenv "ProgramW6432") - (let ((P-1 (getenv "ProgramFiles(x86)")) - (P-2 (getenv "ProgramW6432"))) - (nconc - ;; Always 32 on 64 bit OS, nil on 32 bit OS - (ess-find-rterm (concat P-1 "/R/") "bin/Rterm.exe") - (ess-find-rterm (concat P-1 "/R/") "bin/i386/Rterm.exe") - - ;; Keep this both for symmetry and because it can happen: - (ess-find-rterm (concat P-1 "/R/") "bin/x64/Rterm.exe") - - ;; Always 64 on 64 bit OS, nil on 32 bit OS - (ess-find-rterm (concat P-2 "/R/") "bin/Rterm.exe") - (ess-find-rterm (concat P-2 "/R/") "bin/i386/Rterm.exe") - (ess-find-rterm (concat P-2 "/R/") "bin/x64/Rterm.exe"))) - (let ((PF (getenv "ProgramFiles"))) - (nconc - ;; Always 32 on 32 bit OS, depends on 32 or 64 process on 64 bit OS - (ess-find-rterm (concat PF "/R/") "bin/Rterm.exe") - (ess-find-rterm (concat PF "/R/") "bin/i386/Rterm.exe") - (ess-find-rterm (concat PF "/R/") "bin/x64/Rterm.exe")))) - (let ((PF ess-directory-containing-R)) - (nconc - (ess-find-rterm (concat PF "/R/") "bin/Rterm.exe") - (ess-find-rterm (concat PF "/R/") "bin/i386/Rterm.exe") - (ess-find-rterm (concat PF "/R/") "bin/x64/Rterm.exe"))))))) -(ess-r-define-runners) - -;;*;; Provide and auto-loads - -;;;###autoload -(add-to-list 'auto-mode-alist '("/Makevars\\(\\.win\\)?$" . makefile-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("DESCRIPTION$" . conf-colon-mode)) - -(provide 'ess-r-mode) - -;;; Local variables: -;;; mode: emacs-lisp -;;; byte-compile-warnings: (not lexical) -;;; End: - -;;; ess-r-mode.el ends here diff --git a/elpa/ess-20191014.1343/ess-r-package.el b/elpa/ess-20191014.1343/ess-r-package.el deleted file mode 100644 index 88d1b33e..00000000 --- a/elpa/ess-20191014.1343/ess-r-package.el +++ /dev/null @@ -1,581 +0,0 @@ -;;; ess-r-package.el --- Package development mode for R. -*- lexical-binding: t; -*- - -;; Copyright (C) 2011-2015 Lionel Henry, Vitalie Spinu, A.J. Rossini, Richard -;; M. Heiberger, Martin Maechler, Kurt Hornik, Rodney Sparapani, and -;; Stephen Eglen. - -;; Author: Lionel Henry, Vitalie Spinu -;; Maintainer: ESS-core - -;; Keywords: languages, tools - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; see appropriate documentation section of ESS user manual - -;;; Code: -(require 'cl-lib) -(require 'ess-inf) - -(eval-when-compile - (require 'subr-x) - (require 'tramp)) -;; Silence the byte compiler, OK because this file is only loaded by -;; ess-r-mode and has no autoloads. -(defvar ess-r-customize-alist) -(declare-function inferior-ess-r-force "ess-r-mode") -(declare-function ess-r-get-evaluation-env "ess-r-mode") -(declare-function ess-r-set-evaluation-env "ess-r-mode") -(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) -;; This can be drop after dropping support for Emacs 25: -(declare-function tramp-file-name-localname "tramp" (cl-x)) - -(defvar ess-r-prompt-for-attached-pkgs-only nil - "If nil provide completion for all installed R packages. -If non-nil, only look for attached packages.") - -(define-obsolete-variable-alias 'ess-r-package-auto-set-evaluation-env 'ess-r-package-auto-enable-namespaced-evaluation "18.04") -(define-obsolete-variable-alias 'ess-r-package-auto-set-evaluation-env 'ess-r-package-auto-enable-namespaced-evaluation "18.04") -(defcustom ess-r-package-auto-enable-namespaced-evaluation t - "If non-nil, evaluation env is set to package env automatically. -See also `ess-r-set-evaluation-env' and `ess-r-evaluation-env'." - :group 'ess-r-package - :type 'boolean) - -(defvar-local ess-r-package--info-cache nil - "Current package info cache. -See `ess-r-package-info' for its structure.") - -(define-obsolete-variable-alias 'ess-r-package-library-path 'ess-r-package-library-paths "v18.04") -(defcustom ess-r-package-library-paths nil - "Default path to find user packages. -Can be either a string specifying a directory or a list of directories." - :group 'ess-r-package-library-paths - :type `(choice string (repeat string))) - -(defvar ess-r-package-root-file "DESCRIPTION" - "Presence of this file indicates the project's root.") - -(defvar ess-r-package-dirs - '(("R" . 1) - ("r" . 1) - ("tests" . 1) - ("testthat" . 2) - ("inst" . 1) - ("include" . 2) - ("src" . 1)) - "Alist of directories names and their depth in R package hierarchy. -This list is used to figure out whether the current file belongs -to an R package. If the file specified in `ess-r-package-root-file' -\(DESCRIPTION by default) is found at the presumed root directory -of the package, the current directory is considered to be part of -a R package.") - -(defvar ess-r-package-source-roots - '("R" "src" "tests" "inst/include") - "List of sub-directories within R package where source files are located. -All children of these directories are also considered source -containing directories. Use `ess-r-package-source-dirs' to get -all source dirs recursively within the current package.") - - -;;;*;;; Package Detection - -(defun ess-r-package-project (&optional dir) - "Return the current package as an Emacs project instance. -A project instance is a cons cell of the project type as symbol -and the project path as string. If DIR is provided, the package -is searched from that directory instead of `default-directory'." - (let ((pkg-info (ess-r-package-info dir))) - (when (car pkg-info) - (cons 'ess-r-package (plist-get pkg-info :root))))) - -(cl-defmethod project-roots ((project (head ess-r-package))) - "Return the project root for ESS R packages" - (list (cdr project))) - -(defun ess-r-package-name (&optional dir) - "Return the name of the current package as a string." - (plist-get (ess-r-package-info dir) :name)) - -(defun ess-r-package-info (&optional dir) - "Get the description of the R project in directory DIR. -Return an plist with the keys :name and :root. When not in a -package return '(nil). This value is cached buffer-locally for -efficiency reasons." - (if (and (null dir) (car ess-r-package--info-cache)) - ess-r-package--info-cache - (let* ((path (ess-r-package--find-package-path (or dir default-directory))) - (name (when path - (ess-r-package--find-package-name path))) - (info (if name - (list :name name - :root path) - '(nil)))) - ;; If DIR was supplied we cannot cache in the current buffer. - (if dir - info - (setq-local ess-r-package--info-cache info))))) - -(defun ess-r-package--all-source-dirs (dir) - (when (file-directory-p dir) - (cl-loop for f in (directory-files-and-attributes dir t "^[^.]") - if (cadr f) - append (cons (car f) (ess-r-package--all-source-dirs (car f)))))) - -(defun ess-r-package-source-dirs () - "Get paths within current R package with source files. -Return nil if not in a package. Search sub-directories listed in -`ess-r-package-source-roots' are searched recursively and -return all physically present directories." - (let ((pkg-root (plist-get (ess-r-package-info) :root))) - (when pkg-root - (let ((files (directory-files-and-attributes pkg-root t "^[^.]"))) - (cl-loop for f in files - if (and (cadr f) - (cl-some (lambda (el) (string-match-p (concat "/" el "$") (car f))) - ess-r-package-source-roots)) - append (cons (car f) - (ess-r-package--all-source-dirs (car f)))))))) - -(defun ess-r--select-package-name () - (inferior-ess-r-force) - (let ((pkgs (ess-get-words-from-vector - (format "print(.packages(%s), max = 1e6)\n" - (if ess-r-prompt-for-attached-pkgs-only "FALSE" "TRUE")))) - (current-pkg (ess-r-package-name))) - (let ((env (ess-r-get-evaluation-env))) - (when env - (setq pkgs (append '("*none*") pkgs)) - (when (equal env current-pkg) - (setq current-pkg "*none*")))) - (ess-completing-read "Package" pkgs nil nil nil nil current-pkg))) - -(defun ess-r-package--find-package-path (&optional dir) - "Get the root of R package in directory DIR. -DIR defaults to the current buffer's file name (if non-nil) or -`default-directory'. Root is determined by locating -`ess-r-package-root-file'. If the path looks like a tramp file, -remove the remote information." - (when-let ((path (cond - (dir) - ((buffer-file-name) - (file-name-directory (buffer-file-name))) - (t - default-directory))) - (pkg-path - (when path - (or - ;; First check current directory - (and (file-exists-p (expand-file-name ess-r-package-root-file path)) - path) - ;; Check for known directories in current path - (let ((current-dir (file-name-nondirectory (directory-file-name path))) - known-pkg-dir known-path presumptive-path) - (while (and path (not presumptive-path)) - (setq current-dir (file-name-nondirectory (directory-file-name path))) - (if (and (setq known-pkg-dir (assoc current-dir ess-r-package-dirs)) - (setq known-path (ess--parent-dir path (cdr known-pkg-dir))) - (file-exists-p (expand-file-name ess-r-package-root-file known-path))) - (setq presumptive-path known-path) - (setq path (ess--parent-dir path 1)))) - presumptive-path))))) - (if (file-remote-p pkg-path) - (tramp-file-name-localname (tramp-dissect-file-name pkg-path)) - (directory-file-name pkg-path)))) - -(defun ess-r-package--find-package-name (path) - (let ((file (expand-file-name ess-r-package-root-file path)) - (case-fold-search t)) - (when (file-exists-p file) - (with-temp-buffer - (insert-file-contents-literally file) - (goto-char (point-min)) - (when (re-search-forward "package: \\(.*\\)" nil t) - (match-string 1)))))) - - -;;;*;;; UI - -(defun ess-r-package-use-dir () - "Set process directory to current package directory." - (interactive) - (let ((pkg-root (plist-get (ess-r-package-info) :root))) - (if pkg-root - (ess-set-working-directory (abbreviate-file-name pkg-root)) - (user-error "Not in a project")))) - - -;;;*;;; Evaluation - -(defun ess-r-package-enable-namespaced-evaluation () - "Enable namespaced evaluation in current buffer. -Namespaced evaluation is enabled if -`ess-r-package-auto-enable-namespaced-evaluation' is non-nil." - (when ess-r-package-auto-enable-namespaced-evaluation - (let ((root (plist-get (ess-r-package-info) :root))) - ;; Check that we are in a file within R/ - (when (and root - default-directory - (> (length default-directory) (1+ (length root))) - (let ((subpath (substring default-directory - (1+ (length root)) - (length default-directory)))) - (string= (directory-file-name subpath) "R"))) - (ess-r-set-evaluation-env (ess-r-package-name)))))) - -(add-hook 'ess-r-mode-hook 'ess-r-package-enable-namespaced-evaluation) - -(defun ess-r-package-eval-linewise (command &optional msg p actions) - "Send COMMAND to R process. -COMMAND is a command string with %s placeholder for the -arguments. MSG is the message displayed in minibuffer with %s -placeholder for the package name. P is the value of universal -argument usually received from the upstream command and indicates -which action in ACTIONS list to perform; if 0 or nil, first -action, if 1 or (4) second if 2 or (16) third etc. ACTIONS is a -list of strings (R arguments), or functions which return R -arguments, or expressions which return R arguments." - (inferior-ess-r-force) - (let ((pkg-info (ess-r-package-info)) - (args (ess-r-command--build-args p actions))) - (unless (car pkg-info) - (user-error "Not in a package")) - (ess-project-save-buffers) - (message msg (plist-get pkg-info :name)) - (display-buffer (ess-get-process-buffer)) - (let ((pkg-path (concat "'" (abbreviate-file-name (plist-get pkg-info :root)) "'"))) - (ess-eval-linewise (format command (concat pkg-path args)))))) - -(defun ess-r-command--build-args (ix &optional actions) - (let* ((n (cond ((null ix) 0) - ((listp ix) (round (log (car ix) 4))) - ((integerp ix) ix) - (t (error "Invalid index")))) - (action (nth n actions)) - (args (cond ((null action) "") - ((stringp action) action) - ((functionp action) (funcall action)) - ((listp action) (eval action)) - (t (error "Invalid action"))))) - (if (string= "" args) - args - (concat ", " args)))) - - -;;;*;;; Devtools Integration - -(defun ess-r-devtools-load-package (&optional arg) - "Interface for `devtools::load_all()'. -With prefix ARG ask for extra args." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::load_all(%s)\n" "Loading %s" arg - '("" (read-string "Arguments: " "recompile = TRUE")))) - -(defun ess-r-devtools-unload-package () - "Interface to `devtools::unload()'." - (interactive) - (ess-r-package-eval-linewise - "devtools::unload(%s)\n" "Unloading %s")) - -(defun ess-r-devtools-check-package (&optional arg) - "Interface for `devtools::check()'. -With prefix ARG ask for extra args." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::check(%s)\n" "Checking %s" arg - '("" (read-string "Arguments: " "vignettes = FALSE")))) - -(defun ess-r-devtools-check-with-winbuilder (&optional arg) - "Interface for `devtools::buildwin()'. -With prefix ARG build with R-devel instead of R-patched." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::build_win(%s)\n" "Checking %s on CRAN's Windows server" arg - '("" "version = 'R-devel'"))) - -(defvar ess-r-rhub--history nil) -(declare-function ess-r-check-install-package "ess-r-mode.el") -(defun ess-r-rhub-check-package (&optional arg) - "Interface for `rhub::check()'. -With prefix ARG run with `valgrind = TRUE'." - (interactive "P") - (inferior-ess-r-force) - (ess-r-check-install-package "rhub") - (let* ((platforms (ess-get-words-from-vector "rhub::platforms()$name\n")) - (platform (completing-read "Platform: " platforms nil t nil - ess-r-rhub--history (car ess-r-rhub--history))) - (cmd (format "rhub::check_for_cran(%%s, platform = '%s')\n" platform)) - (msg (format "Checking %%s on RHUB (%s)" platform))) - (ess-r-package-eval-linewise cmd msg arg '("" "valgrind = TRUE")))) - -(defun ess-r-devtools-build (&optional arg) - "Interface for `devtools::build()'. -With prefix ARG, build with 'vignettes = FALSE'." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::build(%s)\n" "Building %s" arg - '("" "vignettes = FALSE"))) - -(defun ess-r-devtools-test-package (&optional arg) - "Interface for `devtools::test()'. -With prefix argument ARG, run tests on current file only." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::test(%s)\n" "Testing %s" arg - '("" ess-r-devtools--cur-file-filter))) - -(defun ess-r-devtools--cur-file-filter () - (let ((file (or (and buffer-file-name - (file-name-nondirectory buffer-file-name)) - (error "Buffer not visiting a file")))) - (format "filter = \"%s\"" - (if (string-match "test-\\([[:alnum:]_-]+\\)\\.[rR]" file) - (match-string-no-properties 1 file) - (file-name-base buffer-file-name))))) - -(defvar ess-r-devtools-revdep-check-cmd - "local({ - pkg_path <- %s - res <- devtools::revdep_check(pkg_path) - - if (file.exists(file.path(pkg_path, 'revdep'))) { - save_path <- file.path(pkg_path, 'revdep') - } else { - save_path <- file.path(pkg_path, '.metadata', 'revdep') - } - devtools::revdep_check_save_summary(res, save_path) - - logs_path <- file.path(save_path, 'logs') - if (!dir.exists(logs_path)) { - dir.create(logs_path) - } - devtools::revdep_check_save_logs(res, logs_path) -}) -") - -(defun ess-project-save-buffers () - "Offer to save modified files in the current project. -Respects `ess-save-silently', which see." - (let ((cur-proj ess-r-package--info-cache)) - (dolist (buf (buffer-list)) - (when-let ((file (buffer-file-name buf)) - (buf-proj (buffer-local-value 'ess-r-package--info-cache buf))) - (when (equal cur-proj buf-proj) - (ess-save-file file)))))) - -(defun ess-r-devtools-document-package (&optional arg) - "Interface for `devtools::document()'. -With prefix ARG ask for extra arguments." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::document(%s)\n" "Documenting %s" arg - '("" (read-string "Arguments: ")))) - -(defun ess-r-devtools-install-package (&optional arg) - "Interface to `devtools::install()'. -By default the installation is \"quick\" with arguments quick = -TRUE, upgrade = FALSE, build = FALSE. On prefix ARG -\\[universal-argument] install with the default -`devtools::install()' arguments." - (interactive "P") - (ess-r-package-eval-linewise - "devtools::install(%s)\n" "Installing %s" arg - '("quick = TRUE, build = FALSE, upgrade = FALSE, keep_source = TRUE" - (read-string "Arguments: " "keep_source = TRUE, force = TRUE")))) - -(defvar ess-r-devtools--install-github-history nil) -(defun ess-r-devtools-install-github (&optional arg) - "Interface to `devtools::install_github()'. -Asks for GitHub repository in the form of user/repo. Force -re-installation when called with a prefix ARG." - (interactive "P") - (let ((command "devtools::install_github(%s%s)") - (repo (format "'%s'" - (read-string "User/Repo: " nil - 'ess-r-devtools--install-github-history - (car ess-r-devtools--install-github-history)))) - (args (if arg - (ess-r-command--build-args 0 '((read-string "Arguments: " "force = TRUE"))) - ""))) - (inferior-ess-r-force) - (unless (derived-mode-p 'inferior-ess-mode) - (display-buffer (ess-get-process-buffer) - '(nil . ((inhibit-same-window . t))))) - (message "Installing %s from github" repo) - (ess-eval-linewise (format command repo args)))) - -(defun ess-r-devtools-create-package () - "Interface to `devtools::create()'. -Default location is determined by the first element of -`ess-r-package-library-paths'." - (interactive) - (let* ((command "devtools::create(\"%s\")") - (default-path (if (stringp ess-r-package-library-paths) - ess-r-package-library-paths - (car ess-r-package-library-paths))) - (path (read-directory-name "Path: " default-path))) - (ess-eval-linewise (format command path)))) - -(defun ess-r-devtools-execute-command (&optional arg) - "Asks with completion for a devtools command. -When called with prefix ARG asks for additional arguments." - (interactive "P") - (inferior-ess-r-force) - (let* ((devtools-funs (ess-get-words-from-vector ".ess_devtools_functions()\n")) - (fun (completing-read "Function: " devtools-funs)) - (command (format "devtools::%s(%%s)\n" fun))) - (ess-r-package-eval-linewise - command (format "Running %s" fun) arg - '("" (read-string "Arguments: "))))) - - -;;;*;;; Minor Mode - -(defcustom ess-r-package-auto-activate t - "If non-nil, `ess-r-package-mode' is turned on within R packages. -If 't' the minor mode auto-activates in R packages. See -`ess-r-package-exclude-modes' if you wish to inhibit -`ess-r-package-mode' in specific buffers." - :group 'ess-r-package - :type 'boolean) - -(defcustom ess-r-package-exclude-modes '(fundamental-mode) - "A list of modes where `ess-r-package' must not be activated. -The check is done with `derived-mode-p'." - :group 'ess-r-package - :type '(repeat symbol) - :package-version '(ess "18.10")) - -(defcustom ess-r-package-enter-hook nil - "Normal hook run on entering `ess-r-package-mode'." - :group 'ess-r-package - :type 'hook) - -(defcustom ess-r-package-exit-hook nil - "Normal hook run on exiting `ess-r-package-mode'." - :group 'ess-r-package - :type 'hook) - -(defcustom ess-r-package-mode-line - ;; FIXME Emacs 25.1: Use `when-let' - '(:eval (let ((pkg-name (ess-r-package-name))) - (when pkg-name - (format " [pkg:%s]" pkg-name)))) - "Mode line for ESS developer. -Set this variable to nil to disable the mode line entirely." - :group 'ess-r-package - :type 'sexp - :risky t) - -(defvar ess-r-package-mode-map - (let ((ess-r-package-mode-map (make-sparse-keymap))) - (define-key ess-r-package-mode-map "\C-c\C-w" 'ess-r-package-dev-map) - ess-r-package-mode-map)) - -(define-minor-mode ess-r-package-mode - "Minor mode for enabling R package development features. - -\\{ess-r-package-mode-map}" - :init-value nil - :keymap ess-r-package-mode-map - :lighter ess-r-package-mode-line - (if ess-r-package-mode - (progn - ;; Forward relevant R settings for interacting with inferior - ;; processes from any mode - (let ((vars '(ess-dialect - ess-setwd-command - ess-getwd-command - ess-quit-function - inferior-ess-reload-function))) - (mapc (lambda (var) - (set (make-local-variable var) - (eval (cdr (assq var ess-r-customize-alist))))) - vars)) - (add-hook 'project-find-functions #'ess-r-package-project) - (run-hooks 'ess-r-package-enter-hook)) - (remove-hook 'project-find-functions #'ess-r-package-project) - (run-hooks 'ess-r-package-exit-hook))) - -(add-hook 'after-change-major-mode-hook 'ess-r-package-auto-activate) - - -;;;*;;; Activation - -(defun ess-r-package-auto-activate () - "Activate developer if current file is part of a package." - (when (and ess-r-package-auto-activate - (or (buffer-name) default-directory) - (not (eq major-mode 'minibuffer-inactive-mode)) - (or - ;; users probably have these in fundamental mode - (member (buffer-name) '("DESCRIPTION" "NAMESPACE")) - (if ess-r-package-exclude-modes - (not (apply #'derived-mode-p ess-r-package-exclude-modes)) - t))) - (when (car (ess-r-package-info)) - (ess-r-package-mode 1)))) - -(defun ess-r-package-re-activate () - "Restart `ess-r-package-mode'. -First, deactivate package mode if active, and activate if in -package mode. Use this function if state of the buffer such as -`default-directory' has changed." - (when ess-r-package-mode - (ess-r-package-mode -1)) - (setq ess-r-package--info-cache nil) - (ess-r-package-auto-activate)) - -(defvar-local ess-r--old-default-dir nil) -(defun ess-r-package-default-directory-tracker (&rest _) - (unless (equal ess-r--old-default-dir default-directory) - (setq ess-r--old-default-dir default-directory) - (ess-r-package-re-activate))) - -(defun ess-r-package-activate-directory-tracker () - (add-hook 'after-change-functions 'ess-r-package-default-directory-tracker t t)) - -(add-hook 'shell-mode-hook 'ess-r-package-activate-directory-tracker t) -(add-hook 'eshell-mode-hook 'ess-r-package-activate-directory-tracker t) -(when (fboundp 'advice-add) - (require 'shell) - (advice-add 'shell-resync-dirs :after 'ess-r-package-re-activate)) - - -;;;*;;; Deprecated variables and functions -(defun ess-developer (&optional _val) - (error "As of ESS 16.04, `ess-developer' is deprecated. Use `ess-r-set-evaluation-env' instead")) - -(defalias 'ess-toggle-developer 'ess-developer) -(define-obsolete-function-alias 'ess-r-devtools-check-package-buildwin 'ess-r-devtools-check-with-winbuilder) -(define-obsolete-function-alias 'ess-r-devtools-ask 'ess-r-devtools-execute-command "18.04") - -(make-obsolete-variable 'ess-developer "Please use `ess-developer-select-package' and `ess-r-set-evaluation-env' instead." "16.04") -(make-obsolete-variable 'ess-developer-root-file "Please use `ess-r-package-root-file' instead." "16.04") -(make-obsolete-variable 'ess-developer-packages "Please use `ess-r-package-set-package' and `ess-r-set-evaluation-env' instead." "16.04") -(make-obsolete-variable 'ess-developer-load-on-add-commands "Please use `ess-r-package-set-package' and `ess-r-set-evaluation-env' instead." "16.04") -(make-obsolete-variable 'ess-developer-activate-in-package "Please use `ess-r-package-auto-activate' instead." "16.04") -(make-obsolete-variable 'ess-developer-enter-hook "Please use `ess-r-package-enter-hook' instead." "16.04") -(make-obsolete-variable 'ess-developer-exit-hook "Please use `ess-r-package-exit-hook' instead." "16.04") - - -(provide 'ess-r-package) - -;;; ess-r-package.el ends here diff --git a/elpa/ess-20191014.1343/ess-r-syntax.el b/elpa/ess-20191014.1343/ess-r-syntax.el deleted file mode 100644 index 58169aaf..00000000 --- a/elpa/ess-20191014.1343/ess-r-syntax.el +++ /dev/null @@ -1,1561 +0,0 @@ -;;; ess-r-syntax.el --- Utils to work with R code - -;; Copyright (C) 2015 Lionel Henry - -;; Author: Lionel Henry -;; Created: 12 Oct 2015 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; API is not yet stable. - -;;; Code: - -(require 'ess-utils) -(require 'regexp-opt) - -(eval-when-compile - (require 'cl-lib)) - - -;;*;; Utils - -;; The three following wrappers return t if successful, nil on error -(defun ess-backward-sexp (&optional N) - (ess-forward-sexp (- (or N 1)))) - -(defun ess-forward-sexp (&optional N) - (or N (setq N 1)) - (condition-case nil - (prog1 t - (goto-char (or (scan-sexps (point) N) - (buffer-end N)))) - (error nil))) - -(defun ess-up-list (&optional N) - (condition-case nil - (let (forward-sexp-function) - (progn (up-list N) t)) - (error nil))) - -(defun ess-backward-up-list (&optional N) - (ess-up-list (- (or N 1)))) - -(defun ess-forward-char (&optional N) - (unless (= (point) (point-max)) - (forward-char (or N 1)) - t)) - -(defun ess-backward-char (&optional N) - (unless (bobp) - (forward-char (- (or N 1))) - t)) - -(defun ess-goto-char (pos) - "Go to POS if it is non-nil. -If POS is nil, return nil. Otherwise return position itself." - (when pos - (goto-char pos))) - -(defun ess-looking-at (regex &optional newlines) - "Like `looking-at' but consumes blanks and comments first." - (save-excursion - (ess-skip-blanks-forward newlines) - (looking-at regex))) - -(defmacro ess-save-excursion-when-nil (&rest body) - (declare (indent 0) - (debug (&rest form))) - `(let ((orig-point (point))) - (cond ((progn ,@body)) - (t (prog1 nil - (goto-char orig-point)))))) - -(defmacro ess-while (test &rest body) - "Like `while' for TEST but return t when BODY gets executed once." - (declare (indent 1) - (debug (&rest form))) - `(let (executed) - (while ,test - (setq executed t) - ,@body) - executed)) - -(defmacro ess-at-indent-point (&rest body) - (declare (indent 0) - (debug (&rest form))) - `(save-excursion - (goto-char indent-point) - (back-to-indentation) - (progn ,@body))) - -(defvar containing-sexp) -(defmacro ess-at-containing-sexp (&rest body) - (declare (indent 0) - (debug (&rest form))) - '(when (not (bound-and-true-p containing-sexp)) - (error "Internal error: containing-sexp is nil or undefined")) - `(save-excursion - (goto-char containing-sexp) - (progn ,@body))) - -(defmacro ess-any (&rest forms) - "Evaluate all arguments and return non-nil if one of the arguments is non-nil. -This is useful to trigger side-effects. FORMS follows the same -syntax as arguments to `cond'." - (declare (indent 0) (debug nil)) - `(let ((forms (list ,@(mapcar (lambda (form) `(progn ,@form)) forms)))) - (cl-some 'identity (mapcar 'eval forms)))) - -(defun ess-char-syntax (string) - (char-to-string (char-syntax (string-to-char string)))) - - -;;*;; Tokenisation - -(defun ess-token-type (token) (car (nth 0 token))) -(defun ess-token-value (token) (cdr (nth 0 token))) -(defun ess-token-start (token) (car (nth 1 token))) -(defun ess-token-end (token) (cdr (nth 1 token))) - -(defun ess-token-refined-type (token) - (ess-token-type (ess-refine-token token))) - -(defun ess-token-after (&optional token) - "Return next TOKEN. -Cons cell containing the token type and string representation." - (save-excursion - (when token - (goto-char (ess-token-end token))) - (ess-jump-token))) - -(defun ess-token-before (&optional token) - "Return previous TOKEN. -Cons cell containing the token type and string representation." - (save-excursion - (when token - (goto-char (ess-token-start token))) - (ess-climb-token))) - -(defun ess-climb-token (&optional type string) - (ess-save-excursion-when-nil - (ess-escape-comment) - (ess-skip-blanks-backward t) - (let ((token (or (ess-climb-token--back) - (ess-climb-token--back-and-forth) - (progn (forward-char -1) (ess-token-after))))) - (if (or type string) - (when (ess-token= token type string) - token) - token)))) - -(defun ess-token--cons (type value) - (if (eq type 'self) - (cons value nil) - (cons type value))) - -(defun ess-climb-token--back () - (let* ((token-end (point)) - (token-type (if (bobp) - "buffer-start" - (ess-climb-token--operator))) - (token-value (buffer-substring-no-properties (point) token-end))) - (unless (null token-type) - (list (ess-token--cons token-type token-value) - (cons (point) token-end))))) - -(defsubst ess-climb-token--char (&rest chars) - (ess-while (and chars - (eq (char-before) (car chars)) - (ess-backward-char)) - (setq chars (cdr chars)))) - -;; Difficult to use regexps here because we want to match greedily -;; backward -(defun ess-climb-token--operator () - (when (pcase (char-before) - ((or `?+ `?/ `?^ `?~ `?? `?!) - (ess-backward-char)) - (`?= - (prog1 (ess-backward-char) - (or (ess-climb-token--char ?=) - (ess-climb-token--char ?!) - (ess-climb-token--char ?:) - (ess-climb-token--char ?>) - (ess-climb-token--char ?<)))) - ((or `?& `?| `?* `?@ `?$) - (prog1 (ess-backward-char) - (ess-climb-token--char (char-after)))) - (`?< - (ess-backward-char)) - (`?> - (prog1 (ess-backward-char) - (or (ess-climb-token--char ?-) - (and (looking-back "->" (- (point) 2)) - (goto-char (- (point) 2)))))) - (`?- - (prog1 (ess-backward-char) - (ess-climb-token--char ?< ?<))) - (`?: - (prog1 (ess-backward-char) - (ess-climb-token--char ?: ?:)))) - 'self)) - -(defun ess-climb-token--back-and-forth () - (let ((limit (point))) - (when (ess-skip-token-backward) - (save-restriction - (narrow-to-region (point) limit) - (ess-token-after))))) - -(defun ess-skip-token-backward () - (ess-save-excursion-when-nil - (cond - ;; Punctuation - ((memq (char-before) '(?, ?\;)) - (ess-backward-char)) - ;; Quoting delimiters - ((memq (char-syntax (char-before)) '(?\" ?$)) - (ess-backward-sexp)) - ;; Syntaxic delimiters - ((memq (char-syntax (char-before)) '(?\( ?\))) - (prog1 (ess-backward-char) - ;; Also skip double brackets - (ess-save-excursion-when-nil - (when (let ((current-delim (char-after))) - (ess-skip-blanks-backward) - (and (memq (char-before) '(?\[ ?\])) - (eq current-delim (char-before)))) - (ess-backward-char))))) - ;; Identifiers and numbers - ((/= (skip-syntax-backward "w_") 0))))) - -(defun ess-jump-token (&optional type string) - "Consume a token forward. -Return a cons cell containing the token type and the token string -content. Return nil when the end of the buffer is reached." - (ess-save-excursion-when-nil - (ess-skip-blanks-forward t) - (let* ((token-start (point)) - (token-type (or (ess-jump-token--regexps) - (ess-jump-token--literal) - (ess-jump-token--infix-op) - (ess-jump-token--punctuation) - (progn (forward-char) "unknown"))) - (token-value (buffer-substring-no-properties token-start (point)))) - (let ((token (list (ess-token--cons token-type token-value) - (cons token-start (point))))) - (if (or type string) - (when (ess-token= token type string) - token) - token))))) - -(defun ess-jump-token--literal () - (cond - ;; Simply assume anything starting with a digit is a number. May be - ;; too liberal but takes care of fractional numbers, integers such - ;; as 10L, etc. False positives are not valid R code anyway. - ((looking-at "[0-9]") - (ess-forward-sexp) - "number") - ((or (looking-at "\\sw\\|\\s_") - (eq (char-after) ?`)) - (ess-forward-sexp) - "identifier") - ((memq (char-after) '(?\" ?\')) - (ess-forward-sexp) - "string"))) - -(defun ess-jump-token--punctuation () - (or (when (= (point) (point-max)) - "buffer-end") - (pcase (char-after) - (`?\; - (forward-char) - 'self) - (`?, - (forward-char) - ;; Treat blanks after comma as part of an argument - (ess-skip-blanks-forward t) - ",")))) - -(defvar ess-r-prefix-keywords-list - '("if" "for" "while" "function")) - -(defvar ess-r-keywords-list - (append ess-r-prefix-keywords-list '("else"))) - -(defvar ess-r-delimiters-list - '("(" ")" "{" "}" "[" "]" "[[" "]]")) - -(defvar ess-r-operators-list - '("+" "-" "*" "/" "%%" "**" "^" - "&" "&&" "|" "||" "!" "?" "~" - "==" "!=" "<" "<=" ">=" ">" - "=" "<-" "<<-" "->" "->>" - "$" "@" ":" "::" ":::" ":=")) - -(defvar ess-r-keywords-re - (concat (regexp-opt ess-r-keywords-list) "\\_>")) - -(defvar ess-r-delimiters-re - (regexp-opt ess-r-delimiters-list)) - -(defvar ess-r-operators-re - (regexp-opt ess-r-operators-list)) - -(defun ess-jump-token--regexps () - (when (or (looking-at ess-r-keywords-re) - (looking-at ess-r-delimiters-re) - (looking-at ess-r-operators-re)) - (goto-char (match-end 0)) - 'self)) - -(defun ess-jump-token--infix-op () - (or (when (looking-at ess-r-operators-re) - (goto-char (match-end 0)) - 'self) - (when (eq (char-after) ?%) - (ess-forward-sexp) - "%infix%"))) - -(defun ess-escape-token () - (ess-escape-comment) - (ess-skip-blanks-forward) - (or (ess-escape-string) - (when (ess-token-delimiter-p (ess-token-after)) - (prog1 t - (mapc (lambda (delims) - (while (and (ess-token-after= nil delims) - (eq (char-before) (string-to-char - (car delims)))) - (ess-backward-char))) - '(("[" "[[") ("]" "]]"))))) - (ess-token-after= '("," ";")) - (and (ess-token-after= "identifier") - (not (memq (char-syntax (char-before)) '(?w ?_)))) - (progn (skip-syntax-backward ".") - (ess-token-operator-p (ess-token-after))) - (/= (skip-syntax-backward "w_") 0))) - -(defun ess-refine-token (token) - (let ((refined-type - (pcase (ess-token-type token) - ;; Parameter assignment - (`"=" - (save-excursion - (goto-char (ess-token-start token)) - (let ((containing-sexp (ess-containing-sexp-position))) - (when (and containing-sexp - (ess-at-containing-sexp - (and (ess-token-after= "(") - (ess-token-before= '("identifier" "string")))) - (save-excursion - (and (ess-climb-token) - (ess-token-before= '("," "("))))) - "param-assign")))) - ;; Quoted identifiers - (`"string" - (when (or - ;; Quoted parameter names - (ess-refined-token= (ess-token-after) "param-assign") - ;; Quoted call names - (ess-token-after= "(")) - "identifier")) - ((or `"(" `")") - (or (save-excursion - (if (ess-token-close-delimiter-p token) - (ess-climb-paired-delims nil token) - (goto-char (ess-token-start token))) - (when (ess-token-keyword-p (ess-token-before)) - "prefixed-expr-delimiter")) - ;; Fixme: probably too crude. Better handled in parser - (when (ess-token= token ")") - (save-excursion - (ess-climb-paired-delims ")" token) - (when (ess-token-before= '("identifier" "string" ")" "]" "]]" "}")) - "argslist-delimiter"))))) - ((or `"{" `"}") - (save-excursion - (unless (ess-climb-paired-delims "}" token) - (goto-char (ess-token-start token))) - (when (ess-refined-token= (ess-token-before) "prefixed-expr-delimiter") - "prefixed-expr-delimiter")))))) - (if refined-type - (list (cons refined-type (ess-token-value token)) - (nth 1 token)) - token))) - -(defun ess-token-balancing-delim (token) - (pcase (ess-token-type token) - (`"(" ")") - (`")" "(") - (`"[" "]") - (`"]" "[") - (`"[[" "]]") - (`"]]" "[["))) - - -;;;*;;; Token predicates - -(defun ess-token= (token &optional type string) - (when (and (null type) - (null string)) - (error "No condition supplied")) - (let ((type (if (stringp type) (list type) type)) - (string (if (stringp string) (list string) string))) - (and (if type (member (ess-token-type token) type) t) - (if string (member (ess-token-value token) string) t)))) - -(defun ess-refined-token= (token type &optional string) - (ess-token= (ess-refine-token token) type string)) - -(defun ess-token-after= (type &optional string) - (ess-token= (ess-token-after) type string)) - -(defun ess-token-before= (type &optional string) - (ess-token= (ess-token-before) type string)) - -(defun ess-token-open-delimiter-p (token) - (string= (ess-char-syntax (ess-token-type token)) "(")) - -(defun ess-token-close-delimiter-p (token) - (string= (ess-char-syntax (ess-token-type token)) ")")) - -(defun ess-token-delimiter-p (token) - (or (ess-token-open-delimiter-p token) - (ess-token-close-delimiter-p token))) - -(defun ess-token-operator-p (token &optional strict) - (and (or (member (ess-token-type token) ess-r-operators-list) - (string= (ess-token-type token) "%infix%")) - (or (null strict) - (not (ess-refined-token= token "param-assign"))))) - -(defun ess-token-keyword-p (token) - (member (ess-token-type token) ess-r-keywords-list)) - - -;;;*;;; Tokens properties and accessors - -(defun ess-token-make-hash (&rest specs) - (let ((table (make-hash-table :test #'equal))) - (mapc (lambda (spec) - ;; alist - (if (listp (cdr spec)) - (mapc (lambda (cell) - (puthash (car cell) (cdr cell) table)) - spec) - ;; Cons cell - (mapc (lambda (token) - (puthash token (cdr spec) table)) - (car spec)))) - specs) - table)) - -(defvar ess-token-r-powers-delimiters - '(("(" . 100) - ("[" . 100) - ("[[" . 100))) - -(defvar ess-token-r-powers-operator - '(("?" . 5) - ("else" . 8) - ("<-" . 10) - ("<<-" . 10) - ("=" . 15) - ("->" . 20) - ("->>" . 20) - ("~" . 25) - ("|" . 30) - ("||" . 30) - ("&" . 35) - ("&&" . 35) - ("!" . 40) - ("<" . 45) - (">" . 45) - ("<=" . 45) - (">=" . 45) - ("==" . 45) - ("+" . 50) - ("-" . 50) - ("*" . 55) - ("/" . 55) - ("%infix%" . 60) - (":" . 65) - ("^" . 70) - ("$" . 75) - ("@" . 75) - ("::" . 80) - (":::" . 80))) - -(defvar ess-token-r-power-table - (ess-token-make-hash ess-token-r-powers-operator - ess-token-r-powers-delimiters)) - -(defvar ess-token-r-right-powers-operator - '((")" . 1))) - -(defvar ess-token-r-right-power-table - (ess-token-make-hash ess-token-r-powers-operator - ess-token-r-right-powers-operator)) - -(defvar ess-token-r-nud-table - (ess-token-make-hash - '(("identifier" . identity) - ("literal" . identity) - ("number" . identity) - ("function" . identity) - ("if" . identity) - ("while" . identity) - ("for" . identity)) - '(("(" . ess-parser-nud-block) - ("{" . ess-parser-nud-block)))) - -(defvar ess-token-r-rnud-table - (ess-token-make-hash - '(("identifier" . identity) - ("literal" . identity) - ("number" . identity)) - '((")" . ess-parser-rnud-paren) - ("}" . ess-parser-nud-block)))) - -(defvar ess-token-r-leds-operator - (let ((operators-list (append '("%infix%" "else") ess-r-operators-list))) - (cons operators-list #'ess-parser-led-lassoc))) - -(defvar ess-token-r-leds-delimiter - '(("(" . ess-parser-led-funcall) - ("[" . ess-parser-led-funcall) - ("[[" . ess-parser-led-funcall))) - -(defvar ess-token-r-led-table - (ess-token-make-hash ess-token-r-leds-operator - ess-token-r-leds-delimiter)) - -(defvar ess-token-r-rid-table - (ess-token-make-hash - '((")" . ess-parser-rid-expr-prefix)))) - - -;;;*;;; Nud, led and rid functions - -(defun ess-parser-nud-block (prefix-token) - (let ((right (list (cons "TODO" nil)))) - (ess-parser-advance-pair nil prefix-token) - (ess-node (cons "block" nil) - (cons (ess-token-start prefix-token) (point)) - (list prefix-token right)))) - -(defun ess-parser-led-lassoc (start infix-token) - (let* ((power (ess-parser-power infix-token)) - (end (ess-parse-expression power))) - (ess-node (cons "binary-op" nil) - (cons (ess-parser-token-start start) (point)) - (list start infix-token end)))) - -(defun ess-parser-led-funcall (left infix-token) - (when (ess-token= left (append '("identifier" "string" "node") - ess-r-prefix-keywords-list)) - (let* ((power (ess-parser-power infix-token)) - (right (ess-parse-arglist power infix-token)) - (type (if (ess-token= left ess-r-prefix-keywords-list) - "prefixed-expr" - "funcall"))) - (when (string= type "prefixed-expr") - (setq right (list right (ess-parse-expression 0)))) - (ess-node (cons type nil) - (cons (ess-parser-token-start left) (point)) - (list left right))))) - -(defun ess-parser-rid-expr-prefix (right suffix-token) - (when (ess-refined-token= suffix-token "prefixed-expr-delimiter") - (ess-parser-rnud-paren suffix-token right))) - -(defun ess-parser-rnud-paren (suffix-token &optional prefixed-expr) - (let* ((infix-token (save-excursion - (ess-parser-advance-pair nil suffix-token))) - (power (ess-parser-power infix-token)) - (args (ess-parse-arglist power suffix-token)) - (left (if prefixed-expr - (ess-parser-advance) - (ess-parse-expression power))) - (type (cond (prefixed-expr "prefixed-expr") - (left "funcall") - (t "enclosed-expr")))) - (when prefixed-expr - (setcdr (car prefixed-expr) (list infix-token suffix-token))) - (ess-node (cons type nil) - (cons (ess-parser-token-start suffix-token) (point)) - (if prefixed-expr - (list prefixed-expr args left) - (list args left))))) - - -;;;*;;; Parsing - -(defun ess-parser-advance (&optional type value) - (if (bound-and-true-p ess-parser--backward) - (ess-climb-token type value) - (ess-jump-token type value))) - -(defun ess-parser-advance-pair (&optional type token) - (if (bound-and-true-p ess-parser--backward) - (ess-climb-paired-delims type token) - (ess-jump-paired-delims type token))) - -(defun ess-parser-next-token () - (if (bound-and-true-p ess-parser--backward) - (ess-token-before) - (ess-token-after))) - -(defun ess-parser-token-start (token) - (if (bound-and-true-p ess-parser--backward) - (ess-token-end token) - (ess-token-start token))) - -(defun ess-parser-power (token) - (or (if (bound-and-true-p ess-parser--backward) - (gethash (ess-token-type token) ess-token-r-right-power-table) - (gethash (ess-token-type token) ess-token-r-power-table)) - 0)) - -(defun ess-node (type pos contents) - (let ((pos (if (bound-and-true-p ess-parser--backward) - (cons (cdr pos) (car pos)) - pos)) - (contents (if (bound-and-true-p ess-parser--backward) - (nreverse contents) - contents))) - (list type pos contents))) - -(defalias 'ess-node-start #'ess-token-start) -(defalias 'ess-node-end #'ess-token-end) - -(defun ess-parse-start-token (token) - (let* ((table (if (bound-and-true-p ess-parser--backward) - ess-token-r-rnud-table - ess-token-r-nud-table)) - (nud (gethash (ess-token-type token) table))) - (when (fboundp nud) - (funcall nud token)))) - -(defun ess-parse-infix-token (infix-token left) - (let ((infix-power (ess-parser-power infix-token)) - (led (or (when (bound-and-true-p ess-parser--backward) - (gethash (ess-token-type infix-token) ess-token-r-rid-table)) - (gethash (ess-token-type infix-token) ess-token-r-led-table)))) - (funcall led left infix-token))) - -(defun ess-parse-expression (&optional power) - (let ((current (ess-parse-start-token (ess-parser-advance))) - (power (or power 0)) - (next (ess-parser-next-token)) - (last-sucessful-pos (point)) - last-success) - (setq last-success current) - (while (and current (< power (ess-parser-power next))) - (ess-parser-advance) - (when (setq current (ess-parse-infix-token next current)) - (setq last-sucessful-pos (point)) - (setq last-success current)) - (setq next (ess-parser-next-token))) - (goto-char last-sucessful-pos) - last-success)) - -(defun ess-parse-arglist (power start-token) - (let ((start-pos (point)) - (arg-start-pos (point)) - (arglist (list start-token)) - (closing-delim (ess-token-balancing-delim start-token)) - expr) - (while (and (setq expr (ess-parse-expression)) - (push (ess-node (cons "arg" nil) - (cons arg-start-pos (point)) - (list expr)) - arglist) - (ess-parser-advance ",")) - (setq arg-start-pos (point))) - (push (ess-parser-advance closing-delim) arglist) - (ess-node (cons "arglist" nil) - (cons start-pos (1- (point))) - (nreverse arglist)))) - -(defun forward-ess-r-expr () - (interactive) - (ess-save-excursion-when-nil - (ess-escape-token) - (ess-parse-expression))) - -(defun forward-ess-r-sexp () - (interactive) - (ess-save-excursion-when-nil - (ess-escape-token) - (let* ((orig-token (ess-token-after)) - (tree (ess-parse-expression)) - (sexp-node (ess-parser-tree-assoc orig-token tree))) - (when sexp-node - (goto-char (ess-token-end sexp-node)) - sexp-node)))) - -(defun backward-ess-r-expr () - (interactive) - (let ((ess-parser--backward t)) - (ess-parse-expression))) - -(defun backward-ess-r-sexp () - (interactive) - (error "Todo")) - -(defun ess-parser-tree-assoc (key tree) - (let ((next tree) - stack last-node result) - (while (and next (null result)) - (cond ((eq next 'node-end) - (pop last-node)) - ((nth 2 next) - (push 'node-end stack) - (dolist (node (nth 2 next)) - (push node stack)) - (push next last-node)) - ((equal next key) - (setq result (car last-node)))) - (setq next (pop stack))) - result)) - - -;;*;; Point predicates - -(defun ess-inside-call-p (&optional call) - "Return non-nil if point is in a function or indexing call." - (let ((containing-sexp (or (bound-and-true-p containing-sexp) - (ess-containing-sexp-position)))) - (save-excursion - (and (prog1 (ess-goto-char containing-sexp) - (ess-climb-chained-delims)) - (save-excursion - (forward-char) - (ess-up-list)) - (or (ess-behind-call-opening-p "(") - (looking-at "\\[")) - (ess-inside-call-name-p call))))) - -(defun ess-inside-continuation-p () - (unless (or (looking-at ",") - (ess-behind-call-opening-p "[[(]")) - (or (save-excursion - (ess-jump-object) - (and (not (ess-ahead-param-assign-p)) - (ess-behind-operator-p))) - (save-excursion - (ess-climb-object) - (ess-climb-operator) - (and (ess-behind-operator-p) - (not (ess-ahead-param-assign-p))))))) - -(defun ess-inside-call-name-p (&optional call) - (save-excursion - (ess-climb-call-name call))) - -(defun ess-inside-prefixed-block-p (&optional call) - "Return non-nil if point is in a prefixed block. -Prefixed blocks refer to the blocks following function -declarations, control flow statements, etc. - -If CALL is not nil, check if the prefix corresponds to CALL. If -nil, return the prefix." - (save-excursion - (ess-escape-prefixed-block call))) - - -;;*;; Syntactic Travellers and Predicates - -;;;*;;; Blanks, Characters, Comments and Delimiters - -(defun ess-skip-blanks-backward (&optional newlines) - "Skip blanks and newlines backward, taking end-of-line comments into account." - (ess-any ((ess-skip-blanks-backward-1)) - ((when newlines - (ess-while (and (not (bobp)) - (= (point) (line-beginning-position))) - (forward-line -1) - (goto-char (ess-code-end-position)) - (ess-skip-blanks-backward-1)))))) - -(defun ess-skip-blanks-backward-1 () - (and (not (bobp)) - (/= 0 (skip-syntax-backward " ")))) - -(defun ess-skip-blanks-forward (&optional newlines) - "Skip blanks and newlines forward, taking end-of-line comments into account." - (ess-any ((/= 0 (skip-syntax-forward " "))) - ((ess-while (and newlines - (= (point) (ess-code-end-position)) - (when (ess-save-excursion-when-nil - ;; Handles corner cases such as point being on last line - (let ((orig-point (point))) - (forward-line) - (back-to-indentation) - (> (point) orig-point))) - (skip-chars-forward " \t") - t)))))) - -(defun ess-jump-char (char) - (ess-save-excursion-when-nil - (ess-skip-blanks-forward t) - (when (looking-at char) - (goto-char (match-end 0))))) - -(defun ess-escape-comment () - (when (ess-inside-comment-p) - (prog1 (comment-beginning) - (skip-chars-backward "#+[ \t]*")))) - -(defun ess-ahead-closing-p () - (memq (char-before) '(?\] ?\} ?\)))) - -(defun ess-ahead-boundary-p () - (looking-back "[][ \t\n(){},]" (1- (point)))) - -(defun ess-escape-string () - (and (nth 3 (syntax-ppss)) - (ess-goto-char (nth 8 (syntax-ppss))))) - -(defun ess-climb-paired-delims (&optional type token) - (ess-save-excursion-when-nil - (let ((token (or token (ess-token-before)))) - (goto-char (ess-token-end token)) - (when (if type - (ess-token= token type) - (ess-token-delimiter-p token)) - (and (ess-backward-sexp) - (ess-token-after)))))) - -(defun ess-jump-paired-delims (&optional type token) - (ess-save-excursion-when-nil - (let ((token (or token (ess-token-after)))) - (goto-char (ess-token-start token)) - (when (if type - (ess-token= token type) - (ess-token-delimiter-p token)) - (and (ess-forward-sexp) - (ess-token-before)))))) - - -;;;*;;; Blocks - -(defun ess-block-opening-p () - (save-excursion - (cond - ((looking-at "{")) - ;; Opening parenthesis not attached to a function opens up a - ;; block too. Only pick up those that are last on their line - ((ess-behind-block-paren-p))))) - -(defun ess-block-closing-p () - (save-excursion - (cond - ((looking-at "}")) - ((looking-at ")") - (forward-char) - (backward-sexp) - (not (looking-back - (concat ess-r-name-pattern "[[:blank:]]*") - (line-beginning-position))))))) - -(defun ess-block-p () - (or (save-excursion - (when containing-sexp - (goto-char containing-sexp) - (ess-block-opening-p))) - (ess-unbraced-block-p))) - -;; Parenthesised expressions -(defun ess-behind-block-paren-p () - (and (looking-at "(") - (not (ess-ahead-attached-name-p)))) - -(defun ess-climb-block (&optional ignore-ifelse) - (ess-save-excursion-when-nil - (cond - ((and (not ignore-ifelse) - (ess-climb-if-else 'to-start))) - ((and (eq (char-before) ?\}) - (prog2 - (forward-char -1) - (ess-up-list -1) - (ess-climb-block-prefix))))))) - -(defvar ess-prefixed-block-patterns - (mapcar (lambda (fun) (concat fun "[ \t\n]*(")) - '("function" "if" "for" "while"))) - -(defun ess-behind-prefixed-block-p (&optional call) - (if call - (looking-at (concat call "[ \t]*(")) - (cl-some 'looking-at ess-prefixed-block-patterns))) - -(defun ess-unbraced-block-p (&optional ignore-ifelse) - "This indicates whether point is in front of an unbraced -prefixed block following a control flow statement. Returns -position of the control flow function (if, for, while, etc)." - (save-excursion - (and (ess-backward-sexp) - (or (and (looking-at "else\\b") - (not ignore-ifelse)) - (and (looking-at "(") - (ess-backward-sexp) - (cl-some 'looking-at ess-prefixed-block-patterns) - (if ignore-ifelse - (not (looking-at "if\\b")) - t))) - (point)))) - -(defun ess-climb-block-prefix (&optional call ignore-ifelse) - "Climb the prefix of a prefixed block. -Prefixed blocks refer to the blocks following function -declarations, control flow statements, etc. - -Should be called either in front of a naked block or in front -of the curly brackets of a braced block. - -If CALL not nil, check if the prefix corresponds to CALL. If nil, -return the prefix." - (ess-save-excursion-when-nil - (or (and (not ignore-ifelse) - (prog1 (and (ess-climb-if-else-call) - (or (null call) - (looking-at call))) - (when (ess-token-after= "else") - (ess-climb-token "}")))) - (let ((pos (ess-unbraced-block-p ignore-ifelse))) - (and (ess-goto-char pos) - (if call - (looking-at call) - (cond ((looking-at "function") - "function") - ((looking-at "for") - "for") - ((looking-at "if") - "if") - ((looking-at "else") - "else")))))))) - -(defun ess-escape-prefixed-block (&optional call) - "Climb outside of a prefixed block." - (let ((containing-sexp (or (bound-and-true-p containing-sexp) - (ess-containing-sexp-position)))) - (or (ess-save-excursion-when-nil - (and (ess-goto-char containing-sexp) - (looking-at "{") - (ess-climb-block-prefix call))) - (ess-escape-unbraced-block call)))) - -(defun ess-escape-unbraced-block (&optional call) - (ess-save-excursion-when-nil - (while (and (not (ess-unbraced-block-p)) - (or (ess-escape-continuations) - (ess-escape-call)))) - (ess-climb-block-prefix call))) - -(defun ess-jump-block () - (cond - ;; if-else blocks - ((ess-jump-if-else)) - ;; Prefixed blocks such as `function() {}' - ((ess-behind-prefixed-block-p) - (ess-jump-prefixed-block)) - ;; Naked blocks - ((and (or (looking-at "{") - (ess-behind-block-paren-p)) - (ess-forward-sexp))))) - -(defun ess-jump-prefixed-block (&optional call) - (ess-save-excursion-when-nil - (when (ess-behind-prefixed-block-p call) - (ess-forward-sexp 2) - (ess-skip-blanks-forward t) - (if (looking-at "{") - (ess-forward-sexp) - (prog1 (ess-jump-expression) - (ess-jump-continuations)))))) - - -;;;*;;; Calls - -(defun ess-call-closing-p () - (save-excursion - (when (cond ((looking-at ")") - (ess-up-list -1)) - ((looking-at "]") - (when (ess-up-list -1) - (prog1 t (ess-climb-chained-delims))))) - (ess-ahead-attached-name-p)))) - -(defun ess-behind-call-opening-p (pattern) - (and (looking-at pattern) - (ess-ahead-attached-name-p))) - -;; Should be called just before the opening brace -(defun ess-ahead-attached-name-p () - (save-excursion - (ess-climb-object))) - -(defun ess-ahead-param-assign-p () - "Return non-nil if looking at a function argument. -To be called just before the `=' sign." - (ess-refined-token= (ess-token-before) "param-assign")) - -(defun ess-behind-arg-p () - (save-excursion - (ess-jump-arg))) - -(defun ess-behind-parameter-p () - (save-excursion - (ess-jump-parameter))) - -(defun ess-jump-parameter () - (ess-save-excursion-when-nil - (and (ess-jump-name) - (when (looking-at "[ \t]*=\\([^=]\\)") - (goto-char (match-beginning 1)) - (ess-skip-blanks-forward) - t)))) - -(defun ess-jump-arg () - (ess-save-excursion-when-nil - (ess-skip-blanks-forward t) - (ess-any ((ess-jump-parameter)) - ((ess-jump-expression)) - ((ess-jump-continuations))))) - -(defun ess-arg-bounds () - "Should be called in front of the argument." - (save-excursion - (let ((beg (point))) - (and (ess-jump-arg) - (list beg (point)))))) - -(defun ess-climb-call (&optional call) - "Climb functions (e.g. ggplot) and parenthesised expressions." - (or (ess-while (ess-save-excursion-when-nil - (ess-climb-name) - (and (ess-climb-chained-delims ?\]) - ;; (ess-climb-expression) - (if (eq (char-before) ?\)) - (ess-climb-call) - (ess-climb-name)) - ))) - (ess-save-excursion-when-nil - (when (and (memq (char-before) '(?\] ?\) ?\})) - (ess-backward-sexp)) - (if call - (and (ess-climb-name) - (looking-at call))) - (prog1 t - (ess-climb-name)))))) - -(defun ess-climb-call-name (&optional call) - (ess-save-excursion-when-nil - (ess-jump-name) - (ess-skip-blanks-forward) - (and (ess-behind-call-opening-p "[[(]") - (ess-climb-name) - (or (null call) - (looking-at call))))) - -(defun ess-step-to-first-arg () - (let ((containing-sexp (ess-containing-sexp-position))) - (cond ((ess-inside-call-p) - (goto-char containing-sexp) - (forward-char) - t) - ((ess-inside-call-name-p) - (ess-jump-name) - (ess-skip-blanks-forward) - (forward-char) - t)))) - -(defun ess-jump-to-next-arg () - (and (ess-jump-arg) - (prog1 (ess-jump-char ",") - (ess-skip-blanks-forward t)))) - -(defun ess-jump-call () - (ess-save-excursion-when-nil - (or (and (ess-jump-object) - (cond ((eq (char-before) ?\))) - ((looking-at "\\[") - (ess-jump-chained-brackets)) - ((looking-at "(") - (ess-forward-sexp)))) - (and (looking-at "[ \t]*(") - (ess-forward-sexp))))) - -(defun ess-behind-call-p () - (save-excursion - (ess-jump-object) - (ess-skip-blanks-forward) - (looking-at "[[(]"))) - -(defun ess-climb-chained-delims (&optional delim) - "Should be called with point between delims, e.g. `]|['." - (setq delim (if delim - (list delim) - '(?\] ?\)))) - (ess-while (ess-save-excursion-when-nil - (when (memq (char-before) delim) - (ess-backward-sexp))))) - -(defun ess-jump-chained-brackets () - (ess-while (ess-save-excursion-when-nil - (when (eq (char-after) ?\[) - (ess-forward-sexp))))) - -(defun ess-escape-call (&optional call) - (let ((containing-sexp (ess-containing-sexp-position))) - (if (ess-inside-call-p) - (ess-save-excursion-when-nil - (goto-char containing-sexp) - (ess-climb-chained-delims) - (and (ess-climb-name) - (or (null call) - (looking-at call)))) - ;; At top level or inside a block, check if point is on the - ;; function name. - (ess-save-excursion-when-nil - (let ((orig-pos (point))) - (and (ess-jump-name) - (looking-at "[[(]") - (ess-climb-name) - (or (null call) - (looking-at call)) - (/= (point) orig-pos))))))) - -(defun ess-escape-calls () - (ess-while (ess-escape-call))) - -(defun ess-jump-inside-call () - (ess-save-excursion-when-nil - (when (ess-jump-name) - (ess-skip-blanks-forward) - (when (looking-at "(") - (forward-char) - t)))) - -(defun ess-args-bounds (&optional marker) - (let ((containing-sexp (ess-containing-sexp-position))) - (when (ess-inside-call-p) - (save-excursion - (let ((beg (1+ containing-sexp)) - (call-beg (ess-at-containing-sexp - (ess-climb-name) - (point)))) - ;; (ess-up-list) can't find its way when point is on a - ;; backquoted name, so start from `beg'. - (and (goto-char beg) - (ess-up-list) - (prog1 t - (forward-char -1)) - (let ((end (if marker - (point-marker) - (point)))) - (list beg end call-beg)))))))) - -(defun ess-args-alist () - "Return all arguments as an alist with cars set to argument -names and cdrs set to the expressions given as argument. Both -cars and cdrs are returned as strings." - (save-excursion - (when (ess-step-to-first-arg) - (let (args current-arg) - (while (and (setq current-arg (ess-cons-arg)) - (setq args (nconc args (list current-arg))) - (ess-jump-to-next-arg))) - args)))) - -(defun ess-cons-arg () - "Return a cons cell of the current argument with car set to the -parameter name (nil if not specified) and cdr set to the argument -expression." - (save-excursion - (ess-skip-blanks-forward t) - (let ((param (when (ess-behind-parameter-p) - (buffer-substring-no-properties - (point) - (prog2 - (ess-jump-name) - (point) - (ess-jump-char "=") - (ess-skip-blanks-forward))))) - (arg (buffer-substring-no-properties - (point) - (progn - (ess-jump-arg) - (point))))) - (cons param arg)))) - - -;;;*;;; Statements - -(defun ess-behind-operator-p (&optional strict) - (ess-token-operator-p (ess-token-after) strict)) - -(defun ess-ahead-operator-p (&optional strict) - (ess-token-operator-p (ess-token-before) strict)) - -(defun ess-climb-lhs (&optional no-fun-arg climb-line) - (ess-save-excursion-when-nil - (let ((start-line (line-number-at-pos))) - (ess-climb-operator) - (when (and (or climb-line (equal (line-number-at-pos) start-line)) - (ess-behind-definition-op-p no-fun-arg)) - (prog1 t - (ess-climb-expression)))))) - -(defun ess-jump-lhs () - (ess-save-excursion-when-nil - (and (ess-jump-name) - (ess-behind-definition-op-p) - (ess-jump-operator)))) - -(defun ess-climb-operator () - (when (ess-token-operator-p (ess-token-before)) - (prog1 (ess-climb-token) - (ess-skip-blanks-backward)))) - -;; Currently doesn't check that the operator is not binary -(defun ess-climb-unary-operator () - (ess-save-excursion-when-nil - (let ((token (ess-climb-token))) - (member (ess-token-type token) '("+" "-" "!" "?" "~"))))) - -;; Currently returns t if we climbed lines, nil otherwise. -(defun ess-climb-continuations (&optional cascade ignore-ifelse) - (let* ((start-line (line-number-at-pos)) - (state (list :start-line start-line - :last-line start-line - :moved 0 - :last-pos (point) - :prev-point nil - :def-op nil - :expr nil))) - (when (ess-while (and (<= (plist-get state :moved) 1) - (or (ess-save-excursion-when-nil - (and (ess-climb-operator) - (ess-climb-continuations--update-state state cascade 'op) - (ess-climb-expression ignore-ifelse))) - (ess-climb-unary-operator)) - (/= (plist-get state :last-pos) (point))) - (ess-climb-continuations--update-state state cascade nil) - (plist-put state :last-pos (point))) - (when (and (plist-get state :prev-point) - (or (= (plist-get state :moved) 3) - (not (plist-get state :expr)))) - (goto-char (plist-get state :prev-point))) - (if (plist-get state :def-op) - 'def-op - (< (line-number-at-pos) (plist-get state :start-line)))))) - -(defun ess-climb-continuations--update-state (state cascade &optional op) - ;; Climbing multi-line expressions should not count as moving up - (when op - (plist-put state :expr (ess-ahead-closing-p))) - (let ((cur-line (line-number-at-pos))) - (when (and (plist-get state :last-line) - (< cur-line (plist-get state :last-line)) - (or cascade (not (plist-get state :expr)))) - (plist-put state :moved (1+ (plist-get state :moved))) - (plist-put state :last-line cur-line))) - ;; Don't update counter after climbing operator or climbing too high - (when (and (not op) - (<= (plist-get state :moved) 1)) - (plist-put state :prev-point (point))) - (when (and (ess-behind-definition-op-p) - (<= (plist-get state :moved) 1)) - (plist-put state :def-op t)) - t) - -(defun ess-jump-operator () - (when (ess-behind-operator-p) - (ess-jump-token) - (ess-skip-blanks-forward t) - t)) - -(defun ess-jump-continuation () - (and (ess-jump-operator) - (ess-jump-expression))) - -(defun ess-jump-continuations () - (let (last-pos) - (when (ess-while (and (or (null last-pos) - (/= (point) last-pos)) - (setq last-pos (point)) - (ess-jump-continuation))) - ;; In calls, operators can start on newlines - (let ((start-line (line-number-at-pos))) - (when (ess-save-excursion-when-nil - (and (ess-inside-call-p) - (ess-skip-blanks-forward t) - (/= (line-number-at-pos) start-line) - (ess-behind-operator-p))) - (ess-jump-continuations))) - t))) - -(defun ess-ahead-continuation-p (&optional or-parameter) - (or (ess-token-operator-p (ess-token-before) (not or-parameter)) - (save-excursion - (ess-climb-block-prefix)) - (ess-token-after= "else") - (save-excursion - (ess-climb-if-else-call)))) - -(defun ess-token-definition-op-p (token strict) - (and (ess-token= token '("<-" "<<-" ":=" "~" "=")) - (if strict - (not (ess-refined-token= token "param-assign")) - t))) - -(defun ess-behind-definition-op-p (&optional strict) - (ess-token-definition-op-p (ess-token-after) strict)) - -(defun ess-ahead-definition-op-p (&optional strict) - (ess-token-definition-op-p (ess-token-before) strict)) - -(defun ess-behind-assignment-op-p () - (let ((token (ess-token-after))) - (and (ess-token= token '("<-" "=")) - (not (ess-refined-token= token "param-assign"))))) - -(defun ess-escape-continuations () - (ess-any ((unless (ess-ahead-boundary-p) - (ess-climb-expression))) - ((ess-while (ess-climb-continuations))))) - -(defun ess-continuations-bounds (&optional marker) - (save-excursion - (let ((beg (progn - (ess-escape-continuations) - (point)))) - (when beg - (ess-jump-expression) - (ess-jump-continuations) - (let ((end (if marker - (point-marker) - (point)))) - (list beg end)))))) - -(defun ess-climb-to-top-level () - (while (ess-goto-char (ess-containing-sexp-position))) - (ess-escape-continuations)) - - -;;;*;;; Statements: Control Flow - -(defun ess-climb-if-else-call (&optional multi-line) - "Climb if, else, and if else calls." - (ess-save-excursion-when-nil - (cond ((ess-climb-paired-delims ")") - (when (ess-climb-token "if") - ;; Check for `else if' - (prog1 t - (ess-save-excursion-when-nil - (let ((orig-line (line-number-at-pos))) - (and (ess-climb-token "else") - (or multi-line - (eq orig-line (line-number-at-pos))))))))) - ((ess-climb-token "else"))))) - - -(defun ess-climb-if-else-body (&optional from-else) - (cond - ;; Climb braced body - ((ess-save-excursion-when-nil - (and (when (progn (ess-skip-blanks-backward t) - (eq (char-before) ?\})) - (prog1 t (forward-char -1))) - (ess-up-list -1)))) - ;; Climb unbraced body - ((when from-else - (ess-save-excursion-when-nil - (ess-skip-blanks-backward t) - (prog1 (ess-climb-expression 'ignore-ifelse) - (or (ess-climb-continuations nil 'ignore-ifelse) - (ess-climb-block-prefix nil 'ignore-ifelse)))))))) - -(defun ess-climb-if-else (&optional to-start) - "Climb horizontal as well as vertical if-else chains, with or -without curly braces." - ;; Don't climb if we're atop the current chain of if-else - (unless (ess-token-after= "if") - (ess-save-excursion-when-nil - (let ((from-else (ess-token-after= "else"))) - (when (and (ess-climb-if-else-body from-else) - (ess-climb-if-else-call to-start)) - ;; If we start from a final else and climb to another else, we - ;; are in the wrong chain of if-else. In that case, - ;; climb-recurse to the top of the current chain and climb - ;; again to step in the outer chain. - (when (save-excursion (and from-else - (ess-jump-token "else") - (not (ess-jump-token "if")))) - (ess-climb-if-else 'to-start) - (ess-climb-continuations) - (ess-climb-block-prefix nil 'ignore-ifelse) - (ess-climb-if-else-call nil)) - (ess-maybe-climb-broken-else) - (when to-start - (ess-climb-if-else to-start)) - t))))) - -;; Broken else: if \n else -(defun ess-maybe-climb-broken-else (&optional same-line) - (ess-save-excursion-when-nil - ;; Don't record current line if not needed (expensive operation) - (let ((cur-line (when same-line (line-number-at-pos)))) - (and (ess-climb-token "else") - (if same-line - (= cur-line (line-number-at-pos)) - t))))) - -(defun ess-skip-curly-backward () - (re-search-backward "}[ \t]*" (line-beginning-position) t)) - -(defun ess-jump-if-else () - (let (from) - (ess-while (ess-save-excursion-when-nil - (ess-skip-blanks-forward t) - (cond - ((and (not (eq from 'if)) - (ess-jump-if) - (setq from 'if))) - ((looking-at "else") - (ess-forward-sexp) - (or (ess-jump-if) - (progn - (ess-skip-blanks-forward t) - (ess-jump-expression))) - (setq from 'else)) - (t - nil)))))) - -(defun ess-jump-if () - (ess-save-excursion-when-nil - (ess-skip-blanks-forward t) - (and (looking-at "if[ \t\n]*(") - (ess-forward-sexp 2) - (progn - (ess-skip-blanks-forward t) - (ess-jump-expression))))) - - -;;;*;;; Function Declarations - -(defun ess-behind-defun-p () - (or (looking-at "function[ \t]*(") - (ess-behind-enclosed-defun-p))) - -(defun ess-behind-enclosed-defun-p () - (save-excursion - (and (ess-behind-call-p) - (ess-jump-inside-call) - (cl-some (lambda (arg) - (string-match "^function\\b" - (cdr arg))) - (ess-args-alist))))) - - -;;;*;;; Names / Objects / Expressions - -;; Should climb any names, including backquoted ones or those -;; containing `@' or `$'. Difficult to achieve with regexps, but -;; skipping chars is faster anyway. -(defun ess-climb-object () - (ess-save-excursion-when-nil - (let (climbed) - (ess-skip-blanks-backward) - ;; Backquoted names can contain any character - (if (and (memq (char-before) '(?` ?\" ?\')) - (ess-backward-sexp)) - (setq climbed t) - (while (cl-some (apply-partially '/= 0) - `(,(skip-syntax-backward "w_") - ,(skip-chars-backward "\"'"))) - (setq climbed t))) - ;; Recurse if we find an indexing char - (let ((tok (ess-token-before))) - (when (member (ess-token-type tok) '("$" "@" "::" ":::")) - (goto-char (ess-token-start tok)) - (ess-climb-object))) - climbed))) - -;; Todo: split name and object climbing -(defun ess-climb-name () - (ess-climb-object)) - -;; This jumps both object names and atomic objects like strings or -;; numbers. -(defun ess-jump-object () - (cond - ;; Jump over object names - ((ess-jump-name)) - ;; Jump over strings)) - ((ess-save-excursion-when-nil - (skip-chars-forward " \t") - (memq (char-after) '(?\" ?\'))) - (ess-forward-sexp)))) - -(defun ess-jump-name () - (ess-save-excursion-when-nil - (let (climbed) - (skip-chars-forward " \t") - ;; Jump over backquoted names - (cond ((and (eq (char-after) ?`) - (looking-back ess-r-symbol-pattern - (1- (point)))) - (forward-char) - (setq climbed t)) - ((eq (char-after) ?`) - (forward-char) - (when (ess-while (not (memq (char-after) '(?` ?\C-J))) - (forward-char)) - (setq climbed t) - (forward-char))) - ;; Jump over regular names - ((when (/= 0 (skip-syntax-forward "w_")) - ;; Maybe point was inside backticks - (when (eq (char-after) ?`) - (forward-char)) - (setq climbed t)))) - climbed))) - -(defun ess-climb-expression (&optional ignore-ifelse) - (ess-save-excursion-when-nil - (or (ess-climb-block ignore-ifelse) - (ess-climb-call) - (ess-climb-object)))) - -(defun ess-jump-expression () - (or (ess-jump-block) - (ess-jump-call) - (ess-jump-object))) - -(provide 'ess-r-syntax) - -;;; ess-r-syntax.el ends here diff --git a/elpa/ess-20191014.1343/ess-r-xref.el b/elpa/ess-20191014.1343/ess-r-xref.el deleted file mode 100644 index c0e40e7d..00000000 --- a/elpa/ess-20191014.1343/ess-r-xref.el +++ /dev/null @@ -1,131 +0,0 @@ -;;; ess-r-xref.el --- An xref backend for R. -*- lexical-binding: t -*- -;; -;; Author: Aaron Jacobs -;; Created: 21 January 2018 -;; Maintainer: ESS-core -;; -;; Keywords: languages, statistics, xref -;; -;; This file is part of ESS. -;; -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This file contains an xref backend for `ess-r-mode'. - -;;; Code: - -(require 'xref) -(require 'ess-inf) -(require 'ess-r-package) -(require 'ess-tracebug) - -;; Silence the byte compiler. OK because this file is only loaded by ess-r-mode. -(declare-function inferior-ess-r-force "ess-r-mode") - - -(defvar ess-r-xref-pkg-sources nil - "Alist of R package->directory associations. -This variable is used as a cache of package->directory -associations, but could be used by the users for a more refined -control of package locations than `ess-r-package-library-paths'.") - -(defun ess-r-xref-backend () - "An `xref-backend-functions' implementation for `ess-r-mode'. -R's xref backend searches for `ess-r-package-library-paths' when -srcrefs point to temporary locations." - 'ess-r) - -(cl-defmethod xref-backend-identifier-at-point ((_backend (eql ess-r))) - (let ((sym (ess-symbol-at-point))) - (when sym - (symbol-name sym)))) - -(cl-defmethod xref-backend-definitions ((_backend (eql ess-r)) symbol) - (let ((xref (ess-r-xref--xref symbol))) - (when xref - (list xref)))) - -(cl-defmethod xref-backend-apropos ((_backend (eql ess-r))) - ;; Not yet supported. - nil) - -(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql ess-r))) - (inferior-ess-r-force) - (ess-get-words-from-vector ".ess_all_functions()\n")) - -(defun ess-r-xref--srcref (symbol) - (inferior-ess-r-force) - ;; Look for `symbol' inside the package namespace - (let* ((pkg (ess-r-package-name)) - (pkg (if pkg - (concat "\"" pkg "\"") - "NULL"))) - (with-current-buffer (ess-command (format ".ess_srcref(\"%s\", %s)\n" symbol pkg)) - (goto-char (point-min)) - (when (re-search-forward "(" nil 'noerror) - (goto-char (match-beginning 0)) - (read (current-buffer)))))) - -(defun ess-r-xref--pkg-srcfile (symbol r-src-file) - "Look in the source directory of the R package containing symbol SYMBOL for R-SRC-FILE." - (let* ((env-name (ess-string-command (format ".ess_fn_pkg(\"%s\")\n" symbol))) - (pkg (if (string-equal env-name "") - (user-error "Can't find package for symbol %s" symbol) - env-name)) - (dir (or (assoc-default pkg ess-r-xref-pkg-sources) - (cond ((stringp ess-r-package-library-paths) - (expand-file-name pkg ess-r-package-library-paths)) - ((listp ess-r-package-library-paths) - (cl-loop for d in ess-r-package-library-paths - for p = (expand-file-name pkg d) - when (file-exists-p p) return p)) - (t (user-error "Invalid value of `ess-r-package-library-paths'"))))) - (file (when dir (expand-file-name r-src-file dir)))) - (when file - (unless (file-readable-p file) - (user-error "Can't read %s" file)) - ;; Cache package's source directory. - (unless (assoc pkg ess-r-xref-pkg-sources) - (push `(,pkg . ,dir) ess-r-xref-pkg-sources)) - file))) - -(defun ess-r-xref--xref (symbol) - "Create an xref for the source file reference of R symbol SYMBOL." - (let ((ref (ess-r-xref--srcref symbol))) - (when ref - (let ((file (nth 0 ref)) - (line (nth 1 ref)) - (col (nth 2 ref))) - (or - ;; 1) Result of ESS evaluation - (let* ((ess-ref (gethash file ess--srcrefs)) - (ess-buff (when ess-ref (ess--dbg-find-buffer (car ess-ref))))) - (when ess-buff - ;; FIXME: this breaks when eval is on larger spans than function - (xref-make symbol (xref-make-buffer-location ess-buff (nth 2 ess-ref))))) - ;; 2) Actual file location - (when (file-readable-p file) - (xref-make symbol (xref-make-file-location file line col))) - ;; 3) Temporary sources - truncate and locate in ess-r-package-library-paths - (when (string-match "/\\(R/.*\\)$" file) - (let ((pkg-file (ess-r-xref--pkg-srcfile symbol (match-string 1 file)))) - (when pkg-file - (xref-make symbol (xref-make-file-location - (expand-file-name pkg-file) line col)))))))))) - -(provide 'ess-r-xref) - -;;; ess-r-xref.el ends here diff --git a/elpa/ess-20191014.1343/ess-rd.el b/elpa/ess-20191014.1343/ess-rd.el deleted file mode 100644 index e8f03b8a..00000000 --- a/elpa/ess-20191014.1343/ess-rd.el +++ /dev/null @@ -1,463 +0,0 @@ -;; ess-rd.el --- Support for editing R documentation (Rd) source -*- lexical-binding: t; -*- - -;; Copyright (C) 1997--2005 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: KH -;; Created: 25 July 1997 -;; Maintainer: ESS-core - -;; This file is part of ESS (Emacs Speaks Statistics). - -;; This file is free software; you may redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by the -;; Free Software Foundation; either version 2, or (at your option) any -;; later version. -;; -;; This is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -;; for more details. -;; -;; A copy of the GNU General Public License is available on the World -;; Wide Web at https://www.gnu.org/copyleft/gpl.html. You can also -;; obtain it by writing to the Free Software Foundation, Inc., 675 Mass -;; Ave, Cambridge, MA 02139, USA. - - -;;; Commentary: -;; - -;;; Code: -(eval-when-compile - (require 'subr-x)) - -(require 'ess-help) -(require 'ess-inf) -;; Silence the byte compiler, see TODO below; can we remove these? -(defvar ess-help-r-sec-regex) -(defvar ess-help-r-sec-keys-alist) -(defvar ess-r-customize-alist) - -(defcustom Rd-mode-hook nil - "Hook to be run when Rd mode is entered." - :type 'hook - :group 'ess-R - :group 'ess-hooks) - -(define-abbrev-table 'Rd-mode-skeleton-abbrev-table - '(("`ag" "\\arguments" nil :system t) - ("`al" "\\alias" nil :system t) - ("`au" "\\author" nil :system t) - ("`bf" "\\bold" nil :system t) - ("`co" "\\code" nil :system t) - ("`de" "\\describe" nil :system t) - ("`dn" "\\description" nil :system t) - ("`dt" "\\details" nil :system t) - ("`em" "\\emph" nil :system t) - ("`en" "\\enumerate" nil :system t) - ("`ex" "\\examples" nil :system t) - ("`fi" "\\file" nil :system t) - ("`fo" "\\format" nil :system t) - ("`it" "\\item" nil :system t) - ("`iz" "\\itemize" nil :system t) - ("`kw" "\\keyword" nil :system t) - ("`li" "\\link" nil :system t) - ("`me" "\\method" nil :system t) - ("`na" "\\name" nil :system t) - ("`no" "\\note" nil :system t) - ("`re" "\\references" nil :system t) - ("`sa" "\\seealso" nil :system t) - ("`se" "\\section" nil :system t) - ("`so" "\\source" nil :system t) - ("`ss" "\\subsection" nil :system t) - ("`sy" "\\synopsis" nil :system t) - ("`ta" "\\tabular" nil :system t) - ("`ti" "\\title" nil :system t) - ("`us" "\\usage" nil :system t) - ("`va" "\\value" nil :system t)) - "Abbrev table for R documentation keywords. -All Rd mode abbrevs start with a grave accent (`)." - :case-fixed t) - -(define-abbrev-table 'Rd-mode-abbrev-table () - "Abbrev table for Rd mode." - :parents (list Rd-mode-skeleton-abbrev-table)) - -(defvar Rd-mode-syntax-table - (let ((tab (copy-syntax-table text-mode-syntax-table))) - (modify-syntax-entry ?\\ "\\" tab) - (modify-syntax-entry ?\{ "(}" tab) - (modify-syntax-entry ?\} "){" tab) - ;; Nice for editing, not for parsing ... - (modify-syntax-entry ?\( "()" tab) - (modify-syntax-entry ?\) ")(" tab) - (modify-syntax-entry ?\[ "(]" tab) - (modify-syntax-entry ?\] ")[" tab) - ;; To get strings right - ;; (modify-syntax-entry ?\' "\"" Rd-mode-syntax-table) - (modify-syntax-entry ?\" "\"" tab) - ;; To make abbrevs starting with a grave accent work ... - (modify-syntax-entry ?\` "w" tab) - ;; Comments - (modify-syntax-entry ?\% "<" tab) - (modify-syntax-entry ?\n ">" tab) - tab) - "Syntax table for `Rd-mode'.") - -(defvar Rd-mode-parse-syntax-table - (let ((tab (copy-syntax-table Rd-mode-syntax-table))) - ;; To make parse-partial-sexps do the thing we want for computing - ;; indentations - (modify-syntax-entry ?\( "_" tab) - (modify-syntax-entry ?\) "_" tab) - (modify-syntax-entry ?\[ "_" tab) - (modify-syntax-entry ?\] "_" tab) - tab) - "Syntax table for parsing Rd mode.") - -(defvar Rd-section-names - '("Rdversion" "arguments" "alias" "author" "concept" "describe" "description" - "details" "docType" "encoding" "enumerate" "examples" "format" - "itemize" "keyword" "name" "note" "preformatted" "references" - "seealso" "section" "source" "subsection" "synopsis" - "tabular" "title" "usage" - "value")) - -(defvar Rd-keywords - '( - ;; the next two lines: only valid in R <= 2.8.1 - ;; commented out on 2011-01-14 for ESS version 5.13: - ;; "Alpha" "Gamma" "alpha" "beta" "epsilon" "lambda" "mu" "pi" "sigma" - ;; "ge" "le" "left" "right" - ;; - "R" "RdOpts" "S3method" "S4method" "Sexpr" "acronym" - "bold" "cite" "code" "command" "cr" "dQuote" "deqn" "dfn" "dontrun" - "dontshow" "donttest" "dots" "email" "emph" "enc" "env" "eqn" "figure" "file" - "href" "if" "ifelse" - "item" "kbd" "ldots" "linkS4class" "link" "method" - "newcommand" "option" "out" - "pkg" "sQuote" "renewcommand" - "samp" "strong" "tab" "url" "var" "verb" - ;; System macros (from /share/Rd/macros/system.Rd ): - "CRANpkg" "PR" "sspace" "doi" - "packageTitle" "packageDescription" "packageAuthor" - "packageMaintainer" "packageDESCRIPTION" "packageIndices" - )) - -(defvar Rd-font-lock-keywords - (list - (cons - (concat "\\\\\\(" - (mapconcat 'identity Rd-section-names "\\|") - "\\>\\)") - 'font-lock-reference-face) ; Rd-bold-face - (cons - (concat "\\\\\\(" - (mapconcat 'identity Rd-keywords "\\|") - "\\>\\)") - 'font-lock-keyword-face) - '("^#\\(ifn?def\\)\\s-+\\(\\sw+\\)" - (1 font-lock-builtin-face) - (2 font-lock-variable-name-face nil t)) - '("^#\\(endif\\)" 1 font-lock-builtin-face)) - "Additional Rd expressions to highlight.") - -(defvar Rd-indent-level 2 - "Indentation of Rd code with respect to containing blocks.") - -(defvar Rd-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\t" #'indent-according-to-mode) - (define-key map "\C-j" #'reindent-then-newline-and-indent) - (define-key map "\C-m" #'reindent-then-newline-and-indent) - (define-key map "\C-c\C-p" #'Rd-preview-help) - (define-key map "\C-c\C-j" #'Rd-mode-insert-item) - (define-key map "\C-c\C-e" #'Rd-mode-insert-skeleton) - (define-key map "\C-c\C-f" #'Rd-font) - (define-key map "\C-c\C-s" #'Rd-mode-insert-section) - (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) - (define-key map "\C-c\C-r" #'ess-eval-region) - (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) - (define-key map "\C-\M-x" #'ess-eval-region-or-function-or-paragraph) - (define-key map "\C-c\C-v" #'ess-display-help-on-object) - (define-key map "\C-c\C-w" #'ess-switch-process) - (define-key map "\C-c\C-y" #'ess-switch-to-ESS) - (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) - map) - "Keymap used in Rd mode.") - -(defvar Rd-mode-menu - (list "Rd" - ["Markup [word]" Rd-font t] - ["Insert Item" Rd-mode-insert-item t] - ["Insert Section" Rd-mode-insert-section t] - ["Insert Skeleton" Rd-mode-insert-skeleton t] - "-" - ["Preview" Rd-preview-help t] - "-" - ["Eval Line" ess-eval-line-visibly-and-step t] - ["Eval Region" ess-eval-region t] - ["Switch to ESS Process" ess-switch-to-ESS t] - ["Switch the ESS Process" ess-switch-process t] - ["Switch to end{ESS Pr}" ess-switch-to-end-of-ESS t] - "-" - ["Toggle Abbrev Mode" abbrev-mode t] - ["Toggle Auto-Fill Mode" auto-fill-mode t] - "-" - ["Submit Bug Report" ess-submit-bug-report t] - "-" - ["Describe Rd Mode" describe-mode t]) - "Menu used in Rd mode.") - -(defvar Rd-to-help-command "R CMD Rd2txt" - "Shell command for converting R documentation source to help text.") - -(defvar Rd-font-list - '((?\C-b "\\bold{" "}") - (?\C-c "\\code{" "}") - (?\C-e "\\emph{" "}") - (?\C-l "\\link{" "}") - (?l "\\code{\\link{" "}}") - (?\C-m "\\email{" "}") - (?\C-q "\\eqn{" "}") - (?\C-u "\\url{" "}") - ) - "List of \"fonts\" used by `Rd-font'. -Each entry is a list. The first element is the key to activate -the font. The second element is the string to insert before -point, and the third element is the string to insert after -point.") - - -;;;###autoload -(define-derived-mode Rd-mode text-mode "Rd" - "Major mode for editing R documentation source files. - -Type \\[list-abbrevs] to display the built-in abbrevs for Rd -keywords.To automatically turn on the abbrev(iate) features, add -the following to your Emacs configuration file: - - (add-hook 'Rd-mode-hook #'abbrev-mode)" - (setq ess-language "S" ess-dialect "R") - (require 'ess-r-mode) - (ess-setq-vars-local ess-r-customize-alist) - - (setq-local indent-line-function 'Rd-mode-indent-line) - (setq fill-column 72) - (setq-local comment-start-skip "\\s<+\\s-*") - (setq-local comment-start "% ") - (setq-local comment-end "") - (setq font-lock-defaults - '(Rd-font-lock-keywords nil nil)) - - ;; Here is a workaround for an Emacs bug related to indirect buffers and - ;; spurious lockfiles that rears its ugly head with .Rd files - ;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2013-02/msg01368.html - ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=14328 - (setq-local create-lockfiles nil) - - (easy-menu-define Rd-mode-menu-map Rd-mode-map - "Menu keymap for Rd mode." Rd-mode-menu) - - (turn-on-auto-fill)) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode)) - -(defun Rd-describe-major-mode () - "Describe the current major mode." - (declare (obsolete describe-mode "ESS 19.04")) - (describe-function major-mode)) - -(defun Rd-mode-in-verbatim-p () - "Return non-nil if in a usage, examples, or synopsis." - (let ((pos (point))) - (save-excursion - (if (and (re-search-backward - "\\\\\\(usage\\|examples\\|synopsis\\)" nil t) - (re-search-forward "\\s(" nil t)) - (condition-case () - (progn - (up-list 1) - (< pos (point))) - (error t)) - nil)))) - -(defun Rd-mode-in-preprocessor-line-p () - "Return non-nil if in a preprocessor line." - (save-excursion - (beginning-of-line) - (looking-at "[ \t]*#\\(ifdef\\|endif\\)"))) - -(defun Rd-mode-calculate-indent () - "Return appropriate indentation for current line in Rd mode." - (save-excursion - (beginning-of-line) - (cond - ((Rd-mode-in-verbatim-p) - ;; Don't do anything in verbatims - nil) - ((Rd-mode-in-preprocessor-line-p) - ;; Indent to 0 - 0) - (t - (let ((p (progn - (re-search-forward "[ \t]*\\s)*" (point-at-eol) t) - (point)))) - (if (or (< (forward-line -1) 0) - (Rd-mode-in-verbatim-p)) - 0 - (set-syntax-table Rd-mode-parse-syntax-table) - (while (and (or (looking-at "[ \t]*$") - (Rd-mode-in-preprocessor-line-p)) - (not (bobp))) - (forward-line -1)) - (re-search-forward "[ \t]*\\s)*" (point-at-eol) t) - (prog1 - (+ (current-indentation) - (* (car (parse-partial-sexp (point) p)) - Rd-indent-level)) - (set-syntax-table Rd-mode-syntax-table)))))))) - -(defun Rd-mode-indent-line () - "Indent current line as Rd source." - (when-let ((ic (Rd-mode-calculate-indent)) - (rp (- (current-column) (current-indentation)))) - (when (< ic 0) - (error "Unmatched parenthesis")) - (indent-line-to ic) - (when (> rp 0) - (move-to-column (+ ic rp))))) - -(defun Rd-mode-insert-item () - "Insert \\item{ on a newline." - (interactive) - (reindent-then-newline-and-indent) - (insert "\\item{") - ) - -(defun Rd-mode-insert-section () - "Insert a section from `Rd-section-names'." - (interactive) - (let ((s (ess-completing-read - "Insert section: " - (mapcar (lambda (x) (cons x x)) Rd-section-names) - nil t))) - (if (string= s "") - (progn (insert "\\section{}{") (backward-char 2)) - (insert (format "\\%s{" s))))) - -(defun Rd-mode-insert-skeleton () - "Insert several empty Rd fields." - (interactive) - ;; Hmm: in theory this should be kept in sync with prompt() - ;; --- maybe using prompt() [or promptClass()...] would be better anyway?! - (insert "\\name{}\n") - (insert "\\alias{}\n") - (insert "\\title{}\n") - (insert "\\description{\n}\n") - (insert "\\usage{\n}\n") - (insert "\\arguments{\n}\n") - (insert "\\value{\n}\n") - (insert "\\details{\n}\n") - (insert "\\references{\n}\n") - (insert "\\seealso{\n}\n") - (insert "\\examples{\n}\n") - (insert "\\author{}\n") - (insert "\\keyword{}\n")) - -;; This is an `easy' version of (defun TeX-font ..) in AUCtex's tex.el ; -;; see TeX-font-list and also LaTeX-font-list in latex.el - -(defun Rd-font (what) - "Insert template for font command. -WHAT determines the font to use, as specified by `Rd-font-list'." - (interactive "c") - ;;TeX had : (Rd-update-style) - (let* ((entry (assoc what Rd-font-list)) - (before (nth 1 entry)) - (after (nth 2 entry))) - (cond ((null entry) ;; help on possibilities : - (let ((help - (concat - "Rd Markup (available from C-c C-f):\n\n\t" - "KEY Rd-Markup\n\n" - (mapconcat - (lambda (entry) - ;; A textual description of an ENTRY in TeX-font-list. - (concat (format "%11s " - (key-description - (char-to-string (nth 0 entry)))) - (format "%14s %-3s" - (nth 1 entry) (nth 2 entry)))) - Rd-font-list "\n")))) - (with-output-to-temp-buffer "*Help*" - (set-buffer "*Help*") - (insert help)))) - - ((region-active-p) - (save-excursion - (cond ((> (mark) (point)) - (insert before) - (goto-char (mark)) - (insert after)) - (t - (insert after) - (goto-char (mark)) - (insert before))))) - (t - (insert before) - (save-excursion - (insert after)))))) - -(defun Rd-preview-help (&optional via-shell) - "Preview the current Rd buffer contents as help. -If the current buffer is not associated with a file, create a -temporary one in variable `temporary-file-directory'." - (declare (advertised-calling-convention () "ESS 19.04")) - (interactive "P") ; If optional VIA-SHELL is set, using `Rd-to-help-command'. - (let ((file buffer-file-name) - (pbuf (get-buffer-create "R Help Preview")) - del-p) - (unless file - (setq file (make-temp-file "RD_" nil ".Rd")) - (write-region (point-min) (point-max) file) - (setq del-p t)) - - (if via-shell ;; FIXME eventually get rid of this option - ;; only method in ESS <= 14.09 -- calls "R" even if in "R-devel"; slower - (let ((shcmd (format "%s '%s'" Rd-to-help-command file))) - (set-buffer pbuf) - (erase-buffer) - (ess-write-to-dribble-buffer - (format "Rd-preview-help: (shell-command |%s| t)" shcmd)) - (shell-command shcmd t)) - ;; else directly: - (ess-force-buffer-current "R process to use: ") - (ess-command (format ".ess_Rd2txt(\"%s\")\n" file) pbuf) - (set-buffer pbuf)) - - ;; FIXME(2): once got rid of via-shell, consider - ;; (ess--flush-help-into-current-buffer file "tools::Rd2txt(\"%s\")\n") - ;; instead of all this : - (ess-setq-vars-local ess-r-customize-alist) - ;; mostly cut'n'paste from ess--flush-help* (see FIXME(2)): - (ess-help-underline) - (ess--help-major-mode) - ;; FIXME: Is this really needed? - (setq ess-help-sec-regex ess-help-r-sec-regex - ess-help-sec-keys-alist ess-help-r-sec-keys-alist) - (goto-char (point-min)) - (set-buffer-modified-p 'nil) - (setq buffer-read-only t) - (setq truncate-lines nil) - (when del-p (delete-file file)) - (unless (get-buffer-window pbuf 'visible) - (display-buffer pbuf t)))) - -(define-obsolete-function-alias 'Rd-submit-bug-report 'ess-submit-bug-report "2018-08-16") - -(provide 'ess-rd) - -;;; ess-rd.el ends here diff --git a/elpa/ess-20191014.1343/ess-rdired.el b/elpa/ess-20191014.1343/ess-rdired.el deleted file mode 100644 index 312a0f9a..00000000 --- a/elpa/ess-20191014.1343/ess-rdired.el +++ /dev/null @@ -1,318 +0,0 @@ -;;; ess-rdired.el --- prototype object browser for R, looks like dired mode. -*- lexical-binding: t; -*- - -;; Copyright (C) 2002--2019 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, Stephen Eglen, and J. Alexander Branham. - -;; Author: Stephen Eglen -;; Created: Thu 24 Oct 2002 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is not part of GNU Emacs. - -;; ess-rdired.el is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; ess-rdired.el is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;; This provides a dired-like buffer for R objects. Instead of -;; operating on files, we operate on R objects in the current -;; environment. Objects can be viewed, edited, deleted, plotted and -;; so on. - -;;; Commentary: - -;; Do "M-x R" to start an R session, then create a few variables: -;; -;; s <- sin(seq(from=0, to=8*pi, length=100)) -;; x <- c(1, 4, 9) -;; y <- rnorm(20) -;; z <- TRUE - -;; Then in Emacs, do "M-x ess-rdired" and you should see the following in -;; the buffer *R dired*: -;; Name Class Length Size -;; s numeric 100 848 bytes -;; x numeric 3 80 bytes -;; y numeric 20 208 bytes -;; z logical 1 56 bytes - -;; Type "?" in the buffer to see the documentation. e.g. when the -;; cursor is on the line for `s', type 'p' to plot it, or `v' to view -;; its contents in a buffer. Then type 'd' to delete it. - -;; How it works. - -;; Most of the hard work is done by the R routine .rdired.objects(), -;; which, when called, produces the list of objects in a tidy format. -;; This function is stored within the Lisp variable `ess-rdired-objects'. - -;; Todo - How to select alternative environments? Currently only -;; shows objects in the .GlobalEnv? See BrowseEnv() in 1.6.x for way -;; of browsing other environments. - -;; Todo - problem with fix -- have to wait for fix() command to return -;; before *R* buffer can be used again. This can get stuck, umm. not -;; sure what is going wrong here. Maybe add a hook to the temp buffer -;; so that when buffer is killed, we send an instruction to R to -;; update the value of the variable to the contents of the buffer. -;; This way *R* doesn't have to wait. - -;; Todo - small bug in .rdired.objects -- if we have a variable called -;; `my.x', its value is replaced by the value of my.x used in the -;; sapply() calls within .rdired.objects(). - -;;; Code: - -(require 'ess-inf) - -(eval-when-compile - (require 'subr-x)) - -(defvar ess-rdired-objects "local({.rdired.objects <- function(objs) { - if (length(objs)==0) { - \"No objects to view!\" - } else { - mode <- sapply(objs, function(my.x) { - eval( parse( text=sprintf('data.class(get(\"%s\"))', my.x))) }) - length <- sapply(objs, function(my.x) { - eval( parse( text=sprintf('length(get(\"%s\"))', my.x))) }) - size <- sapply(objs, function(my.x) { - eval( parse( text=sprintf('format(object.size(get(\"%s\")), units=\"b\")', my.x))) }) - d <- data.frame(mode, length, size) - - var.names <- row.names(d) - - ## If any names contain spaces, we need to quote around them. - quotes = rep('', length(var.names)) - spaces = grep(' ', var.names) - if (any(spaces)) - quotes[spaces] <- '\"' - var.names = paste(quotes, var.names, quotes, sep='') - row.names(d) <- paste(' ', var.names, sep='') - d - } -}; cat('\n'); print(.rdired.objects(ls(envir = .GlobalEnv)))})\n" - "Function to call within R to print information on objects. -The last line of this string should be the instruction to call -the function which prints the output for rdired.") - -(defvar ess-rdired-buffer "*R dired*" - "Name of buffer for displaying R objects.") - -(defvar ess-rdired-auto-update-timer nil - "The timer object for auto updates.") - -(defcustom ess-rdired-auto-update-interval 5 - "Seconds between refreshes of the `ess-rdired' buffer." - :type '(choice (const nil :tag "No auto updates") (integer :tag "Seconds")) - :group 'ess-R - :package-version '(ess . "19.04")) - -(defvar ess-rdired-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "d" #'ess-rdired-delete) - (define-key map "x" #'ess-rdired-delete) - (define-key map "v" #'ess-rdired-view) - (define-key map "V" #'ess-rdired-View) - (define-key map "p" #'ess-rdired-plot) - (define-key map "y" #'ess-rdired-type) - (define-key map "\C-c\C-s" #'ess-rdired-switch-process) - (define-key map "\C-c\C-y" #'ess-switch-to-ESS) - (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) - map)) - -(define-derived-mode ess-rdired-mode tabulated-list-mode "Rdired" - "Major mode for output from `ess-rdired'. -`ess-rdired' provides a dired-like mode for R objects. It shows the -list of current objects in the current environment, one-per-line. You -can then examine these objects, plot them, and so on." - :group 'ess-R - (setq mode-name (concat "RDired " ess-local-process-name)) - (setq tabulated-list-format - `[("Name" 18 t) - ("Class" 10 t) - ("Length" 10 ess-rdired--length-predicate) - ("Size" 10 ess-rdired--size-predicate)]) - (add-hook 'tabulated-list-revert-hook #'ess-rdired-refresh nil t) - (when (and (not ess-rdired-auto-update-timer) - ess-rdired-auto-update-interval) - (setq ess-rdired-auto-update-timer - (run-at-time t ess-rdired-auto-update-interval #'ess-rdired-refresh))) - (add-hook 'kill-buffer-hook #'ess-rdired-cancel-auto-update-timer nil t) - (tabulated-list-init-header)) - -;;;###autoload -(defun ess-rdired () - "Show R objects from the global environment in a separate buffer. -You may interact with these objects, see `ess-rdired-mode' for -details." - (interactive) - (unless (and (string= "R" ess-dialect) - ess-local-process-name) - (error "Not in an R buffer with attached process")) - (let ((proc ess-local-process-name)) - (pop-to-buffer (get-buffer-create ess-rdired-buffer)) - (setq ess-local-process-name proc) - (ess-rdired-mode) - (ess-rdired-refresh))) - -(defun ess-rdired-refresh () - "Refresh the `ess-rdired' buffer." - (let* ((buff (get-buffer-create ess-rdired-buffer)) - (proc-name (buffer-local-value 'ess-local-process-name buff)) - (proc (get-process proc-name)) - (out-buff (get-buffer-create " *ess-rdired-output*")) - text) - (when (and proc-name proc - (not (process-get proc 'busy))) - (ess-command ess-rdired-objects out-buff nil nil nil proc) - (with-current-buffer out-buff - (goto-char (point-min)) - ;; Delete two lines. One filled with +'s from R's prompt - ;; printing, the other with the header info from the data.frame - (delete-region (point-min) (1+ (point-at-eol 2))) - (setq text (split-string (buffer-string) "\n" t "\n")) - (erase-buffer)) - (with-current-buffer buff - (setq tabulated-list-entries - (mapcar #'ess-rdired--tabulated-list-entries text)) - (let ((entry (tabulated-list-get-id)) - (col (current-column))) - (tabulated-list-print) - (while (not (equal entry (tabulated-list-get-id))) - (forward-line)) - (move-to-column col)))))) - -(defun ess-rdired-cancel-auto-update-timer () - "Cancel the timer `ess-rdired-auto-update-timer'." - (setq ess-rdired-auto-update-timer - (cancel-timer ess-rdired-auto-update-timer))) - -(defun ess-rdired--tabulated-list-entries (text) - "Return a value suitable for `tabulated-list-entries' from TEXT." - (let (name class length size) - (if (not (string-match-p " +\"" text)) - ;; Normal-world - (setq text (split-string text " " t) - name (nth 0 text) - text (cdr text)) - ;; Else, someone has spaces in their variable names - (string-match "\"\\([^\"]+\\)" text) - (setq name (substring (match-string 0 text) 1) - text (split-string (substring text (1+ (match-end 0))) " " t))) - (setq class (nth 0 text) - length (nth 1 text) - size (nth 2 text)) - (list name - `[(,name - help-echo "mouse-2, RET: View this object" - action ess-rdired-view) - ,class - ,length - ,size]))) - -(defun ess-rdired-edit () - "Edit the object at point." - (interactive) - (ess-command (concat "edit(" (tabulated-list-get-id) ")\n"))) - -(defun ess-rdired-view (&optional _button) - "View the object at point." - (interactive) - (ess-execute (ess-rdired-get (tabulated-list-get-id)) - nil "R view" )) - -(defun ess-rdired-get (name) - "Generate R code to get the value of the variable NAME. -This is complicated because some variables might have spaces in their names. -Otherwise, we could just pass the variable name directly to *R*." - (concat "get(" (ess-rdired-quote name) ")") - ) - -(defun ess-rdired-quote (name) - "Quote NAME if not already quoted." - (if (equal (substring name 0 1) "\"") - name - (concat "\"" name "\""))) - -(defun ess-rdired-View () - "View the object at point in its own buffer. -Like `ess-rdired-view', but the object gets its own buffer name." - (interactive) - (let ((objname (tabulated-list-get-id))) - (ess-execute (ess-rdired-get objname) - nil (concat "R view " objname )))) - -(defun ess-rdired-plot () - "Plot the object on current line." - (interactive) - (let ((objname (tabulated-list-get-id))) - (ess-eval-linewise (format "plot(%s)" (ess-rdired-get objname))))) - -(defun ess-rdired-type () - "Run the mode() on command at point." - (interactive) - (let ((objname (tabulated-list-get-id)) - ;; create a temp buffer, and then show output in echo area - (tmpbuf (get-buffer-create "**ess-rdired-mode**"))) - (if objname - (progn - (ess-command (concat "mode(" (ess-rdired-get objname) ")\n") - tmpbuf ) - (set-buffer tmpbuf) - (message "%s" (concat - objname ": " - (buffer-substring (+ 4 (point-min)) (1- (point-max))))) - (kill-buffer tmpbuf))))) - -(defalias 'ess-rdired-expunge #'ess-rdired-delete) - -(defun ess-rdired-delete () - "Delete the object at point." - (interactive) - (let ((objname (tabulated-list-get-id))) - (when (yes-or-no-p (format "Really delete %s? " objname)) - (ess-eval-linewise (format "rm(%s)" (ess-rdired-quote objname)) nil nil nil t) - (revert-buffer)))) - -(defun ess-rdired-switch-process () - "Switch to examine different *R* process. -If you have multiple R processes running, e.g. *R*, *R:2*, *R:3*, you can -use this command to choose which R process you would like to examine. -After switching to a new process, the buffer is updated." - (interactive) - (ess-switch-process) - (ess-rdired)) - -(defun ess-rdired--length-predicate (A B) - "Enable sorting by length in `ess-rdired' buffers. -Return t if A's length is < than B's length." - (let ((lenA (aref (cadr A) 2)) - (lenB (aref (cadr B) 2))) - (< (string-to-number lenA) (string-to-number lenB)))) - -(defun ess-rdired--size-predicate (A B) - "Enable sorting by size in `ess-rdired' buffers. -Return t if A's size is < than B's size." - (let ((lenA (aref (cadr A) 3)) - (lenB (aref (cadr B) 3))) - (< (string-to-number lenA) (string-to-number lenB)))) - -(define-obsolete-function-alias 'ess-rdired-quit #'quit-window "ESS 19.04") -(define-obsolete-function-alias 'ess-rdired-next-line #'forward-to-indentation "ESS 19.04") -(define-obsolete-function-alias 'ess-rdired-previous-line #'backward-to-indentation "ESS 19.04") -(define-obsolete-function-alias 'ess-rdired-move-to-object #'back-to-indentation "ESS 19.04") - -(provide 'ess-rdired) - -;;; ess-rdired.el ends here diff --git a/elpa/ess-20191014.1343/ess-roxy.el b/elpa/ess-20191014.1343/ess-roxy.el deleted file mode 100644 index 290deefa..00000000 --- a/elpa/ess-20191014.1343/ess-roxy.el +++ /dev/null @@ -1,1035 +0,0 @@ -;;; ess-roxy.el --- convenient editing of in-code roxygen documentation -;; -;; Copyright (C) 2009--2018 Henning Redestig, A.J. Rossini, Richard -;; M. Heiberger, Martin Maechler, Kurt Hornik, Rodney Sparapani, Stephen -;; Eglen, Vitalie Spinu, and J. Alexander Branham. -;; -;; Author: Henning Redestig -;; Keywords: convenience, tools -;; -;; This file is part of ESS -;; -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3 of the -;; License, or (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see -;; . - - -;;; Commentary: - -;; Lots of inspiration from doc-mode, -;; https://nschum.de/src/emacs/doc-mode/ -;; -;; Features:: -;; -;; - basic highlighting -;; - generating and updating templates from function definition and customized default template -;; - C-c C-o C-o :: update template -;; - navigating and filling roxygen fields -;; - C-c TAB, M-q, C-a, ENTER, M-h :: advised tag completion, fill-paragraph, -;; ess-roxy-move-beginning-of-line, newline-and-indent -;; - C-c C-o n,p :: next, previous roxygen entry -;; - C-c C-o C-c :: Unroxygen region. Convenient for editing examples. -;; - folding visibility using hs-minor-mode -;; - TAB :: advised ess-indent-command, hide entry if in roxygen doc. -;; - preview -;; - C-c C-o C-r :: create a preview of the Rd file as generated -;; using roxygen -;; - C-c C-o C-t :: create a preview of the Rd HTML file as generated -;; using roxygen and the tools package -;; - C-c C-o t :: create a preview of the Rd text file -;; -;; Known issues: -;; -;; - hideshow mode does not work very well. In particular, if ordinary -;; comments precede a roxygen entry, then both will be hidden in the -;; same overlay from start and not unfoldable using TAB since the -;; roxygen prefix is not present. The planned solution is implement -;; a replacement for hideshow. -;; - only limited functionality for S4 documentation. - -;;; Code: - -(require 'ess-utils) -(require 'hideshow) -(require 'outline) -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) -(require 'ess-rd) -(require 'ess-r-syntax) - -(defvar roxy-str) -(defvar ess-r-mode-syntax-table) -(declare-function ess-fill-args "ess-r-mode") -(declare-function ess-fill-continuations "ess-r-mode") -(declare-function inferior-ess-r-force "ess-r-mode") - -(defvar-local ess-roxy-re nil - "Regular expression to recognize roxygen blocks.") - - -;;*;; Roxy Minor Mode - -(defvar ess-roxy-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-o h") #'ess-roxy-hide-all) - (define-key map (kbd "C-c C-o n") #'ess-roxy-next-entry) - (define-key map (kbd "C-c C-o p") #'ess-roxy-previous-entry) - (define-key map (kbd "C-c C-o C-o") #'ess-roxy-update-entry) - (define-key map (kbd "C-c C-o C-r") #'ess-roxy-preview-Rd) - (define-key map (kbd "C-c C-o C-w") #'ess-roxy-preview-HTML) - (define-key map (kbd "C-c C-o C-t") #'ess-roxy-preview-text) - (define-key map (kbd "C-c C-o C-c") #'ess-roxy-toggle-roxy-region) - (define-key map [remap back-to-indentation] #'ess-roxy-goto-end-of-roxy-comment) - (define-key map [remap newline] #'ess-roxy-newline-and-indent) - (define-key map [remap newline-and-indent] #'ess-roxy-newline-and-indent) - (define-key map [remap ess-indent-command] #'ess-roxy-ess-indent-command) - (define-key map [remap move-beginning-of-line] #'ess-roxy-move-beginning-of-line) - (define-key map [remap beginning-of-visual-line] #'ess-roxy-move-beginning-of-line) - map)) - -(defvar ess-roxy-font-lock-keywords nil - "Cache set by `ess-roxy-generate-keywords'. -Used to remove keywords added by function `ess-roxy-mode'.") - -(defun ess-roxy-generate-keywords () - "Generate a list of keywords suitable for `font-lock-add-keywords'." - (setq-local ess-roxy-font-lock-keywords - `((,(concat ess-roxy-re " *\\([@\\]" - (regexp-opt ess-roxy-tags-param t) - "\\)\\>") - (1 'font-lock-keyword-face prepend)) - (,(concat ess-roxy-re " *\\(@" - (regexp-opt '("param" "importFrom" "importClassesFrom" - "importMethodsFrom" "describeIn") - 'words) - "\\)\\(?:[ \t]+\\(\\(?:\\sw+,?\\)+\\)\\)") - (1 'font-lock-keyword-face prepend) - (3 'font-lock-variable-name-face prepend)) - (,(concat "[@\\]" (regexp-opt ess-roxy-tags-noparam t) "\\>") - (0 'font-lock-variable-name-face prepend)) - (,(concat ess-roxy-re) - (0 'bold prepend))))) - -(defvar ess-roxy-fold-examples nil - "Whether to fold `@examples' when opening a buffer. -Use you regular key for `outline-show-entry' to reveal it.") - -;;;###autoload -(define-minor-mode ess-roxy-mode - "Minor mode for editing ROxygen documentation." - :keymap ess-roxy-mode-map - (if ess-roxy-mode - ;; Turn on `ess-roxy-mode': - (progn - (setq-local ess-roxy-re (concat "^" (string-trim comment-start) "+'")) - (font-lock-add-keywords nil (ess-roxy-generate-keywords)) - (add-hook 'completion-at-point-functions #'ess-roxy-complete-tag nil t) - ;; Hideshow Integration - (when ess-roxy-hide-show-p - (hs-minor-mode 1) - (when ess-roxy-start-hidden-p - (ess-roxy-hide-all))) - ;; Outline Integration - (when ess-roxy-fold-examples - (ess-roxy-hide-all-examples)) - ;; Autofill - (setq-local paragraph-start (concat "\\(" ess-roxy-re "\\)*" paragraph-start)) - (setq-local paragraph-separate (concat "\\(" ess-roxy-re "\\)*" paragraph-separate)) - (setq-local adaptive-fill-function 'ess-roxy-adaptive-fill-function) - ;; Hooks - (add-hook 'ess-presend-filter-functions 'ess-roxy-remove-roxy-re nil t)) - ;; Turn off `ess-roxy-mode': - ;; Hideshow - (when (and ess-roxy-hide-show-p hs-minor-mode) - (hs-show-all) - (hs-minor-mode)) - ;; Hooks - (remove-hook 'ess-presend-filter-functions 'ess-roxy-remove-roxy-re t) - (font-lock-remove-keywords nil ess-roxy-font-lock-keywords) - ;; (setq-local syntax-propertize-function nil) - ;; (setq-local font-lock-fontify-region-function nil) - ;; (setq-local font-lock-unfontify-region-function nil) - ) - ;; Regardless of turning on or off we need to re-fontify the buffer: - (when font-lock-mode - (font-lock-flush))) - - - -;;*;; Outline Integration - -(defvar ess-roxy-outline-regexp "^#+' +@examples\\|^[^#]") - -(defun ess-roxy-substitute-outline-regexp (command) - (let ((outline-regexp (if (ess-roxy-entry-p "examples") - ess-roxy-outline-regexp - outline-regexp))) - (funcall command))) - -(declare-function outline-cycle "outline-magic") -(defun ess-roxy-cycle-example () - (interactive) - (unless (featurep 'outline-magic) - (error "Please install and load outline-magic")) - ;; Don't show children when cycling @examples - (let ((this-command 'outline-cycle-overwiew)) - (ess-roxy-substitute-outline-regexp #'outline-cycle))) - -(defun ess-roxy-show-example () - (interactive) - (ess-roxy-substitute-outline-regexp #'outline-show-entry)) - -(defun ess-roxy-hide-example () - (interactive) - (ess-roxy-substitute-outline-regexp #'outline-hide-entry)) - -(defun ess-roxy-hide-all-examples () - (interactive) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "^#+' +@examples\\b" nil t) - ;; Handle edge cases - (when (ess-roxy-entry-p "examples") - (ess-roxy-hide-example))))) - -(when (featurep 'outline-magic) - (substitute-key-definition 'outline-cyle - 'ess-roxy-cyle-example - ess-roxy-mode-map outline-mode-menu-bar-map)) - -(substitute-key-definition 'outline-hide-entry - 'ess-roxy-hide-example - ess-roxy-mode-map outline-minor-mode-map) - -(substitute-key-definition 'outline-show-entry - 'ess-roxy-show-example - ess-roxy-mode-map outline-minor-mode-map) - - -;;*;; Function definitions - -(defun ess-back-to-roxy () - "Go to roxy prefix." - (end-of-line) - (re-search-backward (concat ess-roxy-re " ?") (point-at-bol)) - (goto-char (match-end 0))) - -(defun ess-roxy-beg-of-entry () - "Get point number at start of current entry, 0 if not in entry." - (save-excursion - (let (beg) - (beginning-of-line) - (setq beg -1) - (if (not (ess-roxy-entry-p)) - (setq beg 0) - (setq beg (point))) - (while (and (= (forward-line -1) 0) (ess-roxy-entry-p)) - (setq beg (point))) - beg))) - -(defun ess-roxy-in-header-p () - "True if point is the description / details field." - (save-excursion - (let ((res t) - (cont (ess-roxy-entry-p))) - (beginning-of-line) - (while cont - (if (looking-at (concat ess-roxy-re " *[@].+")) - (progn (setq res nil) - (setq cont nil))) - (setq cont (and (= (forward-line -1) 0) (ess-roxy-entry-p))) - )res))) - -(defun ess-roxy-beg-of-field () - "Get point number at beginning of current field, 0 if not in entry." - (save-excursion - (let (cont beg) - (beginning-of-line) - (setq beg 0) - (setq cont t) - (while (and (ess-roxy-entry-p) cont) - (setq beg (point)) - (if (looking-at (concat ess-roxy-re " *[@].+")) - (setq cont nil)) - (if (ess-roxy-in-header-p) - (if (looking-at (concat ess-roxy-re " *$")) - (progn - (forward-line 1) - (setq beg (point)) - (setq cont nil)))) - (if cont (setq cont (= (forward-line -1) 0)))) - beg))) - -(defun ess-roxy-end-of-entry () - "Get point number at end of current entry, 0 if not in entry." - (save-excursion - (let ((end)) - (end-of-line) - (setq end -1) - (if (not (ess-roxy-entry-p)) - (setq end 0) - (setq end (point))) - (while (and (= (forward-line 1) 0) (ess-roxy-entry-p)) - (end-of-line) - (setq end (point))) - end))) - -(defun ess-roxy-end-of-field () - "Get point number at end of current field, 0 if not in entry." - (save-excursion - (let ((end nil) - (cont nil)) - (setq end 0) - (if (ess-roxy-entry-p) (progn (end-of-line) (setq end (point)))) - (beginning-of-line) - (forward-line 1) - (setq cont t) - (while (and (ess-roxy-entry-p) cont) - (save-excursion - (end-of-line) - (setq end (point))) - (if (or (and (ess-roxy-in-header-p) - (looking-at (concat ess-roxy-re " *$"))) - (looking-at (concat ess-roxy-re " *[@].+"))) - (progn - (forward-line -1) - (end-of-line) - (setq end (point)) - (setq cont nil))) - (if cont (setq cont (= (forward-line 1) 0)))) - end))) - -(defun ess-roxy-entry-p (&optional field) - "Non-nil if point is in a roxy entry. -FIELD allows checking for a specific field with -`ess-roxy-current-field'." - (and ess-roxy-mode - (save-excursion - (beginning-of-line) - (looking-at-p ess-roxy-re)) - (or (null field) - (string= (ess-roxy-current-field) field)))) - -(defun ess-roxy-narrow-to-field () - "Go to to the start of current field." - (interactive) - (let ((beg (ess-roxy-beg-of-field)) - (end (ess-roxy-end-of-field))) - (narrow-to-region beg end))) - -(defun ess-roxy-extract-field () - (let ((field (buffer-substring (ess-roxy-beg-of-entry) - (ess-roxy-end-of-entry))) - (prefix-re (ess-roxy-guess-str)) - (roxy-re ess-roxy-re)) - (with-temp-buffer - (setq ess-roxy-re roxy-re) - (insert field) - (goto-char (point-min)) - (while (re-search-forward prefix-re (point-max) 'noerror) - (replace-match "")) - (buffer-substring (point-min) (point-max))))) - -(defun ess-roxy-adaptive-fill-function () - "Return prefix for filling paragraph or nil if not determined." - (when (ess-roxy-entry-p) - (let ((roxy-str (car (split-string (ess-roxy-guess-str) "'")))) - (if (ess-roxy-in-header-p) - (save-excursion - (ess-back-to-roxy) - (re-search-forward "\\([ \t]*\\)" (line-end-position) t) - (concat roxy-str "' " (match-string 1))) - (concat roxy-str "' " (make-string ess-indent-offset ? )))))) - -(defun ess-roxy-current-field () - "Return the name of the field at point." - (and (not (ess-roxy-in-header-p)) - (save-excursion - (goto-char (ess-roxy-beg-of-field)) - (if (re-search-forward (concat ess-roxy-re - "[ \t]+@\\([[:alpha:]]+\\)") - (line-end-position) t) - (match-string-no-properties 1))))) - -(defun ess-roxy-maybe-indent-line () - "Indent line when point is in a field, but not in its first line." - (when (and (not (ess-roxy-in-header-p)) - (not (equal (ess-roxy-current-field) "examples")) - (save-excursion - (beginning-of-line) - (let ((line-n (count-lines 1 (point)))) - (goto-char (ess-roxy-beg-of-field)) - (not (equal line-n (count-lines 1 (point))))))) - (ess-back-to-roxy) - (delete-region (point) (progn (skip-chars-forward " \t") (point))) - (insert (make-string ess-indent-offset ? )))) - -(defun ess-roxy-goto-func-def () - "Put point at start of function. -Go to the beginning of the current one or below the current -roxygen entry, error otherwise" - (if (ess-roxy-entry-p) - (progn - (ess-roxy-goto-end-of-entry) - (forward-line 1) - (beginning-of-line)) - (unless (looking-at-p ess-function-pattern) - (beginning-of-defun)))) - -(defun ess-roxy-get-args-list-from-def () - "Get args list for current function." - (save-excursion - (ess-roxy-goto-func-def) - (let ((args (ess-roxy-get-function-args))) - (mapcar (lambda (x) (cons x '(""))) args)))) - -(defun ess-roxy-insert-args (args &optional here) - "Insert an ARGS list to the end of the current roxygen entry. -If HERE is supplied start inputting `here'. Finish at end of -line." - (let* ((roxy-str (ess-roxy-guess-str)) - arg-des) - (if (and here (< 1 here)) - (goto-char here) - (ess-roxy-goto-end-of-entry) - (beginning-of-line) - (when (not (looking-at-p "=")) - (end-of-line))) - (while (stringp (caar args)) - (setq arg-des (pop args)) - (unless (string= (car arg-des) "") - (insert (concat "\n" roxy-str " @param " (car arg-des) " ")) - (insert - (ess-replace-in-string (concat (car (cdr arg-des))) "\n" - (concat "\n" roxy-str))) - (when ess-roxy-fill-param-p - (fill-paragraph)))))) - -(defun ess-roxy-merge-args (fun ent) - "Take two args lists (alists) and return their union. -The result holds all keys from both FUN and ENT but no duplicates and -association from ent are preferred over entries from fun. Also, -drop entries from ent that are not in fun and are associated with -the empty string." - (let ((res-arg nil) - (arg-des)) - (while (stringp (caar fun)) - (setq arg-des (pop fun)) - (if (assoc (car arg-des) ent) - (setq res-arg - (cons (cons (car arg-des) (cdr (assoc (car arg-des) ent))) res-arg)) - (setq res-arg (cons (cons (car arg-des) '("")) res-arg)))) - (while (stringp (caar ent)) - (setq arg-des (pop ent)) - (if (and (not (assoc (car arg-des) res-arg)) (not (string= (car (cdr arg-des)) ""))) - (setq res-arg (cons (cons (car arg-des) (cdr arg-des)) res-arg)))) - (nreverse res-arg))) - -(defun ess-roxy-update-entry () - "Update the entry at point or the entry above the current function. -Add a template empty roxygen documentation if no roxygen entry is -available. The template can be customized via the variable -`ess-roxy-template-alist'. The parameter descriptions can are -filled if `ess-roxy-fill-param-p' is non-nil." - (interactive) - (unless (derived-mode-p 'ess-r-mode) - (user-error "%s mode not yet supported" major-mode)) - (save-excursion - (let* ((args-fun (ess-roxy-get-args-list-from-def)) - (args-ent (ess-roxy-get-args-list-from-entry)) - (args (ess-roxy-merge-args args-fun args-ent)) - (roxy-str (ess-roxy-guess-str)) - (line-break "") - template tag-def) - (ess-roxy-goto-func-def) - (when (not (= (forward-line -1) 0)) - (insert "\n") - (forward-line -1)) - (when (and (not (looking-at "^\n")) (not (ess-roxy-entry-p))) - (end-of-line) - (insert "\n")) - (if (ess-roxy-entry-p) - (ess-roxy-insert-args args (1- (ess-roxy-delete-args))) - (setq template (copy-sequence ess-roxy-template-alist)) - (while (stringp (caar template)) - (setq tag-def (pop template)) - (if (string= (car tag-def) "param") - (ess-roxy-insert-args args (point)) - (if (string= (car tag-def) "description") - (insert (concat line-break roxy-str " " - (cdr tag-def) "\n" roxy-str)) - (if (string= (car tag-def) "details") - (insert (concat line-break roxy-str " " (cdr tag-def))) - (insert (concat line-break roxy-str " @" - (car tag-def) " " (cdr tag-def)))))) - (setq line-break "\n")))))) - -(defun ess-roxy-goto-end-of-entry () - "Put point at the bottom of the current entry or above the function at point. -Return t if the point is left in a roxygen entry, otherwise nil. -Error if point is not in function or roxygen entry." - (when (not (ess-roxy-entry-p)) - (beginning-of-defun) - (forward-line -1)) - (if (ess-roxy-entry-p) - (progn (goto-char (ess-roxy-end-of-entry)) - t) - (forward-line) - nil) - (ess-roxy-entry-p)) - -(defun ess-roxy-goto-beg-of-entry () - "Put point at the top of the entry at point or above the function at point. -Return t if the point is left in a roxygen -entry, otherwise nil. Error if point is not in function or -roxygen entry." - (if (not (ess-roxy-entry-p)) - (progn - (goto-char (nth 0 (end-of-defun))) - (forward-line -1))) - (if (ess-roxy-entry-p) - (progn - (goto-char (ess-roxy-beg-of-entry)) - t) - (forward-line) nil)) - -(defun ess-roxy-delete-args () - "Remove all args from the entry at point or above the function at point. -Return 0 if no deletions were made other wise the point at where -the last deletion ended" - (save-excursion - (let* ((cont t) - (field-beg 0) - entry-beg entry-end field-end) - (ess-roxy-goto-end-of-entry) - (setq entry-beg (ess-roxy-beg-of-entry)) - (setq entry-end (ess-roxy-end-of-entry)) - (goto-char entry-end) - (beginning-of-line) - (while (and (<= entry-beg (point)) (> entry-beg 0) cont) - (if (looking-at - (concat ess-roxy-re " *@param")) - (progn - (setq field-beg (ess-roxy-beg-of-field)) - (setq field-end (ess-roxy-end-of-field)) - (delete-region field-beg (+ field-end 1)))) - (setq cont nil) - (if (= (forward-line -1) 0) - (setq cont t))) - field-beg))) - -(defun ess-roxy-get-args-list-from-entry () - "Fill an args list from the entry above the function where the point is." - (save-excursion - (let* (args entry-beg field-beg field-end args-text arg-name desc) - (if (ess-roxy-goto-end-of-entry) - (progn - (setq roxy-str (ess-roxy-guess-str)) - (beginning-of-line) - (setq entry-beg (ess-roxy-beg-of-entry)) - (while (and (< entry-beg (point)) (> entry-beg 0)) - (if (looking-at - (concat ess-roxy-re " *@param")) - (progn - (setq field-beg (ess-roxy-beg-of-field)) - (setq field-end (ess-roxy-end-of-field)) - (setq args-text (buffer-substring-no-properties - field-beg field-end)) - (setq args-text - (ess-replace-in-string args-text roxy-str "")) - (setq args-text - (ess-replace-in-string - args-text "[[:space:]]*@param *" "")) - ;; (setq args-text - ;; (ess-replace-in-string args-text "\n" "")) - (string-match "[^[:space:]]*" args-text) - (setq arg-name (match-string 0 args-text)) - (setq desc (replace-regexp-in-string - (concat "^" (regexp-quote arg-name) " *") "" args-text)) - (setq args (cons (list (concat arg-name) - (concat desc)) - args)))) - (forward-line -1)) - args) - nil)))) - -(defun ess-roxy-toggle-roxy-region (beg end) - "Toggle prefix roxygen string from BEG to END. -Add the prefix if missing, remove if found. BEG and END default -to the region, if active, and otherwise the entire line. This is -convenient for editing example fields." - (interactive "r") - (unless (and beg end) - (setq beg (line-beginning-position) - end (line-end-position))) - (ess-roxy-roxy-region beg end (ess-roxy-entry-p))) - -(defun ess-roxy-roxy-region (beg end &optional on) - (save-excursion - (let (RE to-string - (roxy-str (ess-roxy-guess-str))) - (narrow-to-region beg (- end 1)) - (if on - (progn (setq RE (concat ess-roxy-re " +?")) - (setq to-string "")) - (setq RE "^") - (setq to-string (concat roxy-str " "))) - (goto-char beg) - (while (re-search-forward RE (point-max) 'noerror) - (replace-match to-string)) - (widen)))) - -(defun ess-roxy-preview () - "Generate documentation for roxygen entry at point. -Use a connected R session (starting one if necessary) and -`ess-roxy-package' to generate the Rd code for the entry at -point. Place it in a buffer and return that buffer." - (unless (derived-mode-p 'ess-r-mode) - (user-error "Preview only supported in R buffers, try `ess-r-devtools-document-package' instead")) - (let* ((beg (ess-roxy-beg-of-entry)) - (tmpf (make-temp-file "ess-roxy")) - (roxy-buf (get-buffer-create " *RoxygenPreview*")) - (R-old-roxy - (concat - "..results <- roxygen2:::roc_process(rd_roclet(), parse.files(P), \"\");" - "cat(vapply(..results, function(x) roxygen2:::rd_out_cache$compute(x, format(x)), character(1)))" )) - (R-new-roxy - (concat - "..results <- roc_proc_text(rd_roclet(), readChar(P, file.info(P)$size));" - "cat(vapply(..results, format, character(1)), \"\n\")" )) - (out-rd-roclet - (cond ((string= "roxygen" ess-roxy-package) - "make.Rd2.roclet()$parse") - ;; must not line break strings to avoid getting +s in the output - ((string= "roxygen2" ess-roxy-package) - (concat "(function(P) { if(packageVersion('roxygen2') < '3.0.0') {" - R-old-roxy "} else {" R-new-roxy "} })")) - (t (error "Need to hard code the roclet output call for roxygen package '%s'" - ess-roxy-package))))) - (when (= beg 0) - (error "Point is not in a Roxygen entry")) - (save-excursion - (goto-char (ess-roxy-end-of-entry)) - (forward-line 1) - (if (end-of-defun) - (append-to-file beg (point) tmpf) - (while (and (forward-line 1) - (not (looking-at-p "^$")) - (not (eobp)) - (not (looking-at-p ess-roxy-re)))) - (append-to-file beg (point) tmpf)) - (inferior-ess-r-force) - (ess-force-buffer-current) - (unless (ess-boolean-command (concat "print(suppressWarnings(require(" ess-roxy-package - ", quietly=TRUE)))\n")) - (error (concat "Failed to load the " ess-roxy-package " package; " - "in R, try install.packages(\"" ess-roxy-package "\")"))) - (ess-command (concat out-rd-roclet "(\"" tmpf "\")\n") roxy-buf) - (with-current-buffer roxy-buf - ;; Kill characters up to % in case we missed stripping prompts - ;; or +'s: - (goto-char (point-min)) - (when (re-search-forward "%" (line-end-position) t) - (backward-char) - (delete-region (line-beginning-position) (point))))) - (delete-file tmpf) - roxy-buf)) - -(defun ess-roxy-preview-HTML (&optional visit-instead-of-browse) - "Use a (possibly newly) connected R session and the roxygen package to -generate a HTML page for the roxygen entry at point and open that -buffer in a browser. Visit the HTML file instead of showing it in -a browser if `visit-instead-of-browse' is non-nil." - (interactive "P") - (let* ((roxy-buf (ess-roxy-preview)) - (rd-tmp-file (make-temp-file "ess-roxy-" nil ".Rd")) - (html-tmp-file (make-temp-file "ess-roxy-" nil ".html")) - (rd-to-html (concat "Rd2HTML(\"" rd-tmp-file "\",\"" - html-tmp-file "\", stages=c(\"render\"))")) - ) - (with-current-buffer roxy-buf - (set-visited-file-name rd-tmp-file) - (save-buffer) - (kill-buffer roxy-buf)) - (ess-force-buffer-current) - (ess-command "print(suppressWarnings(require(tools, quietly=TRUE)))\n") - (if visit-instead-of-browse - (progn - (ess-command (concat rd-to-html "\n")) - (find-file html-tmp-file)) - (ess-command (concat "browseURL(" rd-to-html ")\n"))))) - -(defun ess-roxy-preview-text () - "Use the connected R session and the roxygen package to -generate the text help page of the roxygen entry at point." - (interactive) - (with-current-buffer (ess-roxy-preview) - (Rd-preview-help))) - -(defun ess-roxy-preview-Rd (&optional name-file) - "Preview Rd for the roxygen entry at point. -Use the connected R session and the roxygen package to -generate the Rd code for the roxygen entry at point. If called -with a non-nil NAME-FILE (\\[universal-argument]), -also set the visited file name of the created buffer to -facilitate saving that file." - (interactive "P") - (let ((roxy-buf (ess-roxy-preview))) - (pop-to-buffer roxy-buf) - (if name-file - (save-excursion - (goto-char 1) - (search-forward-regexp "name{\\(.+\\)}") - (set-visited-file-name (concat (match-string 1) ".Rd")))) - (Rd-mode) - ;; why should the following be needed here? [[currently has no effect !!]] - ;; usually in a *.Rd file fontification happens automatically - (font-lock-ensure))) - - -(defun ess-roxy-guess-str (&optional not-here) - "Guess the prefix used in the current roxygen block. -If NOT-HERE is non-nil, guess the prefix for nearest roxygen -block before the point." - (save-excursion - (if (ess-roxy-entry-p) - (progn - (goto-char (point-at-bol)) - (search-forward-regexp ess-roxy-re)) - (if not-here - (search-backward-regexp ess-roxy-re))) - (if (or not-here (ess-roxy-entry-p)) - (match-string 0) - (if (derived-mode-p 'ess-r-mode) - ess-roxy-str - (concat (string-trim comment-start) "'"))))) - -(defun ess-roxy-hide-block () - "Hide current roxygen comment block." - (interactive) - (save-excursion - (let ((end-of-entry (ess-roxy-end-of-entry)) - (beg-of-entry (ess-roxy-beg-of-entry))) - (hs-hide-block-at-point nil (list beg-of-entry end-of-entry))))) - -(defun ess-roxy-toggle-hiding () - "Toggle hiding/showing of a block. -See `hs-show-block' and `ess-roxy-hide-block'." - (interactive) - (hs-life-goes-on - (if (hs-overlay-at (point-at-eol)) - (hs-show-block) - (ess-roxy-hide-block)))) - -(defun ess-roxy-show-all () - "Hide all Roxygen entries in current buffer." - (interactive) - (ess-roxy-hide-all t)) - -(defun ess-roxy-hide-all (&optional show) - "Hide all Roxygen entries in current buffer." - (interactive) - (when (not ess-roxy-hide-show-p) - (user-error "First enable hide-show with `ess-roxy-hide-show-p'")) - (hs-life-goes-on - (save-excursion - (goto-char (point-min)) - (while (re-search-forward (concat ess-roxy-re) (point-max) t 1) - (let ((end-of-entry (ess-roxy-end-of-entry))) - (if show - (hs-show-block) - (ess-roxy-hide-block)) - (goto-char end-of-entry) - (forward-line 1)))))) - -(defun ess-roxy-previous-entry () - "Go to beginning of previous Roxygen entry." - (interactive) - (if (ess-roxy-entry-p) - (progn - (goto-char (ess-roxy-beg-of-entry)) - (forward-line -1))) - (search-backward-regexp ess-roxy-re (point-min) t 1) - (goto-char (ess-roxy-beg-of-entry))) - -(defun ess-roxy-next-entry () - "Go to beginning of next Roxygen entry." - (interactive) - (if (ess-roxy-entry-p) - (progn - (goto-char (ess-roxy-end-of-entry)) - (forward-line 1))) - (search-forward-regexp ess-roxy-re (point-max) t 1) - (goto-char (ess-roxy-beg-of-entry))) - -(defun ess-roxy-get-function-args () - "Return the arguments specified for the current function as a list of strings. -Assumes point is at the beginning of the function." - (save-excursion - (let ((args-txt - (buffer-substring-no-properties - (progn - (search-forward-regexp "\\([=,-]+ *function *\\|^\s*function\\)" nil nil 1) - (+ (point) 1)) - (progn - (ess-roxy-match-paren) - (point))))) - (setq args-txt (replace-regexp-in-string "#+[^\"']*\n" "" args-txt)) - (setq args-txt (replace-regexp-in-string "([^)]+)" "" args-txt)) - (setq args-txt (replace-regexp-in-string "=[^,]+" "" args-txt)) - (setq args-txt (replace-regexp-in-string "[ \t\n]+" "" args-txt)) - (split-string args-txt ",")))) - -(defun ess-roxy-match-paren () - "Go to the matching parenthesis." - (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1)) - ((looking-at "\\s\)") (forward-char 1) (backward-list 1)))) - -(defun ess-roxy-complete-tag () - "Complete the tag at point." - (let ((bounds (ess-bounds-of-symbol))) - (when (and bounds - (save-excursion - (goto-char (car bounds)) - (eq (following-char) ?@))) - (list (1+ (car bounds)) (cdr bounds) - (append ess-roxy-tags-noparam ess-roxy-tags-param))))) - -(defun ess-roxy-tag-completion () - "Completion data for Emacs >= 24." - (when (save-excursion (re-search-backward "@\\<\\(\\w*\\)" (point-at-bol) t)) - (let ((beg (match-beginning 1)) - (end (match-end 1))) - (when (and end (= end (point))) - (list beg end (append ess-roxy-tags-noparam ess-roxy-tags-param) :exclusive 'no))))) - -(defun ess-roxy-remove-roxy-re (string) - "Remove `ess-roxy-str' from STRING before sending to R process. -Useful for sending code from example section. This function is -placed in `ess-presend-filter-functions'." - ;; Only strip the prefix in the @examples field, and only when - ;; STRING is entirely contained inside it. This allows better - ;; behavior for evaluation of regions. - (let ((roxy-re ess-roxy-re)) - (if (and (ess-roxy-entry-p "examples") - ;; don't send just @examples if we're looking at a line - ;; like: ##' @examples - (not (string-match-p (concat roxy-re "[[:space:]]*@") string)) - ;; (with-temp-buffer - ;; ;; Need to carry the buffer-local value of - ;; ;; `ess-roxy-re' into the temp buffer: - ;; (setq ess-roxy-re roxy-re) - ;; (insert string) - ;; (ess-roxy-entry-p)) - ) - (replace-regexp-in-string (concat ess-roxy-re "\\s-*") "" string) - string))) - -(defun ess-roxy-find-par-end (stop-point &rest stoppers) - (mapc #'(lambda (stopper) - (when (and (> stop-point (point)) - (save-excursion - (re-search-forward stopper stop-point t))) - (setq stop-point (match-beginning 0)))) - stoppers) - (save-excursion - (goto-char stop-point) - (line-end-position 0))) - - -;;*;; Advices -(defmacro ess-roxy-with-filling-context (examples &rest body) - "Setup context (e.g. `comment-start') for filling roxygen BODY. -EXAMPLES should be non-nil if filling an example block." - (declare (indent 2) (debug (&rest form))) - `(let ((comment-start (concat ess-roxy-re "[ \t]+#")) - (comment-start-skip (concat ess-roxy-re "[ \t]+# *")) - (comment-use-syntax nil) - (adaptive-fill-first-line-regexp (concat ess-roxy-re "[ \t]*")) - (paragraph-start (concat "\\(" ess-roxy-re "\\(" paragraph-start - "\\|[ \t]*@" "\\)" "\\)\\|\\(" paragraph-start "\\)")) - (temp-table (if ,examples - (make-syntax-table ess-r-mode-syntax-table) - Rd-mode-syntax-table))) - (when ,examples - ;; Prevent the roxy prefix to be interpreted as comment or string - ;; starter - (modify-syntax-entry ?# "w" temp-table) - (modify-syntax-entry ?' "w" temp-table)) - ;; Neutralize (comment-normalize-vars) because it modifies the - ;; comment-start regexp in such a way that paragraph filling of - ;; comments in @examples fields does not work - (cl-letf (((symbol-function 'comment-normalize-vars) #'ignore)) - (with-syntax-table temp-table - ,@body)))) - -(defun ess-roxy-ess-indent-command (&optional whole-exp) - "Hide this block if we are at the beginning of the line. -Else call `ess-indent-command'." - (interactive "P") - (if (and (bolp) (ess-roxy-entry-p) ess-roxy-hide-show-p) - (progn (ess-roxy-toggle-hiding)) - (ess-indent-command whole-exp))) - -(defun ess--roxy-fill-block (fun &optional args) - "Fill a roxygen block. -FUN should be a filling function and ARGS gets passed to it." - (let* ((saved-pos (point)) - (par-start (save-excursion - (if (save-excursion - (and (backward-paragraph) - (forward-paragraph) - (<= (point) saved-pos))) - (line-beginning-position) - (progn (backward-paragraph) (point))))) - (par-end (ess-roxy-find-par-end - (save-excursion - (forward-paragraph) - (point)) - (concat ess-roxy-re "[ \t]*@examples\\b") "^[^#]"))) - ;; Refill the whole structural paragraph sequentially, field by - ;; field, stopping at @examples - (ess-roxy-with-filling-context nil - (save-excursion - (save-restriction - (narrow-to-region par-start par-end) - (goto-char (point-min)) - (while (< (point) (point-max)) - (ess-roxy-maybe-indent-line) - (apply fun args) - (forward-paragraph))))))) - -(defun ess-r--fill-paragraph (orig-fun &rest args) - "ESS fill paragraph for R mode. -Overrides `fill-paragraph' which is ORIG-FUN when necessary and -passes ARGS to it." - (cond - ;; Regular case - ((not (derived-mode-p 'ess-r-mode)) - (apply orig-fun args)) - ;; Filling of code comments in @examples roxy field - ((and (ess-roxy-entry-p) - (save-excursion - (ess-roxy-goto-end-of-roxy-comment) - (looking-at "#"))) - (ess-roxy-with-filling-context t - (apply orig-fun args))) - ((and (not (ess-roxy-entry-p)) - (ess-inside-comment-p)) - (apply orig-fun args)) - ;; Filling of call arguments with point on call name - ((and ess-fill-calls - (ess-inside-call-name-p)) - (save-excursion - (skip-chars-forward "^([") - (forward-char) - (ess-fill-args))) - ;; Filling of continuations - ((and ess-fill-continuations - (ess-inside-continuation-p)) - (ess-fill-continuations)) - ;; Filling of call arguments - ((and ess-fill-calls - (ess-inside-call-p)) - (ess-fill-args)) - ;; Filling of roxy blocks - ((ess-roxy-entry-p) - (ess--roxy-fill-block orig-fun args)) - (t - (apply orig-fun args)))) -(advice-add 'fill-paragraph :around #'ess-r--fill-paragraph) - -(defun ess-roxy-move-beginning-of-line (arg) - "Move point to the beginning of the current line or roxygen comment. -If not in a roxygen comment, call `move-beginning-of-line', which -see for ARG. If in a roxygen field, leave point at the end of a -roxygen comment. If already there, move to the beginning of the -line." - (interactive "^p") - (if (ess-roxy-entry-p) - (let ((pos (point))) - (ess-roxy-goto-end-of-roxy-comment) - (when (eql (point) pos) - (move-beginning-of-line nil))) - (move-beginning-of-line arg))) - -(defun ess-roxy-goto-end-of-roxy-comment () - "Leave point at the end of a roxygen comment. -If not in a roxygen entry, call `back-to-indentation'." - (interactive) - (if (ess-roxy-entry-p) - (progn - (end-of-line) - (re-search-backward (concat ess-roxy-re " *") (point-at-bol) t) - (goto-char (match-end 0))) - (back-to-indentation))) - -(defun ess-roxy-indent-new-comment-line () - (if (not (ess-roxy-entry-p)) - (indent-new-comment-line) - (ess-roxy-indent-on-newline))) - -(defun ess-roxy-newline-and-indent () - "Start a newline and insert the roxygen prefix. -Only do this if in a roxygen block and -`ess-roxy-insert-prefix-on-newline' is non-nil." - (interactive) - (if (and (ess-roxy-entry-p) - ess-roxy-insert-prefix-on-newline) - (ess-roxy-indent-on-newline) - (newline-and-indent))) - -(defun ess-roxy-indent-on-newline () - "Insert a newline in a roxygen field." - (cond - ;; Point at beginning of first line of entry; do nothing - ((= (point) (ess-roxy-beg-of-entry)) - (newline-and-indent)) - ;; Otherwise: skip over roxy comment string if necessary and then - ;; newline and then inset new roxy comment string - (t - (let ((point-after-roxy-string - (save-excursion (forward-line 0) - (ess-back-to-roxy) - (point)))) - (goto-char (max (point) point-after-roxy-string))) - (newline-and-indent) - (insert (concat (ess-roxy-guess-str t) " "))))) - -(defun ess-roxy-cpp-fill-paragraph (&rest _args) - "Advice for `c-fill-paragraph' that accounts for roxygen comments." - (cond - ;; Fill roxy @example's. - ((ess-roxy-entry-p "examples") - (ess--roxy-fill-block 'fill-paragraph) nil) - ;; Fill roxy entries. - ((ess-roxy-entry-p) - (ess--roxy-fill-block 'fill-paragraph) nil) - ;; Return t to signal to go on to `c-fill-paragraph'. - (t t))) - -(advice-add 'c-fill-paragraph :before-while 'ess-roxy-cpp-fill-paragraph) - -(defun ess-roxy-enable-in-cpp () - "Enable `ess-roxy-mode' in C++ buffers in R packages." - (when (and (fboundp 'ess-r-package-project) - (ess-r-package-project)) - (ess-roxy-mode))) - -(with-eval-after-load "cc-mode" - (add-hook 'c++-mode-hook #'ess-roxy-enable-in-cpp)) - -(provide 'ess-roxy) - -;;; ess-roxy.el ends here diff --git a/elpa/ess-20191014.1343/ess-s-lang.el b/elpa/ess-20191014.1343/ess-s-lang.el deleted file mode 100644 index 738ef5b4..00000000 --- a/elpa/ess-20191014.1343/ess-s-lang.el +++ /dev/null @@ -1,534 +0,0 @@ -;;; ess-s-lang.el --- Support for editing S source code -*- lexical-binding: t; -*- - -;; Copyright (C) 1989-1997 D. Bates, Kademan, Ritter, D.M. Smith, K. Hornik, -;; R.M. Heiberger, M. Maechler, and A.J. Rossini. -;; Copyright (C) 1998-2015 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: A.J. Rossini -;; Created: 26 Aug 1997 -;; Maintainer: ESS-core - -;; This file is part of ESS (Emacs Speaks Statistics). - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Code for general editing S source code (specializes to S, S+, R). - -;;; Code: - - ; Requires and autoloads - -(require 'ess-mode) -(require 'ess-help) -(require 'ess-inf) - -(declare-function speedbar-add-supported-extension "speedbar" (extension)) - - ; Configuration variables - -(defvar S-syntax-table - (let ((S-syntax-table (make-syntax-table))) - (modify-syntax-entry ?\\ "\\" S-syntax-table) - (modify-syntax-entry ?+ "." S-syntax-table) - (modify-syntax-entry ?- "." S-syntax-table) - (modify-syntax-entry ?= "." S-syntax-table) - (modify-syntax-entry ?% "." S-syntax-table) - (modify-syntax-entry ?< "." S-syntax-table) - (modify-syntax-entry ?> "." S-syntax-table) - (modify-syntax-entry ?& "." S-syntax-table) - (modify-syntax-entry ?| "." S-syntax-table) - (modify-syntax-entry ?\' "\"" S-syntax-table) - (modify-syntax-entry ?\" "\"" S-syntax-table) - (modify-syntax-entry ?# "<" S-syntax-table) ; open comment - (modify-syntax-entry ?\n ">" S-syntax-table) ; close comment - ;;(modify-syntax-entry ?. "w" S-syntax-table) ; "." used in S obj names - (modify-syntax-entry ?. "_" S-syntax-table) ; see above/below, - ; plus consider separation. - (modify-syntax-entry ?$ "_" S-syntax-table); foo$comp = 1 symbol(completion) - (modify-syntax-entry ?@ "_" S-syntax-table); foo@slot = 1 symbol(completion) - (modify-syntax-entry ?_ "_" S-syntax-table) - (modify-syntax-entry ?: "_" S-syntax-table) - (modify-syntax-entry ?* "." S-syntax-table) - (modify-syntax-entry ?< "." S-syntax-table) - (modify-syntax-entry ?> "." S-syntax-table) - (modify-syntax-entry ?/ "." S-syntax-table) - S-syntax-table) - "Syntax table for S code." - ) - -(defvar S-editing-alist - '((paragraph-start . (concat "\\s-*$\\|" page-delimiter)) - (paragraph-separate . (concat "\\s-*$\\|" page-delimiter)) - (paragraph-ignore-fill-prefix . t) - ;;(comment-indent-function . 'S-comment-indent) - ;;(ess-comment-indent . 'S-comment-indent) - ;;(ess-calculate-indent . 'ess-calculate-indent) - ;;(ess-keep-dump-files . 'ask) - ;; For Changelog add, require ' ' before <- : "attr<-" is a function name : - (add-log-current-defun-header-regexp . "^\\(.+\\)\\s-+<-[ \t\n]*function")) - "General options for S and S+ source files.") - -(defvar inferior-S-language-start - '(concat "options(" - "STERM='" ess-STERM "'" - ", str.dendrogram.last=\"'\"" - (if ess-editor (concat ", editor='" ess-editor "'")) - (if ess-pager (concat ", pager='" ess-pager "', help.pager='" ess-pager "'")) - ", show.error.locations=TRUE" - ")") - "S language expression for startup -- default for all S dialects.") - -(defconst S-common-cust-alist - '((ess-language . "S") - (inferior-ess-exit-command . "q()\n") - (inferior-ess-language-start . (eval inferior-S-language-start)) - (comint-use-prompt-regexp . t) ;;use fields if nil - (comint-process-echoes . t) - ;; these prompt are the same for all S-languages As long as custom prompt - ;; ends in inferior-ess-primary-prompt everything should work as expected. - (inferior-ess-primary-prompt . "> ") - ;; (inferior-ess-secondary-prompt . "[+:] ") ;; catch Selection: and alike - (inferior-ess-secondary-prompt . "+ ") ;; catch Selection: and alike - (comment-start . "#") - (comment-add . 1) - (comment-start-skip . "#+ *") - (comment-use-syntax . t) ; see log for bug report 2013-06-07 - (comment-column . 40) - (ess-no-skip-regexp . (concat "^ *@\\|" (default-value 'ess-no-skip-regexp))) - ;; inferior-ess-prompt is used by comint for navigation, only if - ;; comint-use-prompt-regexp is t; (transcript-mode also relies on this regexp) - (inferior-ess-prompt . inferior-S-prompt) - (ess-getwd-command . "getwd()\n") - (ess-setwd-command . "setwd('%s')\n") - (ess-funargs-command . ".ess_funargs(\"%s\")\n") - (fill-nobreak-predicate . 'ess-inside-string-p) - (ess-execute-screen-options-command . "options(width=%d, length=99999)\n") - (font-lock-defaults . '(ess-build-font-lock-keywords - nil nil ((?\. . "w") (?\_ . "w"))))) - "S-language common settings for all -customize-alist.") - -(defconst S+common-cust-alist - (append - '((ess-suffix . "S") - (ess-help-sec-regex . ess-help-S+-sec-regex) - (ess-help-sec-keys-alist . ess-help-S+sec-keys-alist) - (ess-change-sp-regexp . ess-S+-change-sp-regexp) - (ess-function-pattern . ess-s-function-pattern) - (ess-function-template . " <- \n#\nfunction()\n{\n\n}\n") - (ess-dump-filename-template . (replace-regexp-in-string - "S$" ess-suffix ; in the one from custom: - ess-dump-filename-template-proto)) - (ess-traceback-command . "traceback()\n") - (ess-mode-editing-alist . S-editing-alist) - - (ess-dumped-missing-re - . "\\(\\(<-\\|=\\)\nDumped\n\\'\\)\\|\\(\\(<-\\|=\\)\\(\\s \\|\n\\)*\\'\\)") - (ess-syntax-error-re - . "\\(Syntax error: .*\\) at line \\([0-9]*\\), file \\(.*\\)$") - (inferior-ess-objects-command . inferior-Splus-objects-command) - (ess-describe-object-at-point-commands . 'ess-S-describe-object-at-point-commands) - (ess-editor . S-editor) - (ess-pager . S-pager)) - S-common-cust-alist) - "Common settings for all S+<*>-customize-alist." - ) - -;;; Changes from S to S-PLUS 3.x. (standard S3 should be in ess-s-lang!). - -(defconst ess-help-S+sec-keys-alist - '((?a . "ARGUMENTS:") - (?b . "BACKGROUND:") - (?B . "BUGS:") - (?d . "DESCRIPTION:") - (?D . "DETAILS:") - (?e . "EXAMPLES:") - (?n . "NOTE:") - (?O . "OPTIONAL ARGUMENTS:") - (?R . "REQUIRED ARGUMENTS:") - (?r . "REFERENCES:") - (?s . "SEE ALSO:") - (?S . "SIDE EFFECTS:") - (?u . "USAGE:") - (?v . "VALUE:")) - "Alist of (key . string) pairs for use in section searching.") -;;; `key' indicates the keystroke to use to search for the section heading -;;; `string' in an S help file. `string' is used as part of a -;;; regexp-search, and so specials should be quoted. - -;; S ver.3 (NOT S-Plus) -(defconst ess-help-S3-sec-keys-alist - '((?a . "ARGUMENTS:") - (?b . "BACKGROUND:") - (?B . "BUGS:") - (?d . "DESCRIPTION:") - (?D . "DETAILS:") - (?e . "EXAMPLES:") - (?n . "NOTE:") - (?r . "REFERENCES:") - (?s . "SEE ALSO:") - (?S . "SIDE EFFECTS:") - (?u . "USAGE:") - (?v . "VALUE:")) - "Help section keys for S ver.3.") - -;; S ver.4 (NOT S-Plus) -(defconst ess-help-S4-sec-keys-alist - '((?a . "ARGUMENTS:") - (?b . "BACKGROUND:") - (?B . "BUGS:") - (?d . "DESCRIPTION:") - (?D . "DETAILS:") - (?e . "EXAMPLES:") - (?n . "NOTE:") - (?r . "REFERENCES:") - (?s . "SEE ALSO:") - (?S . "SIDE EFFECTS:") - (?u . "USAGE:") - (?v . "VALUE:")) - "Help section keys for S4.") - - -(defconst ess-help-S+-sec-regex "^[A-Z.]+:$" - "Reg(ular) Ex(pression) of section headers in help file.") - - ; Function Definitions - -(defun S-comment-indent () - "Indentation for S comments." - (if (or (looking-at "###") - (and (looking-at "#!") (= 1 (line-number-at-pos)))) - (current-column) - (if (looking-at "##") - (let ((tem (when ;; FIXME ess-calculate-indent is R specific - (fboundp 'ess-calculate-indent) - (ess-calculate-indent)))) - (if (listp tem) (car tem) tem)) - (skip-chars-backward " \t") - (max (if (bolp) 0 (1+ (current-column))) - comment-column)))) - -;;*;; S/R Pretty-Editing - -(defun ess-fix-comments (&optional dont-query verbose) - "Fix buffer so that single-line comments start with at least '##', -and ensure space before subsequent text." - (interactive "P") - (ess-replace-regexp-dump-to-src "#\\([A-Za-z0-9]\\)" "# \\1" nil verbose) - (ess-replace-regexp-dump-to-src "^\\([ \t]*#\\)\\([^#]\\)" - "\\1#\\2" dont-query verbose)) - -(defun ess-dump-to-src (&optional dont-query verbose) - "Make the change in an S - dump() file to improve human readability. -Optional arguments DONT-QUERY and VERBOSE are passed to -`ess-replace-regexp-dump-to-src'." - (interactive "P") - (ess-replace-regexp-dump-to-src "^\"\\([a-z.][a-z.0-9]*\\)\" *<-\n" - "\n\\1 <- " - dont-query verbose)) - -(defun ess-num-var-round (&optional dont-query verbose) - "Round endings like 000000 and 99999. -Optional argument DONT-QUERY means do not query. -Optional argument VERBOSE gives more verbose output." - (interactive "P") - (save-excursion - (goto-char (point-min)) - (let ((num 0) - (str "") - (rgxp "000000+[1-9]?[1-9]?\\>") - (to "")) - (if dont-query - (ess-rep-regexp rgxp to nil nil verbose) - (query-replace-regexp rgxp to nil)) - (while (< num 9) - (setq str (concat (int-to-string num) "999999+[0-8]*")) - (if (and (numberp verbose) (> verbose 1)) - (message (format "\nregexp: '%s'" str))) - (goto-char (point-min)) - (ess-rep-regexp str (int-to-string (1+ num)) - 'fixedcase 'literal verbose) - (setq num (1+ num)))))) - -(defun ess-fix-dot (before-chars &optional dont-query verbose) - "Remove trailing decimal '.' (\"dot\"), before BEFORE-CHARS. -Optional argument DONT-QUERY and VERBOSE get passed to `ess-replace-regexp-dump-to-src'." - ;; typically, before-chars = "]:" or more - (ess-replace-regexp-dump-to-src - (concat "\\([0-9]\\)\\.\\( *[" before-chars "]\\)") - ;; 111 ^ - "\\1\\2" dont-query verbose)) - -(defun ess-fix-dot-1 (&optional do-query verbose) - "Remove trailing decimal '.' (\"dot\"), before ':' or ']', i.e., -in cases where it's ugly and nonsense. DO-QUERY(prefix) asks before replacing." - (interactive "P") - (ess-fix-dot "]:" (not do-query) verbose)) - -(defun ess-fix-dot-more (&optional dont-query verbose) - "Remove trailing decimal '.' (\"dot\", typically from S+) in more cases -than `ess-fix-dot-1'." - (interactive "P") - (ess-fix-dot-1 nil verbose) - (ess-fix-dot ",)" dont-query verbose)) - -(defun ess-fix-EQ-assign (&optional dont-query verbose not-all) - "Replace \"=\" by \"<-\" in places where it 'might make sense', e.g., -for function assignments and lines not ending in \",\". -Be *careful* for list()s of functions and when argument not-all is -nil (as by default) !" - ;;TODO: "in the few places we can be very sure.." - ;;---- is hard in general: local functions: ok; but functions in - ;; list(a = function(x) abs(x), b= function(y) bound(y)) *NOT* ok! - (interactive "P") - (ess-replace-regexp-dump-to-src - "^\\( *[a-z.][_a-z.0-9]*\\) *= *\\(function *(\\)" - "\\1 <- \\2" dont-query verbose) - (unless not-all - ;; "too" aggressive {proposing to replace function argument specs}: - (ess-replace-regexp-dump-to-src ;; all those *not* ending in "," - ;; including Mat[ i, ] = ..., - ;; but not `names(x) = "..."' for that is "confused" with plot(x=x,..) - "^\\( *[a-z.][][, \"_a-z.0-9]*\\) *= *\\([a-z.0-9({]\\(.*[^,]\\)? *$\\)" - "\\1 <- \\2" nil ;; always query - often has many "false positives" - verbose))) - -;;; All of the above three : -(defun ess-MM-fix-src (&optional dont-query verbose) - "Clean up ess-source code which has been produced by dump(..), and other -code typically produced by other tools. Produces more readable code, -and one that is well formatted in Emacs ess-mode." - (interactive "P") - ;; each of the following does a save-excursion: - (ess-dump-to-src dont-query) - (ess-fix-comments dont-query) - (ess-num-var-round dont-query verbose) - (ess-fix-dot-more dont-query verbose) - (ess-fix-EQ-assign dont-query verbose 'not-all)) - -(defun ess-fix-miscellaneous (&optional from verbose) - "Fix Miscellaneous S/R `ill-formation's from current \\[point]. -Particularly use \"<-\"and put spaces around operators." - (interactive "d\nP"); Defaults: point and prefix (C-u) - ;; activate by (setq ess-verbose t) - (ess-if-verbose-write - (format "ess-fix-misc begin (from = %s, verbose = %s)\n" from verbose)) - (save-excursion - - (when (and (string= ess-dialect "R") - (fboundp 'ess-r-fix-T-F)) - (ess-r-fix-T-F from (not verbose))) - - ;; activate by (setq ess-verbose t) - (ess-if-verbose-write "ess-fix-misc: after fix-T-F\n");___D___ - - ;; former C and matlab programmers leave trailing ";" : - ;; (goto-char from) (ess-rep-regexp "; *$" "" nil 'literal verbose) - ;; (ess-if-verbose-write "ess-fix-misc: after trailing ';'\n");___D___ - (goto-char from) (ess-rep-regexp ";\\( *\\)#" "\\1#" nil nil verbose) - (ess-if-verbose-write "ess-fix-misc: after ';' before #\n");___D___ - - ;;from R 1.9.x "_" is valid in names; here assume no initial / trailing '_' - ;; BUG: The following changes "beta_ " or " _abc" - ;; (goto-char from) (ess-rep-regexp " +_ *" " <- " nil 'literal verbose) - ;; (goto-char from) (ess-rep-regexp "_ +" " <- " nil 'literal verbose) - - (ess-if-verbose-write "ess-fix-misc: before 'around \"<-\"' :\n");___D___ - ;; ensure space around "<-" ---- but only replace if necessary: - (goto-char from) - (ess-rep-regexp "\\([^< \t\n]\\)\\(<" (not ">=") : - (goto-char from);; --> " <", care with "->": - (ess-rep-regexp "\\([^-< \t\n]\\)\\([<>]\\)" "\\1 \\2" nil nil verbose) - ;; ">" -> "> " , for "<", don't split "<-" nor "<<-": - (goto-char from) - (ess-rep-regexp "\\(>=?\\)\\([^= \t\n]\\)" "\\1 \\2" nil nil verbose) - (goto-char from) - (ess-rep-regexp "\\(<=?\\)\\([^-<= \t\n]\\)" "\\1 \\2" nil nil t) - - (ess-if-verbose-write "ess-fix-misc: before \"=\" \"==\" .. :\n");___D___ - ;; -- ensure space around "=", "==", "!=" : - (goto-char from) ;; --> " =" - (ess-rep-regexp "\\([^=!<> ]\\)\\([=!]?\\)=" "\\1 \\2=" nil nil verbose) - (goto-char from) (ess-rep-regexp "=\\([^= ]\\)" "= \\1" nil nil verbose) - - (goto-char from) ;; add a space between "{" and surrounding ..char: - (ess-rep-regexp "{\\([.A-Za-z()]\\)" "{ \\1" 'fix nil verbose) - (ess-rep-regexp "\\([()]\\){" "\\1 {" 'fix nil verbose) - (goto-char from) ;; add a space between "}" and a preceding wordchar: - (ess-rep-regexp "\\([A-Za-z0-9()]\\)}" "\\1 }" 'fix nil verbose) - (ess-space-around "else" from verbose) - - (ess-if-verbose-write "ess-fix-misc: after \"{ ... }\" :\n");___D___ - (goto-char from) ;; add a space inside "){" - (ess-rep-regexp "){" ") {" 'fix nil verbose) - - ;; add a newline and indent before a "}" - ;; --- IFF there's NO "{" or "#" AND some NON-white text on the same line: - ;;D (if verbose (message "\t R-fix-misc..: Hard.. '}'")) - (goto-char from) - (ess-rep-regexp "^\\([^#{\n]*[^#{ \t\n]+[ \t]*\\)}[ \t]*$" - "\\1\n}" 'fix nil verbose) - (ess-if-verbose-write "ess-fix-misc __end__\n");___D___ - )) - -(defun ess-cycle-assign () - "Cycle between assignment symbols in `ess-assign-list'. -On consecutive calls, replace the assignment symbol before point -with the next symbol from that list. This function sets the last -keypress to repeat it, so if it is bound to \"C-c C-=\" pressing -\"=\" again cycles to the next assignment." - (interactive) - (if (eq last-command this-command) - (let ((slist ess-assign-list) - str) - ;; The or statements in the setq allow cycling past the end of - ;; ess-assign-list. - (while (and (setq str (or (car slist) (car ess-assign-list)) - slist (or (cdr slist) ess-assign-list)) - (not (and (re-search-backward str - (- (point) (length str)) t) - (not (replace-match (car slist)))))))) - (insert (car ess-assign-list))) - (set-transient-map - (let ((map (make-sparse-keymap)) - (key (format "%c" (event-basic-type last-input-event)))) - (define-key map (kbd key) #'ess-cycle-assign) - map))) - -(defun ess-insert-assign (arg) - "Insert the first element of `ess-assign-list' unless in string or comment. -If the character before point is the first element of -`ess-assign-list', replace it with the last character typed. - -If `ess-language' is not \"S\", call `self-insert-command' with ARG." - (interactive "p") - (if (string= ess-language "S") - (let* ((assign (car ess-assign-list)) - (event (event-basic-type last-input-event)) - (char (ignore-errors (format "%c" event)))) - (cond ((and char (ess-inside-string-or-comment-p)) - (insert char)) - ((re-search-backward assign (- (point) (length assign)) t) - (if (and char (numberp event)) - (replace-match char t t) - (replace-match ""))) - (t (insert assign)))) - (funcall #'self-insert-command arg))) - -;; In case people had this in their config don't cause errors: -(define-obsolete-function-alias 'ess-smart-S-assign 'ess-insert-assign "ESS 18.10") -(define-obsolete-function-alias 'ess-disable-smart-S-assign #'ignore "ESS 18.10") - -(defun ess-add-MM-keys () - "Define MM's user keys." - (declare (obsolete "Setup your own keybindings." "ESS 19.04")) - (define-key inferior-ess-mode-map "\C-cw" #'ess-execute-screen-options) - (define-key ess-mode-map [?\M--] #'ess-insert-assign) - (define-key inferior-ess-mode-map [?\M--] #'ess-insert-assign)) - -(defun ess-dump-args-and-go (Sfunc) - "Dump the function name, with arguments, to a buffer for editing. - -Currently, this needs to: - 1. set the buffer to the right mode, with the right settings - 2. format the statement, - 3. c/function/Sfunc/ -and I need to relearn Emacs lisp (but I had to, anyway." - (interactive "sFunction ? ") - (declare (obsolete 'ess-execute "ESS 19.04")) - (let* ((buffname "ess-complete.R")) - (ess-execute (format "args(%s)" Sfunc) t buffname) - (pop-to-buffer (concat "*" buffname "*")) - (while (search-forward "function" nil t) - (replace-match Sfunc nil t)) - (when (fboundp 'ess-r-mode) - (ess-r-mode)))) - -;;; S imenu support - -;; don't use syntax classes, bad for etags -(defvar ess-imenu-S-generic-expression - '(("Functions" "^\\([^ \t\n]+\\)[ \t\n]*\\(?:<-\\|=\\)[ \t\n]*function[ ]*(" 1) - ("Classes" "^.*setClass(\\(.*\\)," 1) - ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to - ("Generics" "^.*setGeneric(\\([^,]*\\)," 1) - ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\\([^,]+,[^,]*\\)" 2) - ("Package" "^.*\\(library\\|require\\)(\\([^)]*\\)" 2) - ("Data" "^\\(.+\\)[ \t\n]-*\\(?:<-\\|=\\)[ \t\n]*\\(read\\|.*data\\.frame\\).*(" 1)) - "Imenu generic expression for S modes. -See `imenu-generic-expression'.") - -(defun ess-imenu-S (&optional _arg) - "S Language Imenu support for ESS. -ARG is ignored." - (declare (obsolete "It is set automatically in major modes" "ESS 19.04")) - (imenu-add-to-menubar "Imenu-S")) - -(define-obsolete-function-alias 'ess-imenu-R 'ess-imenu-S "ESS 19.04") - - - ;;; Speedbar stuff. - -(eval-after-load "speedbar" - '(progn - (speedbar-add-supported-extension ".R") - (speedbar-add-supported-extension ".S") - (speedbar-add-supported-extension ".s") - (speedbar-add-supported-extension ".q"))) - -(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "R")) - "Return a list of current S help topics associated with process PROC. -If 'sp-for-help-changed?' process variable is non-nil or -`ess-help-topics-list' is nil, (re)-populate the latter and -return it. Otherwise, return `ess-help-topics-list'." - (with-ess-process-buffer nil - (cond - ;; (Re)generate the list of topics - ((or (not ess-help-topics-list) - (ess-process-get 'sp-for-help-changed?)) - (ess-process-put 'sp-for-help-changed? nil) - (setq ess-help-topics-list - (delete-dups - (append (ess-get-object-list proc 'exclude-1st) - (ess-get-help-files-list) - (ess-get-help-aliases-list))))) - (t - ess-help-topics-list)))) - -(defalias 'S 'S+) -(defalias 's-mode 'S+-mode) -(defalias 's-transcript-mode 'S+-transcript-mode) -(defalias 'S-transcript-mode 's-transcript-mode) -(defalias 'S-mode 's-mode) - - -(define-obsolete-function-alias 'ess-toggle-S-assign-key #'ignore "ESS 18.10") -(define-obsolete-function-alias 'ess-smart-underscore 'ess-insert-assign "ESS 18.10") -(define-obsolete-function-alias 'ess-insert-S-assign 'ess-insert-assign "ESS 18.10") - -(define-obsolete-function-alias 'ess-toggle-underscore 'ess-disable-smart-S-assign "ESS 18.10") -(define-obsolete-function-alias 'ess-toggle-S-assign 'ess-disable-smart-S-assign "ESS 18.10") - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Ss]t\\'" . S-transcript-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.Sout" . S-transcript-mode)) - -(provide 'ess-s-lang) - -;;; ess-s-lang.el ends here diff --git a/elpa/ess-20191014.1343/ess-sas-a.el b/elpa/ess-20191014.1343/ess-sas-a.el deleted file mode 100644 index 7cb6f6cb..00000000 --- a/elpa/ess-20191014.1343/ess-sas-a.el +++ /dev/null @@ -1,1460 +0,0 @@ -;;; ess-sas-a.el --- clean-room implementation of many SAS-mode features - -;; Copyright (C) 1997--2009 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Rodney A. Sparapani -;; Maintainer: ESS-core@r-project.org -;; Created: 17 November 1999 -;; Keywords: languages - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Code: - -(require 'ess-mode) -;; Silence the byte compiler -;; FIXME: This is a lot, perhaps they can be moved? -(defvar sas-indent-width) -(defvar SAS-customize-alist) -(defvar sas-mode-local-map) -(declare-function ess-num-or-zero "ess-sas-d") -;; FIXME: What is this doing here??? -(declare-function ess-add-ess-process "essd-els") -(declare-function ess-listing-minor-mode "ess-sas-l") -;;; Table of Contents -;;; Section 1: Variable Definitions -;;; Section 2: Function Definitions -;;; Section 3: Key Definitions - -;;; Section 1: Variable Definitions - -(defvar ess-sas-file-path "." - "Full path-name of the sas file to perform operations on.") - -(defcustom ess-sas-data-view-libname " " - "SAS code to define a library for `ess-sas-data-view-fsview' -or `ess-sas-data-view-insight'." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-data-view-submit-options - (if ess-microsoft-p "-noenhancededitor -nosysin -log NUL:" - "-nodms -nosysin -log /dev/null -terminal") - "The command-line options necessary for your OS with respect to -`ess-sas-data-view-fsview' and `ess-sas-data-view-insight'." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-data-view-fsview-command "; proc fsview data=" - "SAS code to open a SAS dataset with `ess-sas-data-view-fsview'." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-data-view-fsview-statement " " - "SAS code to perform a PROC FSVIEW statement with `ess-sas-data-view-fsview'." - :group 'ess-sas - :type 'string) - - -(make-variable-buffer-local 'ess-sas-data-view-fsview-statement) - -(defcustom ess-sas-data-view-insight-command "; proc insight data=" - "SAS code to open a SAS dataset with `ess-sas-data-view-insight'." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-data-view-insight-statement " " - "SAS code to perform a PROC FSVIEW statement with `ess-sas-data-view-insight'." - :group 'ess-sas - :type 'string) - -(make-variable-buffer-local 'ess-sas-data-view-insight-statement) - -(defcustom ess-sas-graph-view-suffix-regexp - "[.]\\([eE]?[pP][sS]\\|[pP][dD][fF]\\|[gG][iI][fF]\\|[jJ][pP][eE]?[gG]\\|[tT][iI][fF][fF]?\\)" - "GSASFILE suffix regexp." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-graph-view-viewer-alist - ;;creates something like - ;;'(("[pP][dD][fF]" . "/usr/local/bin/acroread") ("[eE]?[pP][sS]" . "/usr/local/bin/gv"))) - (let ((ess-tmp-alist nil) - (ess-tmp-ps nil) (ess-tmp-pdf nil)) - - (setq ess-tmp-ps (executable-find (if ess-microsoft-p "gsview32" "gsview"))) - - (if (not ess-tmp-ps) (setq ess-tmp-ps (executable-find "gv"))) - - (if (not ess-tmp-ps) (setq ess-tmp-ps (executable-find "ghostview"))) - - (setq ess-tmp-pdf (executable-find "evince")) - - (if (not ess-tmp-pdf) (setq ess-tmp-pdf (executable-find "xpdf"))) - - (if (not ess-tmp-pdf) (setq ess-tmp-pdf (if ess-microsoft-p "acrord32" "acroread"))) - - (if (and ess-tmp-ps ess-tmp-pdf) - (setq ess-tmp-alist (list (cons "[eE]?[pP][sS]" ess-tmp-ps) - (cons "[pP][dD][fF]" ess-tmp-pdf))) - - (if ess-tmp-ps - (setq ess-tmp-alist (list (cons "[eE]?[pP][sS]" ess-tmp-ps) - (cons "[pP][dD][fF]" ess-tmp-ps)))))) - - "Associate file name extensions with graphics image file viewers." - :group 'ess-sas - :type '(choice (const nil) (alist))) - -(defcustom ess-sas-log-max 0 - "If >0 and .log file exceeds this many bytes, just \"refresh\" this many bytes." - :group 'ess-sas - :type 'integer) - -(defcustom ess-sas-rtf-font-name "Courier" ; "Bitstream Vera Sans Mono" - "Name of font with which to create MS RTF." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-shell-buffer "*shell*" - "Name that you want to use for the shell buffer; buffer-local." - :group 'ess-sas - :type 'string) - -(make-variable-buffer-local 'ess-sas-shell-buffer) - -(defcustom ess-sas-shell-buffer-remote-host nil - "Remote host that you want to open a shell on." - :group 'ess-sas - :type '(choice (const nil) string)) - -(make-variable-buffer-local 'ess-sas-shell-buffer-remote-host) - -(defcustom ess-sas-shell-buffer-remote-init "ssh" - "Command to open a shell on a remote host." - :group 'ess-sas - :type 'string) - -(make-variable-buffer-local 'ess-sas-shell-buffer-remote-init) - -(defcustom ess-sas-submit-mac-virtual-pc nil - "Non-nil means that you want to run Windows SAS in a -Virtual PC emulator on your Mac; buffer-local." - :group 'ess-sas - :type 'boolean) - -(make-variable-buffer-local 'ess-sas-submit-mac-virtual-pc) - -(defcustom sas-program "sas" - "Command to invoke SAS, default for buffer-local `ess-sas-submit-command'." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-submit-command sas-program - "Command to invoke SAS in batch; buffer-local." - :group 'ess-sas - :type 'string) - -(make-variable-buffer-local 'ess-sas-submit-command) - -(defcustom ess-sas-submit-command-options "-rsasuser" - "Options to pass to SAS in batch; buffer-local." - :group 'ess-sas - :type 'string) - -(make-variable-buffer-local 'ess-sas-submit-command-options) - -(defvar-local ess-sas-submit-method - (if (and (and ess-microsoft-p - (fboundp 'w32-shell-dos-semantics)) - (w32-shell-dos-semantics)) - 'ms-dos 'sh) - "Method used by `ess-sas-submit'. -The default is based on the value of the emacs variable `system-type' -and, on Windows, the function `w32-shell-dos-semantics'. -'sh if *shell* runs sh, ksh, csh, tcsh or bash -'ms-dos if *shell* follows MS-DOS semantics - -Unix users will get 'sh by default. - -Windows users running bash in *shell* will get 'sh by default. - -Windows users running MS-DOS in *shell* will get 'ms-dos by default. - -Users accessing a remote machine with `telnet', `rlogin', `ssh', etc., -should set this variable to 'sh regardless of their local shell -(since their remote shell is 'sh).") - -(defcustom ess-sas-graph-view-viewer-default - (if ess-microsoft-p "explorer" - (if (equal ess-sas-submit-method 'sh) "sdtimage")) - "Default graphics image file viewer." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-submit-post-command - (if (equal ess-sas-submit-method 'sh) "&" - (if ess-microsoft-p "-icon")) - "Command-line statement to post-modify SAS invocation." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-submit-pre-command ;;"nohup" - (if (equal ess-sas-submit-method 'sh) - ;; nice is tricky, higher numbers give you lower priorities - ;; if you are using csh/tcsh, the default priority is 4 - ;; if you are using most other shells, the default priority is 10, - ;; and some implementations are higher, i.e. zsh unless you - ;; specify "setopt no_bg_nice" in your ~/.zshrc - ;; therefore, on the same machine, you can run at a higher or - ;; lower priority by changing shells, although, the command - ;; line is the same! - ;; the following code should give you a priority of 10 regardless - ;; of which shell is in use, but it will default to the old - ;; behavior if csh or variant is not recognized - ;; this should avoid the necessity of each user needing to set this - ;; variable correctly based on the shell that they use and provide - ;; an environment where all shells are treated equally - - (let* ((temp-shell (getenv "SHELL")) - ;; AJR: old CYGWIN versions return nil for (getenv - ;; "SHELL"), so we need to deal with it 'cause I have to - (temp-char (if temp-shell - (string-match "/" temp-shell) - nil))) - (while temp-char - (setq temp-shell (substring temp-shell (+ 1 temp-char))) - (setq temp-char (string-match "/" temp-shell))) - - (cond ((or (equal temp-shell "csh") (equal temp-shell "tcsh")) - "nohup nice +6") - (t "nohup nice"))) - (if ess-microsoft-p "start")) - "Command-line statement to precede SAS invocation, e.g. start or nohup." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-suffix-1 "txt" - "The first suffix to associate with SAS." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-suffix-2 "csv" - "The second suffix to associate with SAS." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-suffix-regexp - (concat "[.]\\([sS][aA][sS]\\|[lL][oO][gG]\\|[lL][sS][tT]" - (if ess-sas-suffix-1 (concat - "\\|" (downcase ess-sas-suffix-1) "\\|" (upcase ess-sas-suffix-1))) - (if ess-sas-suffix-2 (concat - "\\|" (downcase ess-sas-suffix-2) "\\|" (upcase ess-sas-suffix-2))) - "\\)") - "Regular expression for SAS suffixes." - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-tab-stop-list - '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120) - "List of tab stop positions used by `tab-to-tab-stop' in ESS[SAS]." - :type '(repeat integer) - :group 'ess-sas) - -(defcustom ess-sas-temp-root "-temp" - "Appended to root name of the temporary .sas file for `ess-sas-submit-region'." - :group 'ess-sas - :type 'string) - -(defvar ess-sas-versions '("sas") - "List of partial strings for versions of SAS to access within ESS. -Each string specifies the start of a filename. If a filename -beginning with one of these strings is found on `exec-path', a M-x -command for that version of SAS is made available. For example, if the -file \"sas8\" is found and this variable includes the string -\"sas\", a function called `M-x SAS8' will be available to run that -version of SAS. -If duplicate versions of the same program are found (which happens if -the same path is listed on `exec-path' more than once), they are -ignored by calling `delete-dups'. -If you set this variable, you need to restart Emacs (and set this variable -before ess-site is loaded) for it to take effect.") - -(defvar ess-sas-global-unix-keys nil - "Non-nil if function keys use Unix-like SAS key definitions in all modes.") - -(defvar ess-sas-local-pc-keys nil - "Non-nil if function keys use PC-like SAS key definitions -in SAS-mode and related modes.") - -(defvar ess-sas-local-unix-keys nil - "Non-nil if function keys use Unix-like SAS key definitions -in SAS-mode and related modes.") - -;;; Section 2: Function Definitions - - -(defun ess-ebcdic-to-ascii-search-and-replace () - "Search and replace EBCDIC text with ASCII equivalents." - (interactive) - (let ((ess-tmp-dd (executable-find "dd")) (ess-tmp-recode (executable-find "recode")) - (ess-tmp-util nil) (ess-tmp-util-args nil)) - - (if ess-tmp-dd (progn - (setq ess-tmp-util ess-tmp-dd) - (setq ess-tmp-util-args "conv=ascii")) - - (setq ess-tmp-util ess-tmp-recode) - (setq ess-tmp-util-args "EBCDIC..ISO-8859-1")) - - (if ess-tmp-util - (while (search-forward-regexp "[^\f\t\n -~][^\f\t\n -?A-JQ-Yb-jp-y]*[^\f\t\n -~]?" nil t) - (call-process-region (match-beginning 0) (match-end 0) - ess-tmp-util t (list t nil) t ess-tmp-util-args))))) - - -(defun ess-exit-notify-sh (string) - "Detect completion or failure of submitted job and notify the user." - (let* ((exit-done "\\[[0-9]+\\] *\\+* *\\(Exit\\|Done\\)[^\r\n]*") - (beg (string-match exit-done string))) - (if beg - (message "%s" (substring string beg (match-end 0)))))) - - -(defun ess-sas-append-log () - "Append ess-temp.log to the current .log file." - (interactive) - (ess-sas-goto "log" 'revert) - (goto-char (point-max)) - (insert-file-contents (concat (ess-sas-temp-root) ".log")) - (save-buffer)) - -(defun ess-sas-append-lst () - "Append ess-temp.lst to the current .lst file." - (interactive) - (ess-sas-goto "lst" 'revert) - (goto-char (point-max)) - (insert-file-contents (concat (ess-sas-temp-root) ".lst")) - (save-buffer)) - -(defun ess-sas-backward-delete-tab () - "Moves the cursor to the previous tab-stop, deleting any characters -on the way." - (interactive) - - (let* (;; point of search - ;;(ess-sas-search-point nil) - ;; column of search - ;;(ess-sas-search-column nil) - ;; limit of search - ;;(ess-sas-search-limit nil) - ;; text to be inserted after a back-tab, if any - ;;(ess-sas-end-text "end;") - ;; current-column - (ess-sas-column (current-column)) - ;; remainder of current-column and sas-indent-width - (ess-sas-remainder (% ess-sas-column sas-indent-width))) - - (if (not (= ess-sas-column 0)) - (progn - (if (= ess-sas-remainder 0) - (setq ess-sas-remainder sas-indent-width)) - - (let ((backward-delete-char-untabify-method 'nil)) - (backward-delete-char-untabify ess-sas-remainder t) - (setq ess-sas-column (- ess-sas-column ess-sas-remainder)) - (move-to-column ess-sas-column) - (setq left-margin ess-sas-column)) - )) - )) - -;; this feature was far too complicated to perfect -;; (if ess-sas-smart-back-tab (progn -;; (save-excursion -;; (setq ess-sas-search-point -;; (search-backward-regexp "end" nil t)) - -;; (if (and ess-sas-search-point -;; (search-backward-regexp "%" (+ ess-sas-search-point -1) t)) -;; (setq ess-sas-search-point (+ ess-sas-search-point -1)) -;; ) - -;; (if (and ess-sas-search-point -;; (not (equal ess-sas-column (current-column)))) -;; (setq ess-sas-search-point nil)) -;; ) - -;; (save-excursion -;; (setq ess-sas-search-point -;; (search-backward-regexp "do\\|select" -;; ess-sas-search-point t)) - -;; (setq ess-sas-search-column (current-column)) - -;; (if ess-sas-search-point (progn -;; (save-excursion -;; (search-backward-regexp "^" nil t) -;; (setq ess-sas-search-limit (point)) -;; ) - -;; (if (search-backward-regexp "if.*then\\|else" ess-sas-search-limit t) -;; (setq ess-sas-search-point (point))) - -;; (if (search-backward-regexp "%" ess-sas-search-limit t) (progn -;; (setq ess-sas-end-text "%end;") -;; (setq ess-sas-search-point (point)) -;; )) - -;; (setq ess-sas-search-column (current-column)) - -;; (if (not (equal ess-sas-column ess-sas-search-column)) -;; (setq ess-sas-search-point nil)) -;; ))) - -;; (if ess-sas-search-point (insert ess-sas-end-text)) -;; )) - -(defun ess-sas-cd () - "Change directory, taking into account various issues with respect to -`ess-sas-file-path'." - ;(interactive) - (ess-sas-file-path) - (ess-sas-goto-shell t) - (comint-send-input) - (if (equal ess-sas-submit-method 'sh) - (insert "cd \"" (car (last (split-string (file-name-directory ess-sas-file-path) - "\\([a-zA-Z][a-zA-Z]:\\|]\\)"))) "\"") - (if (equal ess-sas-submit-method 'ms-dos) (progn - (if (string-equal ":" (substring ess-sas-file-path 1 2)) (progn - (insert (substring ess-sas-file-path 0 2)) - (comint-send-input))) - (insert "cd \"" (convert-standard-filename - (file-name-directory ess-sas-file-path)) "\"")))) - (comint-send-input)) - -(defun ess-sas--change-alist (item value alist) - "Modify ALIST to set VALUE to ITEM. -If there is a pair whose car is ITEM, replace its cdr by VALUE. -If there is not such pair, create new pair (ITEM . VALUE) and -return new alist whose car is the new pair and cdr is ALIST. -\[tomo's ELIS like function]" - (let ((pair (assoc item alist))) - (if pair - (progn - (setcdr pair value) - alist) - (cons (cons item value) alist)))) - -(defun ess-sas-create-local-variables-alist (&optional file-or-buffer) - "Create an alist of local variables from file-or-buffer. -Use the current buffer if nil." - (declare (obsolete nil "ESS 19.04")) - (if file-or-buffer (set-buffer (if (bufferp file-or-buffer) - file-or-buffer - (find-buffer-visiting file-or-buffer)))) - (ess-sas--change-alist 'ess-kermit-remote-directory ess-kermit-remote-directory nil)) - -(define-obsolete-function-alias - 'ess-change-alist 'ess-sas--change-alist "ESS 18.10") - -(defun ess-sas-data-view-fsview (&optional ess-sas-data) - "Open a dataset for viewing with PROC FSVIEW." - (interactive) - (ess-save-and-set-local-variables) - - (save-excursion (let ((ess-tmp-sas-data nil) - (ess-tmp-sas-data-view-fsview-statement ess-sas-data-view-fsview-statement) - (ess-search-regexp - "[ \t=]\\([a-zA-Z_][a-zA-Z_0-9]*[.][a-zA-Z_][a-zA-Z_0-9]*\\)\\(&.*\\)?[. ,()\t;/]") - (ess-search-except - "^\\([wW][oO][rR][kK]\\|[fF][iI][rR][sS][tT]\\|[lL][aA][sS][tT]\\)[.]")) - - (if ess-sas-data nil (save-match-data - (search-backward-regexp "[ \t=]" nil t) - - (save-excursion - (setq ess-tmp-sas-data - (ess-search-except ess-search-regexp ess-search-except))) - - (if (not ess-tmp-sas-data) - (setq ess-tmp-sas-data - (ess-search-except ess-search-regexp ess-search-except t))) - - (setq ess-sas-data (read-string "Permanent SAS Dataset: " ess-tmp-sas-data)) - - ;; (ess-sas-goto-shell t) - (ess-sas-cd) - - (insert (concat ess-sas-submit-pre-command " " ess-sas-submit-command - " -initstmt \"" ess-sas-data-view-libname ess-sas-data-view-fsview-command - ess-sas-data ";" ess-tmp-sas-data-view-fsview-statement "; run;\" " - ess-sas-submit-command-options " " - ess-sas-data-view-submit-options " " ess-sas-submit-post-command)) - (comint-send-input) - ))))) - -(defun ess-sas-data-view-insight (&optional ess-sas-data) - "Open a dataset for viewing with PROC INSIGHT." - (interactive) - (ess-save-and-set-local-variables) - - (save-excursion (let ((ess-tmp-sas-data nil) - (ess-tmp-sas-data-view-insight-statement ess-sas-data-view-insight-statement) - (ess-search-regexp - "[ \t=]\\([a-zA-Z_][a-zA-Z_0-9]*[.][a-zA-Z_][a-zA-Z_0-9]*\\)\\(&.*\\)?[. ,()\t;]") - (ess-search-except - "^\\([wW][oO][rR][kK]\\|[fF][iI][rR][sS][tT]\\|[lL][aA][sS][tT]\\)[.]")) - - (if ess-sas-data nil (save-match-data - (search-backward-regexp "[ \t=]" nil t) - - (save-excursion - (setq ess-tmp-sas-data - (ess-search-except ess-search-regexp ess-search-except))) - - (if (not ess-tmp-sas-data) - (setq ess-tmp-sas-data - (ess-search-except ess-search-regexp ess-search-except t))) - - (setq ess-sas-data (read-string "Permanent SAS Dataset: " ess-tmp-sas-data)) - - ;; (ess-sas-goto-shell t) - (ess-sas-cd) - - (insert (concat ess-sas-submit-pre-command " " ess-sas-submit-command - " -initstmt \"" ess-sas-data-view-libname ess-sas-data-view-insight-command - ess-sas-data ";" ess-tmp-sas-data-view-insight-statement "; run;\" " - ess-sas-data-view-submit-options " " ess-sas-submit-post-command)) - (comint-send-input) - ))))) - -(defun ess-sas-graph-view () - "Open a GSASFILE for viewing." - (interactive) - ;; (ess-sas-goto-shell t) - (ess-sas-cd) - (ess-sas-goto-log 'no-error-check) - - (save-excursion - (let ( - (ess-tmp-length (length ess-sas-graph-view-viewer-alist)) - (ess-tmp-counter 0) - (ess-tmp-graph nil) - (ess-tmp-graph-alist nil) - (ess-tmp-glyph nil) - (ess-tmp-graph-regexp - (concat "[cCub][oOty][rRpt][dDue][sSt][ ][wW][rR][iI][tT][tT][eE][nN][ ]+[tT][oO][ ]\n?[ ]*\\(.*" - ;; (concat "[ ][rR][eE][cC][oO][rR][dD][sS][ ][wW][rR][iI][tT][tT][eE][nN][ ]+[tT][oO][ ]\n?[ ]*\\(.*" - ess-sas-graph-view-suffix-regexp "\\)"))) - ; (concat "['\"]\\(.*" ess-sas-graph-suffix-regexp "\\)['\"]"))) - - (save-match-data - (search-backward-regexp "[ \t=]" nil t) - - (save-excursion - (setq ess-tmp-graph (ess-search-except ess-tmp-graph-regexp))) - - (if (not ess-tmp-graph) - (setq ess-tmp-graph (ess-search-except ess-tmp-graph-regexp nil t))) - - (setq ess-tmp-graph (read-string "GSASFILE: " - (or ess-tmp-graph ess-sas-file-path))) - - ;;GNU Emacs graphics file image viewing mode loaded? - (if (and (bound-and-true-p auto-image-file-mode) - (string-match "[.][jJ][pP][eE]?[gG]" ess-tmp-graph)) - (find-file ess-tmp-graph) - ;;else XEmacs graphics file image viewing mode loaded? - (if (and (fboundp 'image-mode) - (string-match "[.]\\([jJ][pP][eE]?[gG]\\|[gG][iI][fF]\\)" - ess-tmp-graph)) - (find-file ess-tmp-graph) - ;;else use the appropriate graphics file image viewer - (while (< ess-tmp-counter ess-tmp-length) - (setq ess-tmp-graph-alist - (nth ess-tmp-counter ess-sas-graph-view-viewer-alist)) - (setq ess-tmp-graph-regexp (car ess-tmp-graph-alist)) - - (if (string-match - (concat "[.]" ess-tmp-graph-regexp) ess-tmp-graph) - (progn - (ess-sas-goto-shell t) - (insert ess-sas-submit-pre-command " " - (cdr ess-tmp-graph-alist) " " ess-tmp-graph - (if (equal ess-sas-submit-method 'sh) " &")) - (setq ess-tmp-glyph 'alist) - (setq ess-tmp-counter ess-tmp-length)) - ;;else - (setq ess-tmp-counter (+ ess-tmp-counter 1)))) - - (if (not ess-tmp-glyph) - (progn - (ess-sas-goto-shell t) - (insert ess-sas-submit-pre-command " " - ess-sas-graph-view-viewer-default " " ess-tmp-graph - (if (equal ess-sas-submit-method 'sh) " &")))) - - (comint-send-input))))))) - -(defun ess-sas-file-path (&optional force) - "Define `ess-sas-file-path' to be the current buffer depending on suffix." - (interactive) - - (save-match-data (let ((ess-sas-temp-file (expand-file-name (buffer-name)))) - (if (or force (string-match ess-sas-suffix-regexp ess-sas-temp-file)) ;;(progn - (setq ess-sas-file-path - (nth 0 (split-string ess-sas-temp-file "[<]"))))))) - -(defun ess-sas-file-path-remote-host () - "Return the remote host, if any, associated with `ess-sas-file-path'." - (interactive) - - (let* ((temp-colon-pos (string-match ":" ess-sas-file-path)) - (temp-list - (if (or (not temp-colon-pos) (> temp-colon-pos 2)) - (if (equal ess-sas-file-path ".") nil - (split-string (file-name-directory ess-sas-file-path) - "\\(@\\|:\\|]\\)")) - (list ess-sas-file-path))) - (temp-list-length (length temp-list))) - (if (= temp-list-length 1) (setq temp-list nil) - (if (= temp-list-length 2) (setq temp-list (car temp-list)) - (setq temp-list (nth 1 temp-list)))) - - (if temp-list (setq temp-list - (car (last (split-string temp-list "/"))))) - temp-list)) - -(defun ess-sas-goto (suffix &optional revert no-create) - "Find a file associated with a SAS file by suffix and revert if necessary." -; (interactive) -; (let ((ess-temp-regexp (concat ess-sas-suffix-regexp "[.]?[1-9]?\\'"))) -; can we identify common nonsense extensions like .log.1 or .sas.2? - (let ((ess-temp-regexp (concat ess-sas-suffix-regexp "\\(@.+\\)?\\'"))) - (save-match-data - (if (or (string-match ess-temp-regexp (expand-file-name (buffer-name))) - (string-match ess-temp-regexp ess-sas-file-path)) - (progn - (ess-sas-file-path) - (let* ( - (ess-sas-temp-file (replace-match (concat "." suffix) t t - ess-sas-file-path)) - (ess-sas-temp-buff (find-buffer-visiting ess-sas-temp-file)) - (ess-temp-kermit-remote-directory ess-kermit-remote-directory)) - - (if ess-sas-temp-buff (switch-to-buffer ess-sas-temp-buff) - ;; else - (if no-create (setq revert nil) - (if (file-exists-p ess-sas-temp-file) - (find-file ess-sas-temp-file)))) - ;; else - ;; (let* ((ess-sas-buffer-list (buffer-list)) - ;; (ess-sas-buffer-list-index 0) - ;; (ess-sas-buffer-list-file nil) - ;; (ess-sas-buffer-list-length (length ess-sas-buffer-list))) - ;; (while (< ess-sas-buffer-list-index ess-sas-buffer-list-length) - ;; (setq ess-sas-buffer-list-file - ;; (buffer-file-name (nth ess-sas-buffer-list-index ess-sas-buffer-list))) - ;; (if (and ess-sas-buffer-list-file - ;; (string-match (concat "." suffix) ess-sas-buffer-list-file)) - ;; (switch-to-buffer (nth ess-sas-buffer-list-index ess-sas-buffer-list)) - ;; (setq ess-sas-buffer-list-index ess-sas-buffer-list-length) - ;; ) - ;; (setq ess-sas-buffer-list-index (+ 1 ess-sas-buffer-list-index)) - ;; ))) - - (if (and (not no-create) - (or (string-equal suffix "log") - (string-equal suffix "lst"))) - (ess-kermit-get (file-name-nondirectory ess-sas-temp-file) - ess-temp-kermit-remote-directory)) - - (if revert - (if (and (> ess-sas-log-max 0) (string-equal suffix "log") - (> (ess-num-or-zero (nth 7 (file-attributes ess-sas-temp-file))) - ess-sas-log-max)) - (progn - (insert-file-contents ess-sas-temp-file nil 0 - ess-sas-log-max t) - t) - - (ess-revert-wisely)) nil))))))) - -;;(defun ess-sas-file (suffix &optional revert) -;; "Please use `ess-sas-goto' instead." -;; (let* ((tail (downcase (car (split-string -;; (car (last (split-string (buffer-name) "[.]"))) "[<]")))) -;;(if (fboundp 'file-name-extension) (file-name-extension (buffer-name)) -;; (substring (buffer-name) -3))) -;; (tail-in-tail-list (member tail (list "sas" "log" "lst" -;; ess-sas-suffix-1 ess-sas-suffix-2))) -;; (root (if tail-in-tail-list (expand-file-name (buffer-name)) -;; ess-sas-file-path)) -;; (ess-sas-arg (concat (file-name-sans-extension root) "." suffix)) -;; (ess-sas-buf (find-buffer-visiting ess-sas-arg))) -;; (if (equal tail suffix) (if revert (ess-revert-wisely)) -;; (if (not ess-sas-buf) (find-file ess-sas-arg) -;; (switch-to-buffer ess-sas-buf) -;; (if revert (ess-revert-wisely)))))) - - -(defun ess-sas-goto-file-1 () - "Switch to ess-sas-file-1 and revert from disk." - (interactive) - (ess-sas-goto ess-sas-suffix-1 'revert)) - -(defun ess-sas-goto-file-2 () - "Switch to ess-sas-file-2 and revert from disk." - (interactive) - (ess-sas-goto ess-sas-suffix-2 'revert)) - -(defun ess-sas-goto-log (&optional ess-tmp-no-error-check) - "Switch to the .log file, revert from disk and search for error messages." - (interactive) - - (let ((ess-sas-error (concat - "^ERROR [0-9]+-[0-9]+:\\|^ERROR:\\|_ERROR_=1 _N_=\\|_ERROR_=1[ ]?$" - "\\|NOTE: MERGE statement has more than one data set with repeats" - "\\|NOTE: Variable .* is uninitialized." - "\\|NOTE: SAS went to a new line when INPUT statement reached past" - "\\|NOTE 485-185: Informat .* was not found" - "\\|NOTE: Estimated G matrix is not positive definite." - "\\|NOTE: Compressing data set .* increased size by" - "\\|NOTE: ERROR DETECTED IN ANNOTATE=" - "\\|WARNING: Apparent symbolic reference .* not resolved." - "\\|WARNING: Length of character variable has already been set." - "\\|WARNING: Not all variables in the list " - "\\|WARNING: RUN statement ignored due to previous errors." - "\\|WARNING: Values exist outside the axis range" - "\\|WARNING: Truncated record." - "\\|Bus Error In Task\\|Segmentation Violation In Task")) - (ess-sas-save-point nil)); (ess-sas-pop-mark nil)) - - (if (ess-sas-goto "log" 'revert) (progn - (setq ess-sas-save-point (point)) - (goto-char (point-min))) - (setq ess-sas-save-point (point))) - - ;(if (number-char-or-marker-p ess-sas-save-point) (progn - (if ess-tmp-no-error-check (goto-char ess-sas-save-point) - (if (or (search-forward-regexp ess-sas-error nil t) - (and (goto-char (point-min)) - (search-forward-regexp ess-sas-error nil t))) - t - (goto-char ess-sas-save-point))))) - -(defun ess-sas-goto-lst () - "Switch to the .lst file and revert from disk." - (interactive) - (ess-sas-goto "lst" 'revert)) - -(defun ess-sas-goto-sas (&optional revert) - "Switch to the .sas file." - (interactive) - (ess-sas-goto "sas" revert)) - -(defun ess-sas-goto-shell (&optional set-buffer) - "Set `ess-sas-file-path' and goto `ess-sas-shell-buffer'. If -optional argument is non-nil, then set-buffer rather than switch." - (interactive) - (ess-sas-file-path) - - ; The following let* block is an attempt to deal with remote directories. - (let* ((temp-shell-buffer-remote-host - (or ess-sas-shell-buffer-remote-host (ess-sas-file-path-remote-host))) - (temp-shell-buffer-remote-init ess-sas-shell-buffer-remote-init) - (temp-shell-buffer - (if temp-shell-buffer-remote-host - (concat "*" temp-shell-buffer-remote-host "*") - ess-sas-shell-buffer)) - ) - - (if (get-buffer temp-shell-buffer) - (if set-buffer (set-buffer temp-shell-buffer) - (switch-to-buffer temp-shell-buffer)) - (shell) - (rename-buffer temp-shell-buffer) - (ess-sleep) ; GNU Emacs needs this - - (if temp-shell-buffer-remote-host (progn - (insert (concat - temp-shell-buffer-remote-init " " temp-shell-buffer-remote-host)) - (comint-send-input)) - ) - - (if (eq ess-sas-submit-method 'sh) - (add-hook 'comint-output-filter-functions 'ess-exit-notify-sh)) ;; 19.28 - ;; nil t) works for newer emacsen - ) - ) - - (goto-char (point-max)) - ; (insert "cd " ess-temp-directory) - ; (comint-send-input)) - ) - -(defun ess-sas-interactive () - "And now for something completely different." - (interactive) - ;;(ess-sas-file-path) - (setq ess-local-customize-alist SAS-customize-alist) - ;; (let ((ess-temp-sas-file - ;; (nth 0 (split-string - ;; (car (last (split-string ess-sas-file-path "\\([a-zA-Z][a-zA-Z]:\\|]\\)"))) "[.]")))) - (setq ess-sas-shell-buffer "*iESS[SAS]*") - (ess-sas-goto-shell) - (ess-add-ess-process) - (ess-setq-vars-local ess-local-customize-alist) - (inferior-ess-mode) - (ess-eval-linewise (concat ess-sas-submit-command " " ess-sas-submit-command-options " -stdio")) - ;;" -altlog " ess-temp-sas-file ".log -altprint " - ;; ess-temp-sas-file ".lst -stdio")) - (ess-sas-goto-sas) - (setq ess-sas-submit-method 'iESS) - (setq ess-eval-visibly-p nil) - ) - -;;(defun ess-sas-interactive () -;; (interactive) -;; (ess-sas-file-path) -;; (setq ess-sas-submit-method 'iESS) -;; -;; (let ((ess-temp-stderr " ") (ess-temp-stdout " ") (ess-temp-stdin " ")) -;; (setq ess-sas-shell-buffer "*LOG*") -;; (ess-sas-goto-shell) -;; (insert "tty") -;; (comint-send-input) -;; (sleep-for ess-sleep-for) -;; (save-excursion (setq ess-temp-stderr (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) -;; (setq ess-sas-shell-buffer "*OUTPUT*") -;; (ess-sas-goto-shell) -;; (insert "tty") -;; (comint-send-input) -;; (sleep-for ess-sleep-for) -;; (save-excursion (setq ess-temp-stdout (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) -;; (setq ess-sas-shell-buffer "*PROGRAM*") -;; (ess-sas-goto-shell) -;;;; (insert "tty") -;; (comint-send-input) -;; (sleep-for ess-sleep-for) -;; (insert "sh") -;; (comint-send-input) -;; (sleep-for ess-sleep-for) -;; (save-excursion (setq ess-temp-stdin (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) -;; (insert (concat ess-sas-submit-command " " ess-sas-submit-command-options " -stdio <" -;; ess-temp-stdin " >1 " ess-temp-stdout " >2 " ess-temp-stderr)) -;; (comint-send-input) -;; (ess-add-ess-process) -;; (ess-sas-goto-sas) -;;)) - -(defun ess-sas-kill-buffers () - "Kill all buffers related to a .sas file." - (interactive) - (ess-sas-file-path) - (ess-sas-goto "log" nil t) - (kill-buffer nil) - (ess-sas-goto "lst" nil t) - (kill-buffer nil) - (ess-sas-goto ess-sas-suffix-1 nil t) - (kill-buffer nil) - (ess-sas-goto ess-sas-suffix-2 nil t) - (kill-buffer nil) - (ess-sas-goto "sas" nil t) - (kill-buffer nil) - ) - -; else -(defun ess-sas-rtf-portrait (&optional ess-tmp-font-size) - "Creates an MS RTF portrait file from the current buffer." - (interactive) -; (ess-sas-file-path t) - (ess-revert-wisely) - - (set-visited-file-name (concat (buffer-name) ".rtf")) -; (ess-sas-goto "rtf" t) - (if 'buffer-read-only (setq buffer-read-only nil)) - (ess-rtf-replace-chars) - - (goto-char (point-min)) - (insert (concat - "{\\rtf1\\ansi{\\fonttbl\\f1\\fmodern " ess-sas-rtf-font-name ";}\n" - "\\margl720\\margr720\\margt720\\margb720\n" - "{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\n" - "{\\stylesheet{\\s15\\plain\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Text;}{\\*\\cs16 \\additive\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Base Style;}}\n" - "{\\plain\\s15{\\cs16\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024{\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024\n")) - - (goto-char (point-max)) - (insert "}}}}\n") - - (save-buffer) - (kill-buffer (current-buffer))) - -(defun ess-rtf-replace-chars () - "Convert a text file to an MS RTF file." - (interactive) - (goto-char (point-min)) - (while (re-search-forward "\n" nil t) (replace-match "\\par\n" nil t)) - (goto-char (point-min)) - (while (re-search-forward "\f" nil t) (replace-match "\\page\n" nil t)) - (goto-char (point-min)) - (while (re-search-forward "\t" nil t) (replace-match "\\tab" nil t))) - -(defun ess-sas-rtf-landscape (&optional ess-tmp-font-size) - "Creates an MS RTF landscape file from the current buffer." - (interactive) - (ess-revert-wisely) - - (set-visited-file-name (concat (buffer-name) ".rtf")) - - (if 'buffer-read-only (setq buffer-read-only nil)) - (ess-rtf-replace-chars) - - (goto-char (point-min)) - (insert (concat - "{\\rtf1\\ansi{\\fonttbl\\f1\\fmodern " ess-sas-rtf-font-name ";}\n" - "\\margl720\\margr720\\margt720\\margb720\n" - "{\\*\\pgdsctbl\n" - "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" - "\\landscape\\paperh12240\\paperw15840\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n" - "{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\n" - "{\\stylesheet{\\s15\\plain\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Text;}{\\*\\cs16 \\additive\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Base Style;}}\n" - "{\\plain\\s15{\\cs16\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024{\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024\n")) - - (goto-char (point-max)) - (insert "}}}}\n") - - (save-buffer) - (kill-buffer (current-buffer))) - -(defun ess-sas-rtf-us-landscape () - "Creates an MS RTF US landscape file from the current buffer." - (interactive) - (ess-sas-rtf-portrait "16") - (ess-sas-goto "rtf" t) - (goto-char (point-min)) - (forward-line 3) - (insert (concat "{\\*\\pgdsctbl\n" - "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" - "\\landscape\\paperh12240\\paperw15840\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n")) - (save-buffer) - (kill-buffer (current-buffer))) - -(defun ess-sas-rtf-a4-landscape () - "Creates an MS RTF A4 landscape file from the current buffer." - (interactive) - (ess-sas-rtf-portrait "16") - (ess-sas-goto "rtf" t) - (goto-char (point-min)) - (forward-line 3) - (insert (concat "{\\*\\pgdsctbl\n" - "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn16837\\pghsxn11905\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" - "\\landscape\\paperh11905\\paperw16837\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn16837\\pghsxn11905\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n")) - (save-buffer) - (kill-buffer (current-buffer))) - -(defun ess-sas-submit () - "Save the .sas file and submit to shell using a function that -depends on the value of `ess-sas-submit-method'" - (interactive) - (ess-sas-file-path) - (ess-sas-goto-sas) - (save-buffer) - (hack-local-variables) - ;(ess-save-and-set-local-variables) - - (cond - ((eq ess-sas-submit-method 'ms-dos) - (ess-sas-submit-windows ess-sas-submit-command - ess-sas-submit-command-options)) - ((eq ess-sas-submit-method 'iESS) - (ess-sas-submit-iESS ess-sas-submit-command - ess-sas-submit-command-options)) - ((eq ess-sas-submit-method 'sh) - (ess-sas-submit-sh ess-sas-submit-command - ess-sas-submit-command-options)) - (t (ess-sas-submit-sh ess-sas-submit-command - ess-sas-submit-command-options))) - ; (ess-sas-goto-sas) - ) - -(defun ess-sas-submit-iESS (arg1 arg2) - "iESS -Submit a batch job in an inferior-ESS buffer. The buffer should -(1) have telnet access and be running a shell on a remote machine -or -(2) be running a shell on the local machine. - -The user can telnet to the remote computer and then declare the -*telnet-buffer* to be an inferior ESS buffer with the `ess-add-ess-process' -command. When using a remote computer, the .sas file must live on the -remote computer and be accessed through `ange-ftp'. When -`ess-sas-submit' saves a file, it is therefore saved on the remote -computer. The various functions such as `ess-sas-goto-lst' retrieve -their files from the remote computer. Local copies of the .sas .lst -.log and others may be made manually with `write-buffer'." - ;; (ess-eval-linewise (concat "cd default-directory)) -(ess-force-buffer-current "Process to load into: ") -(ess-eval-linewise - (concat "cd " (car (last - (split-string (file-name-directory ess-sas-file-path) "\\(:\\|]\\)"))))) -(ess-eval-linewise (concat arg1 " " arg2 " " (buffer-name) " &"))) - -(defun ess-sas-submit-region () - "Write region to temporary file, and submit to SAS." - (interactive) - (ess-sas-file-path) - (hack-local-variables t) - (write-region (region-beginning) (region-end) - (concat (ess-sas-temp-root) ".sas")) - - (let ((arg1 ess-sas-submit-command) - (arg2 ess-sas-submit-command-options)) - (save-excursion - (ess-sas-goto-shell t) - - (if (and (when - ;; Silence byte compiler warns about w32-fns - (fboundp 'w32-shell-dos-semantics) - (w32-shell-dos-semantics)) - (string-equal ":" (substring ess-sas-file-path 1 2))) - (progn - (insert (substring ess-sas-file-path 0 2)) - (comint-send-input) - )) - - (insert "cd \"" (convert-standard-filename - (file-name-directory ess-sas-file-path)) "\"") - (comint-send-input) - - (insert (concat ess-sas-submit-pre-command " " arg1 - " " arg2 - " " (ess-sas-temp-root) " " ess-sas-submit-post-command)) - (comint-send-input) - )) - ) - -(defun ess-sas-submit-sh (arg1 arg2) - "Unix or bash in the *shell* buffer. -Multiple processing is supported on this platform. -SAS may not be found in your PATH. You can alter your PATH to include -SAS or you can specify the PATHNAME (PATHNAME can NOT contain spaces), -i.e. let arg1 be your local equivalent of -\"/usr/local/sas612/sas\"." - (if (string-equal (substring - (file-name-nondirectory ess-sas-file-path) 0 1) ess-kermit-prefix) - (progn - (ess-kermit-send) - (ess-sas-goto-shell t) - (insert ess-sas-submit-pre-command " " arg1 " " - (substring (file-name-sans-extension - (file-name-nondirectory ess-sas-file-path)) 1) - " " arg2 " " ess-sas-submit-post-command) - (comint-send-input)) - ;;else - ;; (ess-sas-goto-shell t) - (ess-sas-cd) - ; (insert "cd " (car (last (split-string (file-name-directory ess-sas-file-path) - ;"\\([a-zA-Z][a-zA-Z]:\\|]\\)")))) - ; (comint-send-input) - (insert ess-sas-submit-pre-command " " arg1 " " - (file-name-sans-extension (file-name-nondirectory ess-sas-file-path)) - " " arg2 " " ess-sas-submit-post-command)) - ; (ess-sleep) - (comint-send-input)) - -(defun ess-sas-submit-windows (arg1 arg2) - "Windows using MS-DOS prompt in the *shell* buffer. -Multiple processing is supported on this platform. -On most Windows installations, SAS will not be found in your -PATH so you should alter your PATH to include SAS, i.e. - -SET PATH=%PATH%;C:\\Program Files\\SAS - -Or you can specify the PATHNAME directly (you must escape -spaces by enclosing the string in \\\"'s), i.e. let -`ess-sas-submit-command' be \"\\\"C:\\Program Files\\SAS\\sas.exe\\\"\". -Keep in mind that the maximum command line length in MS-DOS is -127 characters so altering your PATH is preferable." - ;(ess-save-and-set-local-variables) - (ess-sas-goto-shell t) - (if (string-equal ":" (substring ess-sas-file-path 1 2)) - (progn - (insert (substring ess-sas-file-path 0 2)) - (comint-send-input) - ) - ) - (insert "cd \"" (convert-standard-filename - (file-name-directory ess-sas-file-path)) "\"") - (comint-send-input) - (insert ess-sas-submit-pre-command " " arg1 " -sysin \"" - (file-name-sans-extension (file-name-nondirectory ess-sas-file-path)) "\" " - arg2 " " ess-sas-submit-post-command) - (comint-send-input)) - -(defun ess-sas-tab-to-tab-stop () - "Tab to next tab-stop and set left margin." - (interactive) - (tab-to-tab-stop) - (setq left-margin (current-column)) - ) - -(defun ess-sas-temp-root () - "Return `ess-sas-file-path' sans extension with `ess-sas-temp-root' appended." - (concat (file-name-sans-extension ess-sas-file-path) ess-sas-temp-root)) - -(defun ess-sas-transcript (&optional strip) - "Comment .log messages to create a .sas program; use C-u to strip." - (interactive "P") - (save-excursion - (goto-char (point-min)) - - (while (search-forward-regexp (concat - "^\\(\\(1[ \t]+The SAS System\\| \\|NOTE\\|WARNING\\|ERROR\\|" - "[ \t]+\\(\\(real\\|cpu\\) time\\|Licensed to\\|Engine:\\|" - "Physical Name:\\|File Name=\\|Owner Name=\\|Group Name=\\|" - "Access Permission=\\|File Size (bytes)=\\|Pipe command=\\|" - "RECFM=[DFNPV],LRECL=\\|[0-9]+:[0-9]+[ /t]+[0-9]+:[0-9]+\\|" - "[1-9][0-9]* at [0-9]+:[0-9]+[ /t]+[1-9][0-9]* at [0-9]+:[0-9]+\\)\\).*$" - "\\|[0-9]+\\([ \t]+!\\)?\\|MPRINT([_A-Z]+):\\|" - "[ \t]+\\(values at the places given by: (Line):(Column).\\|" - "The m\\(in\\|ax\\)imum record length was [1-9][0-9]*.\\|" - "One or more lines were truncated.\\|" - "Each place is given by: (Number of times) at (Line):(Column).\\|" - "[0-9][0-9]:[0-9][0-9] [MTWFS][aeioudhnrst]+day, [JFMASOND]" - "[aeiouybcghlmnprstv]+ [1-9][0-9]?, 20[0-9][0-9]\\)\\)") - nil t) (replace-match (if strip " " "/*\\&*/") t)) - )) - -(defun ess-sas-toggle-sas-listing-mode (&optional force) - "Toggle SAS-listing-mode for .lst files." - (interactive) - (ess-sas-goto-lst) - - (if (equal (cdr (assoc "\\.[lL][sS][tT]\\'" auto-mode-alist)) 'SAS-listing-mode) (progn - (setq auto-mode-alist (delete '("\\.[lL][sS][tT]\\'" . SAS-listing-mode) auto-mode-alist)) - (setq buffer-read-only nil) - (ess-listing-minor-mode 0)) - (setq auto-mode-alist (append '(("\\.[lL][sS][tT]\\'" . SAS-listing-mode)) auto-mode-alist)) - (setq buffer-read-only t) - (ess-listing-minor-mode 1))) - -(defun ess-sas-toggle-sas-log-mode () - "Toggle SAS-log-mode for .log files." - (interactive) - - (ess-sas-goto-log) - (kill-buffer nil) - - ; (if (equal (cdr (assoc "\\.[lL][oO][gG]\\'" auto-mode-alist)) 'SAS-log-mode) (progn - ; (setq auto-mode-alist (delete '("\\.[lL][oO][gG]\\'" . SAS-log-mode) auto-mode-alist)) - ; (setq buffer-read-only nil) - ; (ess-transcript-minor-mode 0) - ; (font-lock-mode 0)) - ; (setq auto-mode-alist (append '(("\\.[lL][oO][gG]\\'" . SAS-log-mode)) auto-mode-alist)) - ; (setq buffer-read-only t) - ; (ess-transcript-minor-mode 1) - ; (font-lock-mode 1) - ; (font-lock-fontify-buffer)) - - (if (equal (cdr (assoc "\\.[lL][oO][gG]\\'" auto-mode-alist)) 'SAS-log-mode) - (setq auto-mode-alist (delete '("\\.[lL][oO][gG]\\'" . SAS-log-mode) auto-mode-alist)) - (setq auto-mode-alist (append '(("\\.[lL][oO][gG]\\'" . SAS-log-mode)) auto-mode-alist))) - (ess-sas-goto-log)) - -(define-obsolete-variable-alias - 'ess-sas-versions-created 'ess-sas-created-runners "ESS 18.10") -(defvar ess-sas-created-runners) -(defun ess-sas-define-runners () - "Generate the `M-x SASV' functions for starting other versions of SAS. -See `ess-sas-versions' for strings that determine which functions are created. - -The local variable `ess-sas-created-runners' is used to return list of -the new SAS defuns, if any, that were created. The defuns will normally -be placed on the menubar upon ESS initialization." - ;; This works by creating a temp buffer where the template function is - ;; edited so that V is replaced by the version number - (let ((versions - ;; Find which versions of SAS we want. Remove the pathname, - ;; leaving just the name of the executable. - (delete-dups - (mapcar #'file-name-nondirectory - (apply #'nconc - (mapcar #'ess-find-exec-completions - ess-sas-versions)))))) - ;; Iterate over each string in VERSIONS, creating a new defun each time. - (setq ess-sas-created-runners - (mapc (lambda (v) (ess-define-runner v "SAS")) versions)))) -(define-obsolete-function-alias - 'ess-sas-create-versions 'ess-sas-define-runners "ESS 18.10") - - -;;; Section 3: Key Definitions - - -(defun ess-sas-edit-keys-set (&optional arg) - "Set TAB/RET key in `SAS-mode'. -If arg is nil - TAB is `sas-indent-line' and - RET is `newline-and-indent'. -Else - TAB is `ess-sas-tab-to-tab-stop', - C-TAB is `ess-sas-backward-delete-tab' and - RET is `newline'." - (interactive) - - (if arg - (progn - (define-key sas-mode-local-map [(control tab)] - 'ess-sas-backward-delete-tab) - (define-key sas-mode-local-map [return] 'newline) - (define-key sas-mode-local-map "\t" 'ess-sas-tab-to-tab-stop)) - ;;else - (define-key sas-mode-local-map [return] 'newline-and-indent) - (define-key sas-mode-local-map "\t" 'sas-indent-line))) - -(defvar ess-sas-edit-keys-toggle nil - "Toggle TAB/RET key in `SAS-mode'. -nil binds TAB to `sas-indent-line' and RET to `newline-and-indent'. -Non-nil binds TAB to `ess-sas-tab-to-tab-stop', -C-TAB to `ess-sas-backward-delete-tab', and RET to `newline'.") - -(defun ess-sas-edit-keys-toggle (&optional arg) - "Toggle `ess-sas-edit-keys-toggle'. Optional arg is still -accepted for backward compatibility, however, arg is ignored." - (interactive) - - (setq ess-sas-edit-keys-toggle (not ess-sas-edit-keys-toggle)) - (ess-sas-edit-keys-set ess-sas-edit-keys-toggle) - ) - -(defvar ess-sas-global-pc-keys nil - "Non-nil if function keys use PC-like SAS key definitions in all modes.") - -(defun ess-sas-global-pc-keys () - "PC-like SAS key definitions" - (interactive) - (global-set-key [(control f1)] 'ess-sas-rtf-portrait) - (global-set-key [(control f2)] 'ess-sas-rtf-landscape) - (global-set-key (quote [f2]) 'ess-revert-wisely) - (global-set-key (quote [f3]) 'ess-sas-goto-shell) - (global-set-key (quote [f4]) 'ess-sas-goto-file-1) - (global-set-key (quote [f5]) 'ess-sas-goto-sas) - (global-set-key (quote [f6]) 'ess-sas-goto-log) - (global-set-key [(control f6)] 'ess-sas-append-log) - (global-set-key (quote [f7]) 'ess-sas-goto-lst) - (global-set-key [(control f7)] 'ess-sas-append-lst) - (global-set-key (quote [f8]) 'ess-sas-submit) - (global-set-key [(control f8)] 'ess-sas-submit-region) - (global-set-key (quote [f9]) 'ess-sas-data-view-fsview) - (global-set-key [(control f9)] 'ess-sas-data-view-insight) - ;; (global-set-key (quote [f10]) 'ess-sas-toggle-sas-log-mode) - ;; (global-set-key [(control f10)] 'ess-sas-toggle-sas-listing-mode) - ;; (global-set-key (quote [f11]) 'ess-sas-goto-file-2) - ;; (global-set-key [(control f11)] 'ess-ebcdic-to-ascii-search-and-replace) - (global-set-key (quote [f12]) 'ess-sas-graph-view) - (global-set-key [(control tab)] 'ess-sas-backward-delete-tab) - ;; (define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) - (setq ess-sas-global-pc-keys t) - (setq ess-sas-global-unix-keys nil) - (setq ess-sas-local-pc-keys nil) - (setq ess-sas-local-unix-keys nil) - ) - -(defun ess-sas-global-unix-keys () - "Unix/Mainframe-like SAS key definitions" - (interactive) - (global-set-key [(control f1)] 'ess-sas-rtf-portrait) - (global-set-key [(control f2)] 'ess-sas-rtf-landscape) - (global-set-key (quote [f2]) 'ess-revert-wisely) - (global-set-key (quote [f3]) 'ess-sas-submit) - (global-set-key [(control f3)] 'ess-sas-submit-region) - (global-set-key (quote [f4]) 'ess-sas-goto-sas) - (global-set-key (quote [f5]) 'ess-sas-goto-log) - (global-set-key [(control f5)] 'ess-sas-append-log) - (global-set-key (quote [f6]) 'ess-sas-goto-lst) - (global-set-key [(control f6)] 'ess-sas-append-lst) - (global-set-key (quote [f7]) 'ess-sas-goto-file-1) - (global-set-key (quote [f8]) 'ess-sas-goto-shell) - (global-set-key (quote [f9]) 'ess-sas-data-view-fsview) - (global-set-key [(control f9)] 'ess-sas-data-view-insight) - ;; (global-set-key (quote [f10]) 'ess-sas-toggle-sas-log-mode) - ;; (global-set-key [(control f10)] 'ess-sas-toggle-sas-listing-mode) - ;; (global-set-key (quote [f11]) 'ess-sas-goto-file-2) - ;; (global-set-key [(control f11)] 'ess-ebcdic-to-ascii-search-and-replace) - (global-set-key (quote [f12]) 'ess-sas-graph-view) - (global-set-key [(control tab)] 'ess-sas-backward-delete-tab) - ;;(define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) - (setq ess-sas-global-pc-keys nil) - (setq ess-sas-global-unix-keys t) - (setq ess-sas-local-pc-keys nil) - (setq ess-sas-local-unix-keys nil) - ) - -(defun ess-sas-local-pc-keys () - "PC-like SAS key definitions." - (interactive) - (define-key sas-mode-local-map [(control f1)] 'ess-sas-rtf-portrait) - (define-key sas-mode-local-map [(control f2)] 'ess-sas-rtf-landscape) - (define-key sas-mode-local-map (quote [f2]) 'ess-revert-wisely) - (define-key sas-mode-local-map (quote [f3]) 'ess-sas-goto-shell) - (define-key sas-mode-local-map (quote [f4]) 'ess-sas-goto-file-1) - (define-key sas-mode-local-map (quote [f5]) 'ess-sas-goto-sas) - (define-key sas-mode-local-map (quote [f6]) 'ess-sas-goto-log) - (define-key sas-mode-local-map [(control f6)] 'ess-sas-append-log) - (define-key sas-mode-local-map (quote [f7]) 'ess-sas-goto-lst) - (define-key sas-mode-local-map [(control f7)] 'ess-sas-append-lst) - (define-key sas-mode-local-map (quote [f8]) 'ess-sas-submit) - (define-key sas-mode-local-map [(control f8)] 'ess-sas-submit-region) - (define-key sas-mode-local-map (quote [f9]) 'ess-sas-data-view-fsview) - (define-key sas-mode-local-map [(control f9)] 'ess-sas-data-view-insight) - (define-key sas-mode-local-map (quote [f10]) 'ess-sas-toggle-sas-log-mode) - (define-key sas-mode-local-map [(control f10)] 'ess-sas-toggle-sas-listing-mode) - (define-key sas-mode-local-map (quote [f11]) 'ess-sas-goto-file-2) - (define-key sas-mode-local-map [(control f11)] 'ess-ebcdic-to-ascii-search-and-replace) - (define-key sas-mode-local-map (quote [f12]) 'ess-sas-graph-view) - ;(define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) - (setq ess-sas-global-pc-keys nil) - (setq ess-sas-global-unix-keys nil) - (setq ess-sas-local-pc-keys t) - (setq ess-sas-local-unix-keys nil) - ) - -(defun ess-sas-local-unix-keys () - "Unix/Mainframe-like SAS key definitions" - (interactive) - (define-key sas-mode-local-map [(control f1)] 'ess-sas-rtf-portrait) - (define-key sas-mode-local-map [(control f2)] 'ess-sas-rtf-landscape) - (define-key sas-mode-local-map (quote [f2]) 'ess-revert-wisely) - (define-key sas-mode-local-map (quote [f3]) 'ess-sas-submit) - (define-key sas-mode-local-map [(control f3)] 'ess-sas-submit-region) - (define-key sas-mode-local-map (quote [f4]) 'ess-sas-goto-sas) - (define-key sas-mode-local-map (quote [f5]) 'ess-sas-goto-log) - (define-key sas-mode-local-map [(control f5)] 'ess-sas-append-log) - (define-key sas-mode-local-map (quote [f6]) 'ess-sas-goto-lst) - (define-key sas-mode-local-map [(control f6)] 'ess-sas-append-lst) - (define-key sas-mode-local-map (quote [f7]) 'ess-sas-goto-file-1) - (define-key sas-mode-local-map (quote [f8]) 'ess-sas-goto-shell) - (define-key sas-mode-local-map (quote [f9]) 'ess-sas-data-view-fsview) - (define-key sas-mode-local-map [(control f9)] 'ess-sas-data-view-insight) - (define-key sas-mode-local-map (quote [f10]) 'ess-sas-toggle-sas-log-mode) - (define-key sas-mode-local-map [(control f10)] 'ess-sas-toggle-sas-listing-mode) - (define-key sas-mode-local-map (quote [f11]) 'ess-sas-goto-file-2) - (define-key sas-mode-local-map [(control f11)] 'ess-ebcdic-to-ascii-search-and-replace) - (define-key sas-mode-local-map (quote [f12]) 'ess-sas-graph-view) - ;(define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) - (setq ess-sas-global-pc-keys nil) - (setq ess-sas-global-unix-keys nil) - (setq ess-sas-local-pc-keys nil) - (setq ess-sas-local-unix-keys t) - ) - -(defun ess-kermit-get (&optional ess-file-arg ess-dir-arg) - "Get a file with Kermit. WARNING: Experimental! From your *shell* -buffer, start kermit and then log in to the remote machine. Open -a file that starts with `ess-kermit-prefix'. From that buffer, -execute this command. It will retrieve a file from the remote -directory that you specify with the same name, but without the -`ess-kermit-prefix'." - - (interactive) - - ;; (save-match-data - (let ((ess-temp-file (if ess-file-arg ess-file-arg (buffer-name))) - (ess-temp-file-remote-directory ess-dir-arg)) - - (if (string-equal ess-kermit-prefix (substring ess-temp-file 0 1)) - (progn - ;; I think there is a bug in the buffer-local variable handling in GNU Emacs 21.3 - ;; Setting ess-kermit-remote-directory every time is somehow resetting it to the - ;; default on the second pass. So, here's a temporary work-around. It will fail - ;; if you change the default, so maybe this variable should not be customizable. - ;; In any case, there is also trouble with local variables in XEmacs 21.4.9 and - ;; 21.4.10. XEmacs 21.4.8 is fine. - (if ess-temp-file-remote-directory - (setq ess-kermit-remote-directory ess-temp-file-remote-directory) - - (if (string-equal "." ess-kermit-remote-directory) - (setq ess-kermit-remote-directory (read-string "Remote directory to transfer file from: " - ess-kermit-remote-directory)))) - - (setq ess-temp-file-remote-directory ess-kermit-remote-directory) - ;; (setq ess-temp-file (substring ess-temp-file (match-end 0))) - (ess-sas-goto-shell) - (insert "cd " ess-temp-file-remote-directory "; " ess-kermit-command " -s " - (substring ess-temp-file 1) " -a " ess-temp-file) - (comint-send-input) - ;; (insert (read-string "Press Return to connect to Kermit: " nil nil "\C-\\c")) - ;; (comint-send-input) - ;; (insert (read-string "Press Return when Kermit is ready to recieve: " nil nil - ;; (concat "receive ]" ess-sas-temp-file))) - ;; (comint-send-input) - ;; (insert (read-string "Press Return when transfer is complete: " nil nil "c")) - ;; (comint-send-input) - (insert (read-string "Press Return when shell is ready: ")) - (comint-send-input) - (switch-to-buffer (find-buffer-visiting ess-temp-file)) - (ess-revert-wisely) - )))) - -(defun ess-kermit-send () - "Send a file with Kermit. WARNING: Experimental! From -a file that starts with `ess-kermit-prefix', -execute this command. It will transfer this file to the remote -directory with the same name, but without the `ess-kermit-prefix'." - - (interactive) - - ;; (save-match-data - (let ((ess-temp-file (expand-file-name (buffer-name))) - (ess-temp-file-remote-directory nil)) - - (if (string-equal ess-kermit-prefix (substring (file-name-nondirectory ess-temp-file) 0 1)) - (progn - ;; I think there is a bug in the buffer-local variable handling in GNU Emacs 21.3 - ;; Setting ess-kermit-remote-directory every time is somehow resetting it to the - ;; default on the second pass. Here's a temporary work-around. It will fail - ;; if you change the default, so maybe this variable should not be customizable. - ;; In any case, there is also trouble with local variables in XEmacs 21.4.9 and - ;; 21.4.10. XEmacs 21.4.8 is fine. - (if (string-equal "." ess-kermit-remote-directory) - (setq ess-kermit-remote-directory (read-string "Remote directory to transfer file to: " - ess-kermit-remote-directory))) - - (setq ess-temp-file-remote-directory ess-kermit-remote-directory) - - ;; (setq ess-temp-file (substring ess-temp-file (match-end 0))) - (ess-sas-goto-shell) - (insert "cd " ess-temp-file-remote-directory "; " ess-kermit-command " -a " - (substring (file-name-nondirectory ess-temp-file) 1) " -g " ess-temp-file) - (comint-send-input) - ;; (insert (read-string "Press Return to connect to Kermit: " nil nil "\C-\\c")) - ;; (comint-send-input) - ;; (insert (read-string "Press Return when Kermit is ready to recieve: " nil nil - ;; (concat "receive ]" ess-sas-temp-file))) - ;; (comint-send-input) - ;; (insert (read-string "Press Return when transfer is complete: " nil nil "c")) - ;; (comint-send-input) - (insert (read-string "Press Return when shell is ready: ")) - (comint-send-input) - (switch-to-buffer (find-buffer-visiting ess-temp-file)) - (ess-revert-wisely) - )))) - -(provide 'ess-sas-a) - -;;; ess-sas-a.el ends here diff --git a/elpa/ess-20191014.1343/ess-sas-d.el b/elpa/ess-20191014.1343/ess-sas-d.el deleted file mode 100644 index af3ec492..00000000 --- a/elpa/ess-20191014.1343/ess-sas-d.el +++ /dev/null @@ -1,338 +0,0 @@ -;;; ess-sas-d.el --- SAS customization - -;; Copyright (C) 1997--2001 Richard M. Heiberger and A. J. Rossini -;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Richard M. Heiberger -;; Created: 20 Aug 1997 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This file defines all the SAS customizations for ESS behaviors. See -;; ess-sas-l and ess-sas-a for the underlying general modifications. - -;;; Code: - -;;; Autoloads: - -(require 'shell) -(require 'ess-sas-l) - -(defcustom SAS-mode-hook nil - "Hook to run when entering SAS mode." - :type 'hook - :group 'ess-sas) - -(defvar inferior-SAS-args "-stdio -linesize 80 -noovp -nosyntaxcheck" - "Arguments to use for starting SAS.") - -(defvar inferior-SAS-args-temp nil - "Hack variable, needed for args preprocessing. -Better logic needed! (see 2 uses, in this file).") - -(defvar SAS-mode-syntax-table - (let ((tab (make-syntax-table))) - (modify-syntax-entry ?\\ "." tab) ;; backslash is punctuation - (modify-syntax-entry ?+ "." tab) - (modify-syntax-entry ?- "." tab) - (modify-syntax-entry ?= "." tab) - (modify-syntax-entry ?% "w" tab) - (modify-syntax-entry ?< "." tab) - (modify-syntax-entry ?> "." tab) - (modify-syntax-entry ?& "w" tab) - (modify-syntax-entry ?| "." tab) - (modify-syntax-entry ?\' "\"" tab) - (modify-syntax-entry ?* ". 23" tab) ; comment character - (modify-syntax-entry ?\; "." tab) - (modify-syntax-entry ?_ "w" tab) - (modify-syntax-entry ?< "." tab) - (modify-syntax-entry ?> "." tab) - (modify-syntax-entry ?/ ". 14" tab) ; comment character - (modify-syntax-entry ?. "w" tab) - tab) - "Syntax table for `SAS-mode'.") - -(defun ess-SAS-pre-run-hook (temp-ess-dialect) - "Set up log and list files for interactive SAS." - - (let* ((ess-shell-buffer-name-flag (get-buffer "*shell*")) - ess-shell-buffer-name - ;; isn't pretty yet. - ;; ess-local-process-name is defined after this function. - ;; it needs to be defined prior to this function. - (tmp-procname (let ((ntry 0) - (done nil)) - ;; find a non-existent process - (while (not done) - (setq ntry (1+ ntry) - done (not - (get-process (ess-proc-name - ntry - temp-ess-dialect))))) - (ess-proc-name ntry temp-ess-dialect))) - ;; Following was tmp-local-process-name. Stolen from inferior-ess - (ess-sas-lst-bufname (concat "*" tmp-procname ".lst*")) - (ess-sas-log-bufname (concat "*" tmp-procname ".log*")) - (explicit-shell-file-name "/bin/sh") - inferior-SAS-redirect-args - ess-sas-lst - ess-sas-log) - - (ess-write-to-dribble-buffer - (format "(ess-SAS-pre-run-hook 1): ess-lang=%s, ess-dialect=%s, temp-dialect=%s, buf=%s \n" - ess-language - ess-dialect - temp-ess-dialect - (current-buffer))) - ;; If someone is running a *shell* buffer, rename it to avoid - ;; inadvertent nuking. - (if ess-shell-buffer-name-flag - (with-current-buffer "*shell*" - (setq ess-shell-buffer-name - (rename-buffer "*ess-shell-regular*" t)))) - - ;; Construct the LST buffer for output - (if (get-buffer ess-sas-lst-bufname) - nil - (shell) - (accept-process-output (get-buffer-process (current-buffer))) - (sleep-for 2) ; need to wait, else working too fast! - (setq ess-sas-lst (ess-insert-accept "tty")) - (SAS-listing-mode) - (shell-mode) - (ess-listing-minor-mode t) - (rename-buffer ess-sas-lst-bufname t)) - - ;; Construct the LOG buffer for output - (if (get-buffer ess-sas-log-bufname) - nil - (shell) - (accept-process-output (get-buffer-process (current-buffer))) - (sleep-for 2) ; need to wait, else working too fast! - (setq ess-sas-log (ess-insert-accept "tty")) - ;(SAS-log-mode) - (shell-mode) - (ess-transcript-minor-mode t) - (rename-buffer ess-sas-log-bufname t)) - - (setq inferior-SAS-redirect-args (concat " " - ess-sas-lst - " " - ess-sas-log - " ") - inferior-SAS-args-temp (concat inferior-SAS-redirect-args - inferior-SAS-args)) - - ;; Restore the *shell* buffer - (if ess-shell-buffer-name-flag - (with-current-buffer ess-shell-buffer-name - (rename-buffer "*shell*"))) - - (delete-other-windows) - (split-window-vertically) - (split-window-vertically) - (switch-to-buffer (nth 2 (buffer-list))) - (other-window 2) - (switch-to-buffer ess-sas-log-bufname) - (split-window-vertically) - (other-window 1) - (switch-to-buffer ess-sas-lst-bufname) - (other-window 2) - - ;;workaround - (setq inferior-SAS-program - (concat (file-name-as-directory ess-etc-directory) - "ess-sas-sh-command")) - (setq inferior-ess-program inferior-SAS-program))) - -(defun ess-insert-accept (command) - "Submit command to process, get next line." - (interactive) - (goto-char (point-max)) - (insert command) - (comint-send-input) - (accept-process-output (get-buffer-process (current-buffer))) - (forward-line -1) - (let* ((beg (point)) - (ess-tty-name (progn (end-of-line) (buffer-substring beg (point))))) - (goto-char (point-max)) - ess-tty-name)) - - -(defvar SAS-customize-alist - '((ess-local-customize-alist . 'SAS-customize-alist) - (ess-language . "SAS") - (ess-dialect . "SAS") - (inferior-ess-program . inferior-SAS-program) - (ess-help-sec-regex . "^[A-Z. ---]+:$") - (ess-help-sec-keys-alist . " ") - (ess-object-name-db-file . "ess-sas-namedb.el") - (inferior-ess-objects-command . "objects(%d)");;FIXME - (inferior-ess-help-command . "help(\"%s\",pager=\"cat\",window=F)\n");;FIXME - (inferior-ess-exit-command . "endsas;\n") - (ess-loop-timeout . 500000 ) - (inferior-ess-primary-prompt . "^") - (inferior-ess-secondary-prompt . "^") - (comint-use-prompt-regexp . t) - (inferior-ess-start-args . inferior-SAS-args-temp) - ;; (ess-pre-run-hook . 'ess-SAS-pre-run-hook) - ;; (ess-local-process-name . nil) - ) - "Variables to customize for SAS") - -;;; The functions of interest (mode, inferior mode) - -;;;###autoload -(define-derived-mode SAS-mode ess-mode "[SAS]" - "Major mode for editing SAS source. See `ess-mode' for more help." - :group 'ess-sas - (ess-setq-vars-local SAS-customize-alist) - (setq ess-local-customize-alist SAS-customize-alist) - (setq-local sentence-end ";[\t\n */]*") - (setq-local paragraph-start "^[ \t]*$") - (setq-local paragraph-separate "^[ \t]*$") - (setq-local paragraph-ignore-fill-prefix t) - (setq-local adaptive-fill-mode nil) - (setq-local indent-line-function 'sas-indent-line) - (setq-local comment-start "/*") - (setq-local comment-start-skip "/[*]") - (setq-local comment-end "*/") - (setq-local comment-end-skip "[*]/") - (setq-local comment-column 40) - (setq-local ess-local-process-name nil) - (setq-local tab-stop-list ess-sas-tab-stop-list) - (setq-local font-lock-keywords-case-fold-search t) - ;; Local map settings, AFTER initialization (only if not yet defined) - (unless sas-mode-local-map - (setq sas-mode-local-map (copy-keymap (current-local-map))) - (ess-sas-edit-keys-set ess-sas-edit-keys-toggle) - (if ess-sas-local-unix-keys (ess-sas-local-unix-keys)) - (if ess-sas-local-pc-keys (ess-sas-local-pc-keys)) - (if ess-sas-global-unix-keys (ess-sas-global-unix-keys)) - (if ess-sas-global-pc-keys (ess-sas-global-pc-keys))) - (define-key sas-mode-local-map ";" 'ess-electric-run-semicolon) - (define-key sas-mode-local-map (kbd "\C-c\C-w") 'ess-multi-frame-SAS) - ;; this is a mess - ;; interactive and batch commands share sas-mode-local-map, - ;; but the associated commands are very different - ;; what would be better is two maps like - ;; sas-batch-mode-local-map and sas-interactive-mode-local-map - ;; or smart function definitions that would do the appropriate - ;; thing for either batch or interactive sessions - ;; however, neither of these solutions are planned - ;; therefore, no key definitions can be shared between - ;; batch and interactive at this time, hence the lines that - ;; are commented below: uncomment at your own risk - ;; (define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) - ;; (define-key sas-mode-local-map "\C-c\C-b" 'ess-sas-submit) - ;; (define-key sas-mode-local-map "\C-c\C-r" 'ess-sas-submit-region) - ;; (define-key sas-mode-local-map "\C-c\C-x" 'ess-sas-goto-log) - ;; (define-key sas-mode-local-map "\C-c\C-y" 'ess-sas-goto-lst) - - (use-local-map sas-mode-local-map) - - (setq font-lock-defaults - ;; KEYWORDS KEYWORDS-ONLY CASE-FOLD ..... - '(SAS-mode-font-lock-defaults nil t))) - - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode)) - -;; rmh Jul 10 2003 -(defun ess-electric-run-semicolon (arg) - "Insert character. If the line contains \"run;\" or \"quit;\" and nothing else then indent line." - (interactive "P") - (if ess-sas-edit-keys-toggle (insert ";") (let (insertpos) - (if (and (not arg) - (eolp) - (save-excursion - (skip-chars-backward " \t") - (backward-word 1) - (and (looking-at "run\\|quit") - (progn - (skip-chars-backward " \t") - (bolp))))) - (progn - (insert last-command-event) - (funcall indent-line-function) - (save-excursion - (if insertpos (goto-char (1+ insertpos))) - (delete-char -1)))) - (if insertpos - (save-excursion - (goto-char insertpos) - (self-insert-command (prefix-numeric-value arg))) - (self-insert-command (prefix-numeric-value arg)))))) - -(defun SAS-menu () - "Start SAS from the menu." - (interactive) - (if ess-microsoft-p - ;; replace with other choices for starting SAS? - (error "SAS cannot be started this way in ESS on Windows.") - (SAS))) - -(defun SAS () - "Call 'SAS', from SAS Institute." - (interactive) - (let* ((temp-dialect "SAS")) ;(cdr (rassoc ess-dialect SAS-customize-alist)))) - (ess-write-to-dribble-buffer - (format "(SAS): ess-dial=%s, temp-dial=%s\n" - ess-dialect - temp-dialect)) - (ess-SAS-pre-run-hook temp-dialect) - (setq ess-eval-visibly-p nil) - ;; FIXME: `inferior-SAS-args' is defined from - ;; `inferior-SAS-args-temp' in `ess-SAS-pre-run-hook' - (let ((inf-buf (inferior-ess nil SAS-customize-alist))) - (with-current-buffer inf-buf - (use-local-map sas-mode-local-map)) - inf-buf))) - -(defun ess-multi-frame-SAS () - "Put running SAS buffers into separate frames. -Load this function M-x load-file essx-sas.el RET. -Then find-file myfile.sas. If myfile.sas is already in a buffer, kill-buffer -it and then find-file it again. -Place the cursor in a myfile.sas buffer. Run SAS with M-x SAS, -Return the cursor to the myfile.sas buffer, -then enter C-c C-w to put *SAS* *SAS.log* *SAS.lst* buffers into -their own frames." - (interactive) - (delete-other-windows) - (with-current-buffer "*SAS*" - (make-frame)) - (with-current-buffer "*SAS.log*" - (make-frame)) - (with-current-buffer "*SAS.lst*" - (make-frame))) - -(defun ess-num-or-zero (arg) - "If a number, then return that number, otherwise return 0." - (or (and (numberp arg) arg) 0)) - - ; Provide package - -(provide 'ess-sas-d) - -;;; ess-sas-d.el ends here diff --git a/elpa/ess-20191014.1343/ess-sas-l.el b/elpa/ess-20191014.1343/ess-sas-l.el deleted file mode 100644 index 726842b9..00000000 --- a/elpa/ess-20191014.1343/ess-sas-l.el +++ /dev/null @@ -1,1845 +0,0 @@ -;;; ess-sas-l.el --- SAS customization - -;; Copyright (C) 1997--2009 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Authors: Richard M. Heiberger -;; A.J. Rossini -;; Rodney Sparapani -;; Created: 20 Aug 1997 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS (Emacs Speaks Statistics). - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - - -;;; Commentary: - -;; This is based upon Version 1.4 of SAS mode: - - -;;; sas-mode: indent, run etc, SAS programs. -;;; Copyright (C) 1994--1997 Tom Cook -;;; Author: Tom Cook -;;; Dept. of Biostatistics -;;; University of Wisconsin - Madison -;;; Madison, WI 53706 -;;; cook@biostat.wisc.edu -;;; -;;; Acknowledgements: -;;; Menu code for XEmacs/Lucid emacs and startup mods -;;; contributed by arossini@biostats.hmc.psu.edu -;;; -;;; Last change: 2/1/95 -;;; Last change: 01/15/02 - -;;; Code: - -(require 'ess-mode) -(require 'ess-sas-a) - -(declare-function SAS-mode "ess-sas-d") - -(put 'ess-transcript-minor-mode 'permanent-local t) -(or (assq 'ess-transcript-minor-mode minor-mode-alist) - (setq minor-mode-alist - (append minor-mode-alist - (list '(ess-transcript-minor-mode " ESStr"))))) - -(put 'ess-listing-minor-mode 'permanent-local t) -(or (assq 'ess-listing-minor-mode minor-mode-alist) - (setq minor-mode-alist - (append minor-mode-alist - (list '(ess-listing-minor-mode " ESSlst"))))) - -(defun ess-transcript-minor-mode (&optional arg) - "Toggle Ess-Transcript minor mode. -With arg, turn Ess-Transcript minor mode on if arg is positive, off -otherwise. See the command `ess-transcript-mode' for more information -on this mode." - (interactive "P") - (setq ess-transcript-minor-mode - (if (null arg) (not ess-transcript-minor-mode) - (> (prefix-numeric-value arg) 0))) - (force-mode-line-update) - (setq mode-line-process - '(" [" ess-local-process-name "]"))) - -(defun ess-listing-minor-mode (&optional arg) - "Toggle Ess-Listing minor mode. -With arg, turn Ess-Listing minor mode on if arg is positive, off -otherwise. Ess-Listing mode is used solely to place an indicator on -the mode line." - (interactive "P") - (setq ess-listing-minor-mode - (if (null arg) (not ess-listing-minor-mode) - (> (prefix-numeric-value arg) 0))) - (force-mode-line-update) - (setq mode-line-process - '(" [" ess-local-process-name "]"))) - -(defcustom ess-automatic-sas-log-or-lst-mode t - "Automatically turn on `SAS-log-mode' and `SAS-listing-mode' when enabled." - :type 'boolean - :group 'ess-sas) - -(defun ess-SAS-log-mode-p () - "Return t when when a SAS log file is detected. -A SAS log is defined as having: - -1. The first line matches \"^1[ \t]*The SAS System\" -2. The file name ends in .log. -" - (and ess-automatic-sas-log-or-lst-mode - (save-excursion - (goto-char (point-min)) - (looking-at "1[ \t]*The SAS System")) - (if (buffer-file-name) - (string-match ".log$" (buffer-file-name)) - t))) - -(defun ess-SAS-listing-mode-p () - "Return t when SAS listing file is detected. -A .lst file is a SAS listing file when: - -1. The file name ends in .lst -2. The corresponding log file exists and is a SAS log file. -" - (when ess-automatic-sas-log-or-lst-mode - (let* ((bfn (buffer-file-name)) - (log (and bfn - (string-match-p "\\.lst$" bfn) - (replace-regexp-in-string "\\.lst$" ".log" bfn)))) - (and log - (file-exists-p log) - (with-temp-buffer - (insert-file-contents log nil 0 200) - (goto-char (point-min)) - (looking-at "1[ \t]*The SAS System")))))) - -(add-to-list 'magic-mode-alist - '(ess-SAS-log-mode-p . SAS-log-mode)) -(add-to-list 'magic-mode-alist - '(ess-SAS-listing-mode-p . SAS-listing-mode)) - -(define-derived-mode SAS-log-mode SAS-mode "ESS[LOG]" - "`ess-transcript-mode' for SAS." - :group 'ess-sas - (ess-transcript-minor-mode 1) - (setq buffer-read-only t) ;; to protect the buffer. - (buffer-disable-undo)) - -(defvar sas-mode-local-map nil "contains modified local keymap for SAS") -(define-derived-mode SAS-listing-mode special-mode "ESS[LST]" - "Fundamental mode with `ess-listing-minor-mode' and read-only." - :keymap sas-mode-local-map - :group 'ess-sas - (ess-listing-minor-mode 1) - (buffer-disable-undo)) - -(fset 'sas-log-mode 'SAS-log-mode) -(fset 'SAS-transcript-mode 'SAS-log-mode) -(fset 'sas-transcript-mode 'SAS-log-mode) -(fset 'sas-mode 'SAS-mode) -(fset 'sas-listing-mode 'SAS-listing-mode) - -(defcustom sas-indent-width 4 - "Amount to indent sas statements." - :group 'ess-sas - :type 'integer) - -(defcustom sas-indent-ignore-comment "\\*" - "Comments that start with this regular expression are ignored in indentation." - :group 'ess-sas - :type 'string) - -(defcustom sas-require-confirmation t - "Require confirmation when revisiting a modified sas-output file." - :group 'ess-sas - :type 'boolean) - -(defcustom sas-pre-run-hook nil - "Hook to execute prior to running SAS via `submit-sas'." - :group 'ess-sas - :type 'hook) - -(defcustom sas-notify t - "Beep and display message when job is done." - :group 'ess-sas - :type 'boolean) - -(defcustom sas-error-notify t - "If `sas-notify' t, indicate errors in log file upon completion." - :group 'ess-sas - :type 'boolean) - -(defcustom sas-get-options nil - "Options to be passed to SAS in sas-get-dataset." - :group 'ess-sas - :type '(choice (const nil) string)) - -(defcustom sas-get-options-history nil - "History list of Options passed to SAS in sas-get-dataset." - :type '(choice (const nil) - (string)) - :group 'ess-sas) - -(defcustom sas-page-number-max-line 3 - "Number of lines from the page break, to search for the page -number." - :group 'ess-sas - :type 'integer) - -(defcustom sas-notify-popup nil - "If this and `sas-notify' are t), popup a window when SAS job ends." - :group 'ess-sas - :type 'boolean) - -(defcustom sas-tmp-libname "_tmp_" - "Libname to use for sas-get-dataset." - :group 'ess-sas - :type 'string) - -(defcustom sas-file-name nil - "The name of the current sas file." - :group 'ess-sas - :type '(choice (const nil) file)) - -;; The next two are ``the inside of [...] in a regexp'' to be used in -;; (skip-chars-(for|back)ward SAS-..-chars) -(defcustom sas-white-chars " \t\n\f" - "This does NOT escape blanks (RMH, 2000/03/20)." - :group 'ess-sas - :type 'string) - -(defcustom sas-comment-chars (concat sas-white-chars ";") - "Doc?" - :group 'ess-sas - :type 'string) - -(defcustom ess-sas-run-regexp-opt t - "If you do not want to run regexp-opt, then set to nil." - :group 'ess-sas - :type 'boolean) - -(defvar sas-buffer-name nil) -(defvar sas-file-root nil) -(defvar sas-submitable nil) -(defvar sas-dataset nil) - -(defvar SAS-mode-font-lock-defaults - (if ess-sas-run-regexp-opt - (list - ;; .log NOTE: messages - (cons "^NOTE [0-9]+-[0-9]+: Line generated by the invoked macro" - font-lock-comment-face) - (cons "^NOTE: .*$" font-lock-comment-face) - (cons "^ [^ @].*[.]$" font-lock-comment-face) - (cons "^ [a-z].*[a-z][ ]?$" font-lock-comment-face) - (cons "^ Engine:[ ]+V.+$" font-lock-comment-face) - (cons "^ Physical Name:[ ]+.+$" font-lock-comment-face) - (cons "^ \\(cpu\\|real\\) time[ ]+[0-9].*$" - font-lock-comment-face) - (cons "^ decimal may be shifted by the" - font-lock-comment-face) - (cons "^NOTE: The infile " font-lock-comment-face) - (cons "^NOTE: 1 record was read from the infile " - font-lock-comment-face) - (cons "^NOTE: [1-9][0-9]* records were read from the infile " - font-lock-comment-face) - (cons "^ Filename=.*,$" font-lock-comment-face) - (cons "^ File Name=.*,$" font-lock-comment-face) - (cons "^ File $" font-lock-comment-face) - (cons "^ Name=.*,$" font-lock-comment-face) - (cons "^ File List=(" font-lock-comment-face) - (cons "^ List=(" font-lock-comment-face) - (cons "^ Owner Name=.*,$" font-lock-comment-face) - (cons "^ Access Permission=.*,$" font-lock-comment-face) - (cons "^ Last Modified=.*,?$" font-lock-comment-face) - (cons "^ File Size (bytes)=[0-9]+$" font-lock-comment-face) - (cons "^ Pipe command=" font-lock-comment-face) - (cons "^NOTE: The file " font-lock-comment-face) - (cons "^NOTE: 1 record was written to the file " - font-lock-comment-face) - (cons "^NOTE: [1-9][0-9]* records were written to the file " - font-lock-comment-face) - (cons "^NOTE: PROC LOGISTIC is modeling the probability that" - font-lock-comment-face) - (cons "^NOTE: PROC GENMOD is modeling the probability that" - font-lock-comment-face) - (cons "^1[ ]+The SAS System.*$" font-lock-comment-face) - (cons "^\014.*$" font-lock-comment-face) - (cons "[*][*][*] ANNOTATE macros are now available [*][*][*]" - font-lock-comment-face) - (cons "For further information on ANNOTATE macros, enter," - font-lock-comment-face) - ;; (cons "^SAS/STAT 9.3_M1, SAS/ETS 9.3_M1, SAS/OR 9.3_M1" - ;; font-lock-comment-face) - (cons "\\(or \\)?%HELPANO.*$" - font-lock-comment-face) - (cons "^Local Variables:$" font-lock-comment-face) - (cons "^End:$" font-lock-comment-face) - (cons "^MPRINT([_A-Z0-9]+)" font-lock-comment-face) - - ;; .log ERROR: messages - ; (cons "^ERROR\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$" - (cons "^ERROR\\( [0-9]+-[0-9]+\\)?: .*$" - font-lock-keyword-face) - ; ERROR: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-keyword-face) - ; ERROR #-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-keyword-face) - ; ERROR ##-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-keyword-face) - ; ERROR ###-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-keyword-face) - (cons "^ a format name." font-lock-keyword-face) - (cons "^ where a numeric operand is required. The condition was: " - font-lock-keyword-face) - (cons "[ ][_]+$" font-lock-keyword-face) - - ;; .log WARNING: messages - ;(cons "^WARNING\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$" - (cons "^WARNING\\( [0-9]+-[0-9]+\\)?: .*$" - font-lock-function-name-face) - ; WARNING: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-function-name-face) - ; WARNING #-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-function-name-face) - ; WARNING ##-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-function-name-face) - ; WARNING ###-###: - (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" - font-lock-function-name-face) - - ;; SAS comments - ;; /* */ style handled by grammar above - (cons "\\(^[0-9]*\\|[:;!]\\)[ \t]*%?\\*[^;/][^;]*;" - font-lock-comment-face) - - ; these over-rides need to come before the more general declarations - (cons "\\") - ; font-lock-keyword-face) - ; - ;; SAS base and SAS/Graph statements - (cons (concat ;"\\<" - (regexp-opt - '( - "do" "to" "by" "goto" ; "go" - "abort" "and" "array" "assess" "attrib" - "baseline" "bayes" "between" "bivar" "block" "bubble" "bubble2" - "change" "choro" "class" "contains" "contrast" - "delete" "display" "dm" "donut" "drop" - "else" "error" "exchange" "exclude" - "fcs" "file" "filename" "format" "freq" - "footnote" "footnote1" "footnote2" "footnote3" "footnote4" "footnote5" - "footnote6" "footnote7" "footnote8" "footnote9" "footnote10" - "goptions" "grid" ; "ge" "gt" - "hazardratio" "hbar" "hbar3d" - "id" "if" "index" "infile" "informat" "input" ; "is" rarely used, but common false pos. - "keep" - "label" "length" "libname" "like" "link" "lsmeans" ; "le" "lt" - "manova" "means" "merge" "missing" "model" "modify" - "not" "null" ; "ne" "note" - "ods" "options" "output" "otherwise" ; "or" - "pageby" "parms" "pie" "pie3d" "plot" "plot2" "prism" "put" - "random" "rename" "repeated" "retain" - "same" "save" "scatter" "select" "set" "skip" "star" "strata" "sum" "sumby" "surface" - "table" "tables" "test" "then" "time" - "title" "title1" "title2" "title3" "title4" "title5" - "title6" "title7" "title8" "title9" "title10" - "univar" "update" - "value" "var" "vbar" "vbar3d" - "weight" "where" "window" "with" - ; "x" - ) 'words)) ;"\\>") - font-lock-keyword-face) - - ;; SAS/GRAPH statements not handled above - (cons (concat "\\<" - (regexp-opt - '("axis" "legend" "pattern" "symbol")) "\\([1-9][0-9]?\\)?" - "\\>") - font-lock-keyword-face) - - ;; SAS functions and SAS macro functions - (cons "%[a-z_][a-z_0-9]*[(;]" font-lock-function-name-face) - ;(cons "\\" - "("); "[ \t]*(") - font-lock-function-name-face) - ) - (list - ;; .log NOTE: messages - (cons "^NOTE: .*$" font-lock-constant-face) - - ;; .log ERROR: messages - (cons "^ERROR: .*$" font-lock-keyword-face) - - ;; .log WARNING: messages - (cons "^WARNING: .*$" font-lock-function-name-face) - - ;; SAS comments - ;; /* */ handled by grammar above - ;; (list "/\\*.*\\*/" 0 font-lock-comment-face t) - (cons "\\(^[0-9]*\\|;\\)[ \t]*\\(%?\\*\\|comment\\).*\\(;\\|$\\)" font-lock-comment-face) - - ;; SAS execution blocks, DATA/RUN, PROC/RUN, SAS Macro Statements - (cons "\\<%do[ \t]*\\(%until\\|%while\\)?\\>" - font-lock-constant-face) - ;;(cons (concat "\\(^[0-9]*\\|;\\)[ \t]*" - ;;"%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)" - ;;"\\>") font-lock-constant-face) - (cons "\\<%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)\\>" - font-lock-constant-face) - - (cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*" - "\\(data\\|endsas\\|finish\\|quit\\|run\\|start\\)[ \t\n;]") - font-lock-constant-face) - (cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*" - ;;"proc[ \t]+[a-z][a-z_0-9]+") font-lock-constant-face) - "proc[ \t]+" - ;;SAS/Base, SAS/Graph, SAS/FSP and common add-ons - "\\(append" - "\\|b\\(genmod\\|lifereg\\|phreg\\)" - "\\|c\\(a\\(lendar\\|talog\\)\\|port\\|o\\(mpare\\|ntents\\|py\\|rr\\)\\)" - "\\|d\\(atasets\\|bcstab\\|isplay\\)\\|ex\\(plode\\|port\\)" - "\\|f\\(orm\\(at\\|s\\)\\|req\\|s\\(browse\\|edit\\|l\\(etter\\|ist\\)\\|view\\)\\)" - "\\|g?\\(chart\\|p\\(lot\\|rint\\)\\)" - "\\|g\\(anno\\|contour\\|device\\|font\\|\\(key\\)?map\\|options\\|project" - "\\|re\\(duce\\|move\\|play\\)\\|slide\\|testit\\|3\\(d\\|grid\\)\\)" - "\\|\\(map\\|[cg]\\)?import\\|i\\(ml\\|nsight\\)" - "\\|means\\|options\\|p\\(menu\\|rintto\\)" - "\\|r\\(ank\\|e\\(gistry\\|port\\)\\)" - "\\|s\\(ort\\|ql\\|tandard\\|ummary\\)" - "\\|t\\(abulate\\|emplate\\|imeplot\\|ran\\(spose\\|tab\\)\\)\\|univariate" - ;;SAS/Stat and SAS/ETS - "\\|a\\(ceclus\\|nova\\|rima\\|utoreg\\)\\|boxplot" - "\\|c\\(a\\(lis\\|n\\(corr\\|disc\\)\\|tmod\\)\\|itibase\\|luster\\|o\\(mputab\\|rresp\\)\\)" - "\\|discrim\\|expand\\|f\\(a\\(ctor\\|stclus\\)\\|orecast\\|req\\)" - "\\|g\\(enmod\\|l\\(immix\\|m\\(mod\\|power\\|select\\)?\\)\\)\\|inbreed\\|k\\(de\\|rige2d\\)" - "\\|l\\(attice\\|ife\\(reg\\|test\\)\\|o\\(ess\\|gistic\\)\\)" - "\\|m\\(ds\\|ixed\\|o\\(de\\(clus\\|l\\)\\|rtgage\\)\\|ulttest\\)" - "\\|n\\(ested\\|l\\(in\\|mixed\\)\\|par1way\\)\\|orthoreg" - "\\|p\\(dlreg\\|hreg\\|l\\(an\\|s\\)\\|ower\\|r\\(in\\(comp\\|qual\\)\\|obit\\)\\)\\|r\\(sr\\)?eg" - "\\|s\\(core\\|im\\(2d\\|lin\\)\\|pectra\\|t\\(atespace\\|dize\\|epdisc\\)\\|urvey\\(means\\|reg\\|select\\)\\|yslin\\)" - "\\|t\\(phreg\\|pspline\\|r\\(ansreg\\|ee\\)\\|test\\)" - "\\|var\\(clus\\|comp\\|iogram\\)\\|x11" - "\\)") font-lock-constant-face) - - ;;(cons (concat "\\(^[0-9]*\\|;\\|%then\\|%else\\)[ \t]*" - ;;"\\(%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\)" - ;;"\\>") font-lock-constant-face) - (cons "\\<%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\>" - font-lock-constant-face) - - (cons "\\<%\\(by\\|else\\|t\\(o\\|hen\\)\\)\\>" - font-lock-constant-face) - - ;; SAS dataset options/PROC statements followed by an equal sign/left parentheses - - (cons (concat - "[ \t(,]" - "\\(attrib\\|by\\|compress\\|d\\(ata\\|rop\\)\\|f\\(irstobs\\|ormat\\)" - "\\|i\\(d\\|f\\|n\\)\\|ke\\(ep\\|y\\)\\|l\\(abel\\|ength\\)" - "\\|o\\(bs\\|rder\\|ut\\)\\|rename\\|s\\(ortedby\\|plit\\)" - "\\|var\\|where\\)" - "[ \t]*=") - font-lock-keyword-face) - (cons "\\<\\(in\\(:\\|dex[ \t]*=\\)?\\|until\\|wh\\(en\\|ile\\)\\)[ \t]*(" - font-lock-keyword-face) - - ;; SAS statements - (cons (concat - "\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*" - "\\(a\\(bort\\|rray\\|ttrib\\)\\|b\\(ayes\\|y\\)" - "\\|c\\(hange\\|lass\\|ontrast\\)" - "\\|d\\(elete\\|isplay\\|m\\|o\\([ \t]+\\(data\\|over\\)\\)?\\|rop\\)" - "\\|e\\(rror\\|stimate\\|xc\\(hange\\|lude\\)\\)" - "\\|f\\(ile\\(name\\)?\\|o\\(otnote\\(10?\\|[2-9]\\)?\\|rmat\\)\\|req\\)" - "\\|go\\([ \t]*to\\|ptions\\)" - "\\|hazardratio\\|[hv]bar\\(3d\\)?" - "\\|i\\(d\\|f\\|n\\(dex\\|f\\(ile\\|ormat\\)\\|put\\|value\\)\\)" - "\\|keep\\|l\\(abel\\|ength\\|i\\(bname\\|nk\\|st\\)\\|smeans\\)" - "\\|m\\(anova\\|e\\(ans\\|rge\\)\\|issing\\|od\\(el\\|ify\\)\\)\\|note" - "\\|o\\(ds\\|ptions\\|therwise\\|utput\\)\\|p\\(arms\\|lot2?\\|ut\\)" - "\\|r\\(andom\\|e\\(name\\|peated\\|tain\\)\\)" - "\\|s\\(ave\\|e\\(lect\\|t\\)\\|kip\\|trata\\|um\\(by\\)?\\)" - "\\|t\\(ables?\\|i\\(me\\|tle\\(10?\\|[2-9]\\)?\\)\\)\\|update" - "\\|va\\(lue\\|r\\)\\|w\\(eight\\|here\\|i\\(ndow\\|th\\)\\)" - - ;; IML statements that are not also SAS statements - "\\|append\\|c\\(lose\\(file\\)?\\|reate\\)\\|edit\\|f\\(ind\\|orce\\|ree\\)" - "\\|insert\\|load\\|mattrib\\|p\\(a[ru]se\\|rint\\|urge\\)" - "\\|re\\(move\\|peat\\|place\\|set\\|sume\\)" - "\\|s\\(et\\(in\\|out\\)\\|how\\|ort\\|tore\\|ummary\\)\\|use\\)?" - - "\\>") font-lock-keyword-face) - - - - ;; (cons "\\<\\(\\(then\\|else\\)[ \t]*\\)?\\(do\\([ \t]*over\\)?\\|else\\)\\>" - ;; font-lock-keyword-face) - - ;; SAS statements that must be followed by a semi-colon - (cons (concat - "\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*" - "\\(cards4?\\|datalines\\|end\\|l\\(ostcard\\)\\|page\\|stop\\)?" - "[ \t]*;") font-lock-keyword-face) - - ;; SAS/GRAPH statements not handled above - (cons (concat - "\\(^[0-9]*\\|):\\|[;,]\\)[ \t]*" - "\\(axis\\|legend\\|pattern\\|symbol\\)" - "\\([1-9][0-9]?\\)?\\>") font-lock-keyword-face) - - ;; SAS Datastep functions and SAS macro functions - ;(cons "%[a-z_][a-z_0-9]*[ \t]*[(;]" - ;; SAS macro functions occasionally defined with no arguments - ;; which means they can be followed by any character that can - ;; separate tokens, however, they are most likely to be followed - ;; by operat-ions/ors - (cons "%[a-z_][a-z_0-9]*[- \t();,+*/=<>]" - font-lock-function-name-face) - (cons "\\ (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))))) - - -;;(defun sas-indent-region (start end) -;; "Indent a region of SAS code." -;; (interactive "r") -;; (save-excursion -;; (let ((endmark (copy-marker end))) -;; (goto-char start) -;; (and (bolp) (not (eolp)) -;; (sas-indent-line)) -;; (indent-sexp endmark) -;; (set-marker endmark nil)))) - - -(defun indent-sas-statement (arg) - "Indent all continuation lines sas-indent-width spaces from first -line of statement." - (interactive "p") - (let (end) - (save-excursion - (if (> arg 0) - (while (and (> arg 0) (search-forward ";" (point-max) 1 1)) - (setq end (point)) - (if (bobp) nil (backward-char 1)) - (beginning-of-sas-statement 1) - (forward-char 1) - (indent-region (point) - end - (+ (current-column) (1- sas-indent-width))) - (search-forward ";" (point-max) 1 1) - (setq arg (1- arg))))))) - -;; added 9/31/94 -(defun sas-next-statement-indentation () - "Returns the correct indentation of the next sas statement. -The current version assumes that point is at the end of the statement. -This will (hopefully) be fixed in later versions." - (if (bobp) 0 - (save-excursion - (let ((prev-end (point))) - (beginning-of-sas-statement 1) - (while (and (not (bobp)) - (not (looking-at "\\*/")) - (looking-at sas-indent-ignore-comment)) - (skip-chars-backward sas-white-chars) - (if (bobp) nil - (backward-char 1)) - (setq prev-end (point)) - (beginning-of-sas-statement 1 t)) - (if (or - (looking-at - (concat "data[ \n\t;]\\|" - (regexp-opt '("cards;" "cards4;" "datalines;" "datalines4;" "lines;" "lines4;")) - "\\|proc[ \n\t]\\|%?do[ \n\t;]\\|%macro[ \n\t]\\|/\\*")) - (save-excursion - (re-search-forward - "\\b%?then\\>[ \n\t]*\\b%?do\\>\\|\\b%?else\\>[ \n\t]*\\b%?do\\>" - prev-end 1 1))) ; fixed 1/30/95 to avoid being fooled by - ; variable names starting with "do" - (+ (current-indentation) sas-indent-width) - (if (looking-at "%?end[ ;\n]\\|%mend[ ;\n]\\|\\*/") - (max (- (current-indentation) sas-indent-width) 0) - (current-indentation))))))) - -;; added 2/1/95 -(defun sas-comment-start-col () - "If the current line is inside a /* */ comment, returns column in which the -opening /* appears. returns 0 otherwise." - (let ((pos (point))) - (save-excursion - (if (and (search-backward "*/" (point-min) 1 1) - (search-forward "/*" pos 1 1)) - (current-indentation) - 0)))) - - -;; Created 6/27/94 to verify that RUN; statements match PROC and DATA -;; statements. Useful since indentation my be goofy w/o "RUN;" -(defun sas-check-run-statements () - "Check to see that \"run\" statements are matched with proc, data statements." - (interactive) - (let (pos - (ok t) - (eob-ok t)) - (save-excursion - (beginning-of-line) - (while ok - (if (re-search-forward - "\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)" - nil 1) - (if (match-beginning 2) - (if (re-search-forward - "\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)" - nil t) - (progn (setq pos (point)) - (setq ok (match-beginning 1))) - (setq eob-ok nil pos (point-max)))) - (setq ok nil))) - (setq ok (eobp))) - (if (and ok eob-ok) (message "Run statements match") - (goto-char pos) - (beep) - (message "Missing Run Statement.")))) - -(defun sas-fix-life-tables () - "Remove censored and duplicate observations from life tables generated by -Proc Lifetest. Operates on current region. A major space saver if there is -heavy censoring." - (interactive) - (if buffer-read-only (setq buffer-read-only nil)) - (goto-char (point-min)) - (while (re-search-forward "^.*[ ]+[.][ ]+[.][ ]+[.][ ]+.*$" nil t) - (replace-match "" nil nil))) - ; (save-excursion - ; (shell-command-on-region - ; start end - ; "sed '/[ ][.][ ]/d'" t))) -;;"sed \"\\? *\\. *\\. *\\. ?d\"" t))) -;;(vip-goto-line 1) -;;(setq ex-g-flag nil -;;ex-g-variant nil) -;;(vip-ex "1,$g/ \\. \\. \\. /d"))) - -(defun sas-fix-page-numbers (offset &optional page-num) - "Fix number of current page in sas output files after editing. Add -OFFSET to actual page number." - (interactive "P") - (if (not offset) (setq offset 0)) - (if (not page-num) (setq page-num (sas-page-number))) - (save-excursion - (if (/= (preceding-char) ?\C-l) (backward-page 1)) - (let (end len mstart mend) - (save-excursion - (forward-line sas-page-number-max-line) - (setq end (point))) - (if (re-search-forward - "\\(^[0-9]+[ ]\\)\\|\\([ ][0-9]+$\\)" - end t) - (progn (setq len (- (match-end 0) (match-beginning 0)) - mstart (match-beginning 0) - mend (match-end 0)) - (delete-region mstart mend) - (if (eolp) - (insert (format - (concat "%" len "d") (+ page-num offset))) - (insert (substring - (concat (+ (sas-page-number) offset) " ") - 0 len)))))))) - -(defun sas-page-fix (start) - "Fix page numbers in sas output from point to end of file. -If START is given this will be the number for the current page." - (interactive "P") - (let (offset (pnum (sas-page-number))) - (if (not start) (setq offset 0) - (setq offset (- start pnum))) - (while (not (eobp)) - (sas-fix-page-numbers offset pnum) - (setq pnum (1+ pnum)) - (forward-page 1)))) - -(defun fix-page-breaks () - "Fix page breaks in SAS 6 print files." - (interactive) - (save-excursion - (goto-char (point-min)) - (if (looking-at "\f") (delete-char 1)) - ;(replace-regexp "^\\(.+\\)\f" "\\1\n\f\n") - (while (re-search-forward "^\\(.+\\)\f" nil t) - (replace-match "\\1\n\f\n" nil nil)) - (goto-char (point-min)) - ;(replace-regexp "^\f\\(.+\\)" "\f\n\\1") - (while (re-search-forward "^\f\\(.+\\)" nil t) - (replace-match "\f\n\\1" nil nil)) - ; (goto-char (point-min)) - ;(replace-regexp " $" "") - ;(while (re-search-forward "$" nil t) - ; (replace-match "" nil nil)) - (goto-char (point-min)) - ;(replace-regexp " \\([^\\$]+\\)" "\n\\1") - (while (re-search-forward " \\([^\\$]+\\)" nil t) - (replace-match "\n\\1" nil nil)) - (goto-char (point-max)) - (if (not (bobp)) - (progn (backward-char 1) - (if (not (looking-at "\n")) - (progn (forward-char 1) (open-line 1))))))) - -(defun sas-page-number () - ;; like what-page except it returns an integer page number - "Return page number of point in current buffer." - (let ((opoint (point))) (save-excursion - (goto-char (point-min)) - (1+ (sas-how-many page-delimiter opoint))))) - -(defun sas-how-many (regexp &optional end) - ;; a copy of `how-many' which returns an integer - ;; rather than a message - "Return number of matches for REGEXP following point." - (let ((count 0) opoint) - (save-excursion - (while (and (not (eobp)) - (progn (setq opoint (point)) - (re-search-forward regexp end t))) - (if (= opoint (point)) - (forward-char 1) - (setq count (1+ count)))) - count))) - -(defun beginning-of-sas-proc () - "Move point to beginning of sas proc, macro or data step." - (interactive) - (let ((case-fold-search t)) - (forward-char -1) - (while (not (or (looking-at "data\\|proc\\|%macro") - (bobp))) - (re-search-backward "proc\\|data\\|%macro" (point-min) 1) - (beginning-of-sas-statement 1)))) - -(defun next-sas-proc (arg) - "Move point to beginning of next sas proc." - (interactive "P") - (let ((case-fold-search t)) - (forward-char 1) - (if (re-search-forward - "^[ \t]*\\(data[ ;]\\|proc[ ;]\\|endsas[ ;]\\|g?options[ ;]\\|%macro[ ;]\\)" - nil t arg) - (beginning-of-sas-statement 1) - (forward-char -1)))) - -(defun set-sas-file-name () - "Stores the name of the current sas file." - (let ((name (buffer-file-name))) - (cond ((not name)) - ((string-match (substring name -4 nil) - "\\.sas\\|\\.lst\\|\\.log") - - (setq sas-file-name (substring name 0 (- (length name) 4))) - (setq sas-buffer-name (buffer-name)) - (setq sas-file-root (substring sas-buffer-name 0 - (- (length sas-buffer-name) 4)))) - (t (message "This file does not have a standard suffix"))))) - -;; created 6/27/94 -(defun sas-set-alternate-file-name (name) - "Stores the NAME of an alternate sas file. -When this file is submitted with `submit-sas', the alternate file will -be submitted instead. `sas-submitable' is automatically sets to t." - (interactive "f") - (cond ((string-match (substring name -4 nil) - "\\.sas\\|\\.lst\\|\\.log") - (setq sas-file-name (substring name 0 (- (length name) 4))) - (setq sas-submitable t)) - (t (message "This file does not have a standard suffix")))) - -(defun switch-to-sas-source () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file "sas")) - -(defun switch-to-sas-lst () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file "lst")) - -(defun switch-to-sas-log () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file "log")) - -(defun switch-to-sas-source-other-window () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file-other-window "sas")) - -(defun switch-to-sas-lst-other-window () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file-other-window "lst")) - -(defun switch-to-sas-log-other-window () - "Switches to sas source file associated with the current file." - (interactive) - (switch-to-sas-file-other-window "log")) - -;;(defun switch-to-sas-file (suff &optional revert silent) -;; "Switches to sas \"SUFF\" file associated with the current file" -;; (let* ((sfile sas-file-name) -;; (buf (get-file-buffer (concat sfile "." suff))) -;; (sas-require-confirmation -;; (and sas-require-confirmation (not revert)))) -;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) -;; (find-file (concat sfile "." suff)) -;; (progn (switch-to-buffer buf) -;; (if (not (verify-visited-file-modtime (current-buffer))) -;; (progn (revert-buffer t t) -;; (if (not silent) -;; (message "File has changed on disk. Buffer automatically updated.")))))) -;; (setq sas-file-name sfile)) -;; (if (string-equal suff "sas") -;; (if (not (string-equal major-mode "sas-mode")) -;; (sas-mode)) -;; (if (not (string-equal major-mode "sasl-mode")) -;; (sasl-mode)))) -;; -;;(defun switch-to-sas-file-other-window (suff) -;; "Switches to sas \"SUFF\" file associated with the current file" -;; (let* ((sfile sas-file-name) -;; (buf (get-file-buffer (concat sfile "." suff)))) -;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) -;; (find-file-other-window (concat sfile "." suff)) -;; (progn (switch-to-buffer-other-window buf) -;; (if (not (verify-visited-file-modtime (current-buffer))) -;; (progn (revert-buffer t t) -;; (message "File has changed on disk. Buffer automatically updated."))))) -;; (setq sas-file-name sfile)) -;; (if (string-equal suff "sas") -;; (if (not (string-equal major-mode "sas-mode")) -;; ;;(sas-mode) -;; ) -;; (if (not (string-equal major-mode "sasl-mode")) -;; ;;(sasl-mode) -;; ))) - -(defun switch-to-sas-file (suff) - "Switches to sas \"SUFF\" file associated with the current file." - (switch-to-buffer (set-sas-file-buffer suff))) - -(defun switch-to-sas-file-other-window (suff) - "Switches to sas \"SUFF\" file associated with the current file." - (switch-to-buffer-other-window (set-sas-file-buffer suff))) - -;; The following was created 6/7/94 to handle buffers without messing up -;; windows. - -(defun set-sas-file-buffer (suff &optional revert silent) - "Sets current buffer to sas \"SUFF\" file associated with the current file." - (let* ((sfile sas-file-name) - (buf (get-file-buffer (concat sfile "." suff))) - (sas-require-confirmation - (and sas-require-confirmation (not revert)))) - (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) - (set-buffer (find-file-noselect (concat sfile "." suff))) - (progn (set-buffer buf) - (if (not (verify-visited-file-modtime (current-buffer))) - (progn (revert-buffer t t) - (if (not silent) - (message "File has changed on disk. Buffer automatically updated.")))))) - (setq sas-file-name sfile)) - ;;(if (string-equal suff "sas") - ;; (if (not (string-equal major-mode "sas-mode")) (sas-mode)) - ;; (if (not (string-equal major-mode "sasl-mode"))(sasl-mode)) - (current-buffer)) - -(defun switch-to-sas-process-buffer () - "Switch to sas-process-buffer." - (interactive) - (let (buf proc-name) - (setq proc-name (concat "SAS" sas-file-name) - buf (concat "*" proc-name "*")) - (switch-to-buffer-other-window buf))) - -(defun submit-sas () - ;; 6/17/94 added sas-submitable local variable. - "Submit SAS file as shell command." - (interactive) - (if ;; can file be run, or is it only for inclusion? - (or sas-submitable - (progn - (beep) - (y-or-n-p - (format - "Submission is disabled for this file. Submit it anyway? ")))) - (progn - ;; if buffer name has changed, tell user - (if (or - (string-equal sas-buffer-name (buffer-name)) - (not - (y-or-n-p - (format - "The name of this buffer has changed. Submit the new file? ")))) - (setq sas-buffer-name (buffer-name)) - (set-sas-file-name)) - (let ((sas-file sas-file-name) - (sas-root sas-file-root) - ;;(sas-buf sas-buffer-name) - proc-name - buf) - - ;; Save buffer to SAS the right file :-). - (if (buffer-modified-p) - (if (y-or-n-p (format "Buffer %s is modified. Save it? " - (buffer-name))) - (save-buffer))) - (setq proc-name (concat "SAS" sas-file) - buf (concat "*" proc-name "*")) - (if (get-buffer buf) - (save-window-excursion (switch-to-buffer buf) - (erase-buffer) - (setq default-directory - (file-name-directory sas-file)))) - - (run-hooks 'sas-pre-run-hook) ;; added 8/24/94 - (message "---- Submitting SAS job ----") - ;; (switch-to-buffer buf) - (make-comint proc-name - sas-program ;added sas-program 4/29/94 - nil - sas-root) - (save-window-excursion - (switch-to-buffer buf) - (setq sas-file-name sas-file) - (bury-buffer buf)) - - (message "---- SAS job submitted ---- ") - - (if sas-notify;; added 4/7/94 - (set-process-sentinel (get-process proc-name) 'sas-sentinel) - (display-buffer buf t)))) - (message "---- File not submitted ----"))) - -;; 5/2/94 Modified sas-sentinel to check for errors in log file upon -;; completion. -(defun sas-sentinel (proc arg);; created 4/7/94 - "Notify user that SAS run is done." - (beep) - ;;(if (string-equal arg "finished\n") - (save-excursion - (let (msg buf win (sbuf (concat "*" (process-name proc) "*"))) - (setq msg - (format "SAS %s %s" - (substring arg 0 -1) - (if sas-error-notify - ;;(save-window-excursion - (progn - (set-buffer sbuf) - (setq buf (set-sas-file-buffer "log" t t)) - (goto-char (point-min)) - (setq win (get-buffer-window buf)) - (save-window-excursion - (if win - (progn - (select-window win) - (if (re-search-forward "^ERROR" nil t) - " (See .log file for errors)" - "")) - (switch-to-buffer buf) - (if (re-search-forward "^ERROR" nil t) - " (See .log file for errors)" - "")))) - ""))) - (set-buffer sbuf) - (goto-char (point-max)) - (insert msg) - (bury-buffer (get-buffer sbuf)) - ;;(if (and sas-notify-popup window-system) - ;; (x-popup-dialog t - ;; (list "SAS Menu" (cons msg nil) ))) - ;;(if (not (minibuffer-window-active-p)) (princ msg)) - (princ msg)))) - -;; 5/2/94 Modified run-sas-on-region to separate log and output buffers. -;; -;;(defun run-sas-on-region (start end append &optional buffer) -;; "Submit region to SAS" -;; (interactive "r\nP") -;; (message "---- Running SAS ----") -;; (let ((sfile sas-file-name) -;; (shell-file-name "/bin/sh") -;; serror buff) -;; (setq buffer (or buffer "*SAS output*")) -;; (save-excursion -;; (shell-command-on-region -;; start end;; added sas-program -;; (concat sas-program " -nonews -stdio 2> /tmp/_temp_.log" nil)) -;; (get-buffer-create "*SAS Log*") -;; (save-window-excursion -;; (switch-to-buffer "*SAS Log*") -;; (erase-buffer) -;; (insert-file-contents "/tmp/_temp_.log") -;; (delete-file "/tmp/_temp_.log") -;; (setq serror (re-search-forward "^ERROR" nil t)) -;; (if serror () (bury-buffer))) -;; (setq buff (get-buffer-create buffer)) -;; (save-window-excursion -;; (switch-to-buffer buff) -;; (setq sas-file-name sfile) -;; (if append -;; (progn -;; (end-of-buffer) -;; (insert "\f\n")) -;; (erase-buffer)) -;; (if (get-buffer "*Shell Command Output*") -;; (progn (insert-buffer "*Shell Command Output*") -;; (kill-buffer "*Shell Command Output*")) -;; (insert "SAS completed with no output.")) -;; (if append () (sasl-mode)) -;; (message "---- SAS Complete ----"))) -;; (if (not serror) -;; (switch-to-buffer-other-window buff) -;; (switch-to-buffer-other-window "*SAS Log*") -;; (goto-char serror) -;; (beep) -;; (message "Error found in log file.") -;; ))) - -(defun switch-to-dataset-log-buffer () - "Switch to log buffer for run-sas-on-region." - (interactive) - (switch-to-buffer-other-window "*SAS Log*")) - -(defun switch-to-dataset-source-buffer () - "Switch to source buffer for run-sas-on-region." - (interactive) - (switch-to-buffer-other-window (format " *sas-tmp-%s*" sas-dataset))) - -;;(defun sas-get-dataset (filename &optional arg opts-p append buffer vars) -;; "Run proc contents and proc print on SAS dataset. Automatically prompts -;;for SAS options to use. Default options are defined by the variable -;;`sas-get-options'. Output may be updated from within output buffer with -;;C-cr if dataset changes. Also, the source code which generates the output -;;may be edited with C-cs. Typing C-cr within the output buffer reexecutes -;;the (modified) source code." -;; (interactive "fName of SAS dataset (file name):") -;; (let ((file (file-name-nondirectory filename)) -;; (dir (file-name-directory filename)) -;; (opts sas-get-options) -;; (minibuffer-history sas-get-options-history) -;; buf); fsize) -;; (setq buffer (or buffer (concat "*" file "*"))) -;; (setq opts (if opts-p opts (read-string "SAS options: " opts))) -;; (setq sas-get-options-history minibuffer-history) -;; (cond ((string-match (substring file -6 nil) "\\.ssd01") -;; (setq file (substring file 0 (- (length file) 6)))) -;; (t (error "This file is not a SAS dataset."))) -;; (setq buf (format " *sas-tmp-%s*" file)) -;; (get-buffer-create buf) -;; (save-window-excursion -;; (switch-to-buffer buf) -;; (erase-buffer) -;; (setq default-directory dir) -;; (if opts -;; (insert (format "options %s ;\n" opts))) -;; (insert (format "title \"Contents of SAS dataset `%s'\" ;\n" file)) -;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir)) -;; (if (not (equal arg 1)) -;; (insert (format "proc contents data = %s.%s ;\n" sas-tmp-libname file))) -;; (if (equal arg 2) () -;; (insert (format "proc print data = %s.%s ;\n" sas-tmp-libname file)) -;; (if vars (insert (format " var %s ;\n" vars)))) -;; (run-sas-on-region (point-min) (point-max) append -;; buffer) -;; (get-buffer buffer) -;; (if append () (sasd-mode)) ;; added 5/5/94 -;; (setq sas-dataset file)) -;; (if (get-buffer-window buffer t) -;; (raise-frame (window-frame (get-buffer-window buffer t))) -;; (display-buffer buffer (not append))) -;; )) - -;;(defun revert-sas-dataset () -;; "Revert current sas dataset from disk version" -;; (interactive) -;; (let* ((file sas-dataset) -;; (buf (format " *sas-tmp-%s*" file)) -;; (pos (point))) -;; (save-window-excursion -;; (switch-to-buffer buf) -;; (run-sas-on-region (point-min) (point-max) nil -;; (concat "*" file ".ssd01*")) -;; ) -;; (goto-char pos) ;; added 6/9/94 -;; (sasd-mode) ;; added 5/5/94 -;; (setq sas-dataset file))) - -(defun sas-insert-local-variables () ;; created 6/17/94 - "Add local variables code to end of sas source file." - (interactive) - (save-excursion - (if (re-search-forward "\\* *Local Variables: *;" nil t) - () - (goto-char (point-max)) - (insert " - -** Local Variables: ; -** End: ; -page ; -")))) - - - -;;-*-emacs-lisp-*- -;;; file name: sas-data.el -;;; -;;; Version 1.0 -;;; -;;; sas-data-mode: manage sas datasets -;;; Copyright (C) 1994 Tom Cook -;;; -;;; This program is free software; you can redistribute it and/or modify -;;; it under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 2 of the License, or -;;; (at your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; A copy of the GNU General Public License is available at -;;; https://www.r-project.org/Licenses/ -;;; -;;; Author: Tom Cook -;;; Dept. of Biostatistics -;;; University of Wisconsin - Madison -;;; Madison, WI 53706 -;;; cook@biostat.wisc.edu -;; Created: 8/11/94 - -;; variables section -(defvar sas-dir-mode-map nil) -(defvar-local sas-directory-name nil - "Name of directory associated with this buffer.") -(defvar-local sas-dir-buf-end nil) -(defvar-local sas-sorted-by-num nil) -;; user variables - -;; keymaps etc... - -(if sas-dir-mode-map () - (setq sas-dir-mode-map (make-sparse-keymap)) - ;;(define-key sas-dir-mode-map "c" 'sas-contents) - (define-key sas-dir-mode-map "p" 'sas-print) - (define-key sas-dir-mode-map "m" 'sas-mark-item) - (define-key sas-dir-mode-map "u" 'sas-unmark-item) - (define-key sas-dir-mode-map " " 'sas-next-line) - (define-key sas-dir-mode-map "\C-n" 'sas-next-line) - (define-key sas-dir-mode-map "\C-p" 'sas-prev-line) - (define-key sas-dir-mode-map "\177" 'sas-prev-line-undo) - (define-key sas-dir-mode-map "\C-b" 'sas-backward-page-narrow) - (define-key sas-dir-mode-map "\C-v" 'sas-forward-page-narrow) - (define-key sas-dir-mode-map "\C-m" 'sas-goto-dataset) - (define-key sas-dir-mode-map [mouse-2] 'sas-mouse-goto-dataset) - (define-key sas-dir-mode-map "t" 'sas-dir-goto-page) - (define-key sas-dir-mode-map "q" 'bury-buffer) - (define-key sas-dir-mode-map "g" 'sas-revert-library) - (define-key sas-dir-mode-map "1" 'digit-argument) - (define-key sas-dir-mode-map "2" 'digit-argument) - (define-key sas-dir-mode-map "3" 'digit-argument) - (define-key sas-dir-mode-map "4" 'digit-argument) - (define-key sas-dir-mode-map "5" 'digit-argument) - (define-key sas-dir-mode-map "6" 'digit-argument) - (define-key sas-dir-mode-map "7" 'digit-argument) - (define-key sas-dir-mode-map "8" 'digit-argument) - (define-key sas-dir-mode-map "9" 'digit-argument) - (define-key sas-dir-mode-map [menu-bar sas run] - '("Submit File " . submit-sas)) - ) - -(define-derived-mode sas-dir-mode special-mode "SAS" - "Major mode for managing sas files." - :group 'ess-sas - (setq sas-directory-name (expand-file-name default-directory))) - - -;;(defun sas-make-library (directory &optional update) -;; "Create a buffer with the names of all sas datasets from DIRECTORY." -;; (interactive "DDirectory Name: ") -;; (let ((dir (expand-file-name directory)) buf out cont pos) -;; (setq buf (format " *sas-tmp-%s*" dir)) -;; (setq out (concat "*SAS-dir-" dir)) -;; (setq cont (concat "*SAS-cont-" dir)) -;; (get-buffer-create buf) -;; (if (get-buffer out) -;; (if update -;; (progn -;; (set-buffer out) -;; (setq buffer-read-only nil))) -;; (setq update t)) -;; (pop-to-buffer out) -;; (setq default-directory dir) -;; (setq pos (point)) -;; (if update -;; (progn -;; (save-window-excursion -;; (set-buffer buf) -;; (erase-buffer) -;; (setq default-directory dir) -;; (insert "options linesize=70 pagesize=1000 ;\n") -;; (insert (format "title \"Contents of SAS directory `%s'\" ;\n" -;; dir)) -;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir)) -;; (insert (format "proc contents data = %s._all_ directory details memtype=data ;\n" sas-tmp-libname)) -;; (run-sas-on-region (point-min) (point-max) nil -;; out) -;; (set-buffer out) -;; (goto-char (point-min)) -;; (if (= (sas-how-many page-delimiter (point-max)) 0) -;; (let ((buffer-read-only nil)) -;; (erase-buffer) -;; (insert "There are no SAS datasets in this directory") -;; (pop-to-buffer out)) -;; (save-excursion -;; (set-buffer (get-buffer-create cont)) -;; (setq buffer-read-only t) -;; (let ((buffer-read-only nil)) -;; (erase-buffer) -;; (insert-buffer out) -;; (delete-region (point-min) -;; (or (re-search-forward page-delimiter nil t) -;; (point-min))) -;; (sas-page-fix 1) -;; (goto-char (point-min)) -;; (sas-dir-mode) -;; (sas-narrow-to-page))) -;; (if (re-search-forward page-delimiter nil t) -;; (delete-region (progn (beginning-of-line) (point)) -;; (point-max))) -;; (sas-insert-set-properties (point-min) (point-max)) -;; ) -;; (switch-to-buffer out t) -;; (goto-char (point-min)) -;; (sas-dir-mode) -;; (setq sas-dir-buf-end (point-max))) -;; (goto-char pos) -;; (sas-move-to-filename (point-max)))))) - - -(defun sas-move-to-filename (&optional eol) - (or eol (setq eol (progn (end-of-line) (point)))) - (beginning-of-line) - (if (re-search-forward "\\(^ *[0-9]+ *<*\\)[^:0-9\n]" eol t) - (goto-char (match-end 1)))) - -(defun sas-next-line (arg) - "Move down one line." - (interactive "p") - (forward-line arg) - (sas-move-to-filename (point-max))) -;;(and (< (point) sas-dir-buf-end) -;;(forward-line arg) -;;(sas-move-to-filename sas-dir-buf-end))) - -(defun sas-prev-line (arg) - "Move up one line." - (interactive "p") - (beginning-of-line) - (re-search-backward "^ *[0-9]+ *<*[^:0-9\n]" (point-min) t) - (sas-move-to-filename sas-dir-buf-end)) - -(defun sas-insert-set-properties (beg end) - (save-excursion - (goto-char beg) - (while (< (point) end) - (if (sas-move-to-filename) - (put-text-property (point) - (+ 8 (point)) - 'mouse-face 'highlight)) - (forward-line 1)))) - -(defun sas-get-filename () - "Return name of dataset on current line." - (interactive) - (save-excursion - (if (string-equal "*SAS-dir" (substring (buffer-name) 0 8)) - (sas-move-to-filename) - (goto-char (point-min)) - (re-search-forward "Data Set Name: [^.]*\\.")) - (expand-file-name - (downcase (concat sas-directory-name - (buffer-substring - (point) - (save-excursion - (skip-chars-forward "A-Z0-9_") - (point))) ".ssd01"))))) - -(defun sas-get-file-number () - "Return name of dataset on current line." - (interactive) - (if (sas-move-to-filename) - (progn (forward-word -1) - (re-search-forward "[0-9]*") - (string-to-number - (buffer-substring (match-beginning 0) - (match-end 0)))))) - -;;(defun sas-contents () -;; "Run proc contents on current file." -;; (interactive) -;; (let ((buffer-read-only nil) (sas-get-options "linesize=70")) -;; (sas-get-dataset (sas-get-filename) 2 t t (buffer-name)) -;; (end-of-buffer) -;; (backward-page-top-of-window 1))) -;; -;;(defun sas-print () -;; "Run proc contents on current file." -;; (interactive) -;; (sas-get-dataset (sas-get-filename) 1 nil nil nil -;; (sas-create-var-string))) - -(defun sas-goto-page (arg) - "Goto top of page ARG. If no ARG, then goto top of file." - (interactive "P") - (goto-char 1) - (if arg - (if (> arg 1) - (progn - (re-search-forward page-delimiter (point-max) 1 (1- arg))))) - (skip-chars-forward sas-white-chars); was " \f\n" till 5.1.13 - (recenter 1)) - -(defun forward-page-top-of-window (arg) - "Move forward to page boundary and leave first line at top of window. -With arg, repeat, or go back if negative. A page boundary is any line -whose beginning matches the regexp `page-delimiter'." - (interactive "p") - (forward-page arg) - (recenter 0)) - -(defun backward-page-top-of-window (arg) - "Move backward to page boundary and leave first line at top of window. -With arg, repeat, or go back if negative. A page boundary is any line -whose beginning matches the regexp `page-delimiter'." - (interactive "p") - (forward-page (- arg)) - (recenter 0)) - -(defun sas-narrow-to-page () - (save-excursion - (let* ((min (point-min)) - (max (point-max))) - ;;(omin (point-min)) - ;;(omax (point-max))) - (if (or (bolp) (beginning-of-line) - (looking-at page-delimiter)) - (forward-char 1) - (forward-page -1)) - (setq min (point)) - (forward-page 1) - (beginning-of-line) - (setq max (point)) - (narrow-to-region min max)))) - -(defun sas-forward-page-narrow (arg) - "Move forward to page boundary and narrow to page. -With arg, repeat, or go back if negative. A page boundary is any line -whose beginning matches the regexp `page-delimiter'." - (interactive "p") - (widen) - (forward-page arg) - (sas-narrow-to-page) - (goto-char (point-min))) - -(defun sas-backward-page-narrow (arg) - "Move backward to page boundary and narrow to page. -With arg, repeat, or go back if negative. A page boundary is any line -whose beginning matches the regexp `page-delimiter'." - (interactive "p") - (goto-char (point-min)) - (widen) - (forward-page (- arg)) - (sas-narrow-to-page)) - -(defun sas-goto-dataset (&optional page) - (interactive) - (and sas-directory-name - (let ((page (or page (sas-get-file-number)))) - ;;(dir sas-directory-name)) - (if page - (progn - (switch-to-buffer-other-window - (concat "*SAS-cont-" sas-directory-name)) - (widen) - (sas-goto-page page) - (sas-narrow-to-page) - (goto-char (point-min))))))) - -;;(defun sas-mouse-goto-dataset (event) -;; (interactive "e") -;; (let (page buf) -;; (save-window-excursion -;; (save-excursion -;; (set-buffer (window-buffer (posn-window (event-end event)))) -;; (save-excursion -;; (goto-char (posn-point (event-end event))) -;; (setq page (sas-get-file-number))) -;; (sas-goto-dataset page) -;; (setq buf (buffer-name)))) -;; (set-buffer buf) -;; (goto-char (point-min)) -;; (display-buffer buf))) - - -(defun sas-dir-goto-page (page) - (interactive "p") - (widen) - (sas-goto-page page) - (sas-narrow-to-page)) - -(defun sas-mark-item (&optional next) - (interactive) - (sas-move-to-filename) - (beginning-of-line) - (let ((buffer-read-only nil)) - (if (re-search-forward "^\\( *[0-9]+ *\\) \\([A-Z][A-Z_0-9]*\\) " - (save-excursion (end-of-line) (point)) t) - (replace-match "\\1<\\2>"))) - (or next (sas-next-line 1))) - -(defun sas-unmark-item () - (interactive) - (save-excursion - (beginning-of-line) - (let ((buffer-read-only nil)) - (if (re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>" - (save-excursion (end-of-line) (point)) t) - (replace-match "\\1 \\2 "))))) - -(defun sas-prev-line-undo (arg) - (interactive "p") - (sas-prev-line arg) - (sas-unmark-item) - (sas-move-to-filename)) - -(defun sas-create-var-string () - (and (string-equal "*SAS-cont" (substring (buffer-name) 0 9)) - (let (str) - (goto-char (point-min)) - (while - (re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>" - nil t) - (setq str (concat str " " (buffer-substring (match-beginning 2) - (match-end 2))))) - str))) - - -(defun ess-imenu-SAS (&optional arg) - "SAS language Imenu support for ESS." - (interactive) - (setq imenu-generic-expression - '( (nil "[ \t\n=]\\([a-zA-Z_][a-zA-Z_0-9]*[.][a-zA-Z_][a-zA-Z_0-9]*\\)[ ,()\t\n;]" 1))) - (imenu-add-to-menubar "SAS Datasets")) - -;;(defun sas-revert-library () -;; "Update current library." -;; (interactive) -;; (if sas-directory-name -;; (sas-make-library sas-directory-name t))) - -(provide 'ess-sas-l) - -;;; ess-sas-l.el ends here diff --git a/elpa/ess-20191014.1343/ess-site.el b/elpa/ess-20191014.1343/ess-site.el deleted file mode 100644 index 917bc906..00000000 --- a/elpa/ess-20191014.1343/ess-site.el +++ /dev/null @@ -1,71 +0,0 @@ -;;; ess-site.el --- user customization of ESS -*- lexical-binding: t; -*- - -;; Copyright (C) 1993 David M. Smith -;; Copyright (C) 1997--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2018 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, Stephen Eglen, -;; Vitalie Spinu, and Lionel Henry. - -;; Author: David Smith -;; Created: 12 Nov 1993 -;; Maintainer: ESS-core -;; Keywords: local - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Load path, autoloads, and major modes -;; ======================================== -;; -;; This file defines all the site-specific customizations for ESS. It should be -;; edited on a per-site basis. users who wish to use ESS should add the path to -;; ess-site to their `load-path' and require it: -;; -;; (add-to-list 'load-path "/path/to/ess/lisp-directory");; -;; (require 'ess-site) -;; -;; For most users the variable ess-lisp-directory will automatically be set -;; correctly. If you are working with an old Emacs, one in which file-truename -;; is not defined, then you might need to change the value of ess-lisp-directory -;; to the directory which is to contain the file ess-site.elc. This is probably -;; the current directory, or the value of LISPDIR if it was set in the Makefile. -;; -;; Debug startup: (setq ess-show-load-messages t) - -;;; Code: - -(when load-file-name - ;; Modify this if ess-site.el is not in the ./lisp/ directory - (defvar ess-lisp-directory (file-name-directory load-file-name) - "Directory containing ess-site.el(c) and other ESS Lisp files.") - (add-to-list 'load-path ess-lisp-directory)) - -;;; Loading popular dialects (they should become optional in the future) - -(require 'ess-r-mode) -(require 'ess-julia) -(require 'essd-els) ;; ess-remote -(require 'ess-stata-mode) -(require 'ess-sas-d) -(require 'ess-bugs-d) -(require 'ess-jags-d) -(require 'ess-toolbar) - -(provide 'ess-site) - -;;; ess-site.el ends here diff --git a/elpa/ess-20191014.1343/ess-sp6-d.el b/elpa/ess-20191014.1343/ess-sp6-d.el deleted file mode 100644 index a90ecd0c..00000000 --- a/elpa/ess-20191014.1343/ess-sp6-d.el +++ /dev/null @@ -1,198 +0,0 @@ -;;; ess-sp6-d.el --- S-Plus 6 & 7 & 8 customization - -;; Copyright (C) 2001--2005 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: A.J. Rossini -;; Created: 2001/02/06 -;; Maintainer: ESS Core Team - -;; Keywords: languages - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; AJR copied S+5 to be S+6. -;; AJR copied S4 to be S+5. -;; DB contributed the changes from ess-sp3-d.el to -;; ess-s4-d.el. (removed the old ugly approach). -;; This file defines Sp5 customizations for ess-mode. Lots of thanks -;; to RMH and JMC for code and suggestions -;; Thanks to MM for making this sensible. - -;;; Code: - -(require 'ess-mode) -(require 'ess-inf) -(require 'ess-s-lang) -(require 'ess-trns) - - -;; You now need to make sure you've defined if you are running 5.0 or 5.1. -;; Lots of things are broken between them, GRR... - -(defun S+-directory-p (directory) - "Splus 5++ directories have a .Data directory and a __Meta directory within." - (and directory - (file-directory-p (concat directory ".Data")) - (file-directory-p (concat directory ".Data/__Meta")))) - -(defvar S+-directory-function #'inferior-ess-default-directory) - -(defvaralias 'S+6-setup-directory-function 'S+-setup-directory-function) -(defvar S+-setup-directory-function - (lambda (startdir) - (when (and startdir (S+-directory-p startdir)) - (setenv "S_WORK" - (if (getenv "S_WORK") - (concat startdir ":" (getenv "S_WORK")) - ;;(message "adding %s to S_WORK" startdir) - startdir))))) - - - -(defvaralias 'S+6-customize-alist 'S+-customize-alist) -(defvar S+-customize-alist - (append - '((ess-local-customize-alist . 'S+-customize-alist) - (ess-dialect . S+-dialect-name) - (ess-function-pattern . ess-r-function-pattern) - - (ess-object-name-db-file . "ess-sp6-namedb.el") - (inferior-ess-program . inferior-S+-program) - (inferior-ess-help-command . "help(\"%s\", pager=\"slynx -dump\", window=FALSE)\n") - (inferior-ess-search-list-command . "searchPaths()\n") - - (ess-directory-function . S+-directory-function) - (ess-setup-directory-function . S+-setup-directory-function) - (ess-STERM . "iESS")) - S+common-cust-alist) - - "Variables to customize for S+.") - -(defvar ess-S+-post-run-hook nil - "Functions run in process buffer after the initialization of S+ - process.") - -(defvar ess-S+--injected-code - ".ess_funargs <- function(funname){ - ## funname <- deparse(substitute(object)) - fun <- try(eval(parse(text=funname)), silent = TRUE) - if(is.function(fun)) { - special <- grepl('[:$@[]', funname) - args <- args(fun) - fmls <- formals(args) - fmls.names <- names(fmls) - fmls <- gsub('\\\"', '\\\\\\\"', as.character(fmls), fixed = TRUE) - args.alist <- sprintf(\"'(%s)\", paste(\"(\\\"\", fmls.names, \"\\\" . \\\"\", fmls, \"\\\")\", sep = '', collapse = ' ')) - ## envname <- environmentName(environment(fun)) - envname <- if (special) '' else 'S+' - cat(sprintf('(list \\\"%s\\\" %s )\\n', envname, args.alist)) - } -} -") - -(defalias 'S+6 'S+) -(defun S+ (&optional proc-name) - "Call 'Splus6', based on S version 4, from Bell Labs. -New way to do it." - (interactive) - (ess-write-to-dribble-buffer - (format "\n(S+): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer))) - (let ((inf-buf (inferior-ess nil S+-customize-alist))) - (ess-command ess-S+--injected-code) - (when inferior-ess-language-start - (ess-eval-linewise inferior-ess-language-start)) - (with-current-buffer inf-buf - (run-mode-hooks 'ess-S+-post-run-hook)) - inf-buf)) - - -(defalias 'S+6-mode 'S+-mode) -;;;###autoload -(defun S+-mode (&optional proc-name) - "Major mode for editing S+ source. See `ess-mode' for more help." - (interactive) - (setq-local ess-local-customize-alist S+-customize-alist) - (ess-mode) - (if (fboundp 'ess-add-toolbar) (ess-add-toolbar)) - (setq imenu-generic-expression ess-imenu-S-generic-expression) - (when ess-imenu-use-S (imenu-add-to-menubar "Imenu-S"))) - -(defalias 'S+6-transcript-mode 'S+-transcript-mode) -(define-derived-mode S+-transcript-mode ess-transcript-mode "ESS S Transcript" - "S-PLUS 6 transcript mode." - :syntax-table S-syntax-table - :group 'ess-S) - -(defvar ess-s-versions '("Splus") - "List of partial strings for versions of S to access within ESS. -Each string specifies the start of a filename. If a filename -beginning with one of these strings is found on `exec-path', a M-x -command for that version of S is made available. For example, if the -file \"Splus7\" is found and this variable includes the string -\"Splus\", a function called `M-x Splus7' will be available to run that -version of S. -If duplicate versions of the same program are found (which happens if -the same path is listed on `exec-path' more than once), they are -ignored by calling `delete-dups'. -Set this variable to nil to disable searching for other versions -of S using this method. -If you set this variable, you need to restart Emacs (and set this variable -before ess-site is loaded) for it to take effect.") -(define-obsolete-variable-alias - 'ess-s-versions-created 'ess-s-created-runners "ESS 18.10") -(defvar ess-s-created-runners) -(defun ess-s-define-runners () - "Generate functions for starting other versions of S. -See `ess-s-versions' for strings that determine which functions are created. -It assumes these versions of S can be run as a substitute for Splus6. - -This function returns the list of functions, if any, that were -created. The functions will normally be placed on the menubar upon -ESS initialization." - (when ess-s-versions - (let ((versions - (delete-dups - (mapcar #'file-name-nondirectory - (apply #'nconc - (mapcar #'ess-find-exec-completions - ess-s-versions)))))) - ;; Iterate over each string in VERSIONS, creating a new defun - ;; each time. - (setq ess-s-created-runners - (mapc (lambda (v) (ess-define-runner v "S")) versions)) - ;; Add to menu - (when ess-s-created-runners - ;; new-menu will be a list of 3-vectors, of the form: - ;; ["R-1.8.1" R-1.8.1 t] - (let ((new-menu (mapcar (lambda (x) (vector x (intern x) t)) - ess-s-created-runners))) - (easy-menu-add-item ess-mode-menu '("Start Process") - (cons "Other" new-menu))))))) -;; Define the runners -(ess-s-define-runners) -(define-obsolete-function-alias - 'ess-s-versions-create 'ess-s-define-runners "ESS 18.10") - - - - ; Provide package - -(provide 'ess-sp6-d) - -;;; ess-sp6-d.el ends here diff --git a/elpa/ess-20191014.1343/ess-stata-lang.el b/elpa/ess-20191014.1343/ess-stata-lang.el deleted file mode 100644 index a3360b53..00000000 --- a/elpa/ess-20191014.1343/ess-stata-lang.el +++ /dev/null @@ -1,1219 +0,0 @@ -;;; ess-stata-lang.el --- Stata customization -*- lexical-binding: t; -*- - -;; Copyright (C) 1999--2000, Thomas Lumley, A. J. Rossini, Brendan Halpin. -;; Copyright (C) 1997--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Thomas Lumley , -;; Brendan Halpin -;; Created: 2 Nov 1997 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS (Emacs Speaks Statistics). - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This is based upon Version 0.4 of Stata mode. - -;; Stata modes. Emacs modes for using the Stata statistical package -;; Modified from S-mode, comint-mode -;; -;; (c) Thomas Lumley 1997 -;; -;; version 0.4 20/7/97 -;; -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; (for the GNU GPL see above) - - -;;; Code: - -(declare-function ess-help-mode "ess-help") - -(require 'make-regexp) ; it's now local to the directory. -;;(load-library "make-regexp") ;; this is necessary for -;; ado-set-font-lock-keywords -;; only needed in Emacs >= 22.x -(require 'comint) -(require 'ess-trns) - -(defconst ess-help-STA-sec-keys-alist - '((?d . "Description") - (?e . "Examples") - (?o . "Options") - (?s . "Also see") - (?S . "Syntax") - (?r . "Remarks") - (?t . "Title")) - "Help section keys. -`key' indicates the keystroke to use to search for the section heading -`string' in an Stata help file. `string' is used as part of a -regexp-search, and so specials should be quoted. -") - -(defconst ess-help-STA-sec-regex "^[A-Z a-z]+:?\n-+\\|http:" - "Reg(ular) Ex(pression) of section headers in help file.") - -(defun ado-set-font-lock-keywords () - "Create font lock keywords for Stata syntax. This is from the -ado-mode of Bill Rising , and uses make-regexp." - ;; (make-local-variable 'ado-font-lock-keywords) - (interactive) - (list - ;; special highlighting - ;; program definitions - (eval-when-compile - (make-regexps - '(("^\\*!.*") font-lock-keyword-face) - )) - (eval-when-compile - (make-regexps - "^" - '(( - "pr" "pro" "prog" "progr" "progra" "program" - ) font-lock-keyword-face) - "[ \t]+" - '(( - "de" "def" "defi" "defin" "define" - "di" "dir" - "drop" - "l" "li" "lis" "list" - ) font-lock-type-face nil) - "[ \t]+" - '(("[_a-z]+[_a-z0-9]*") font-lock-keyword-face nil) - )) - (eval-when-compile - (make-regexps - '(("^[ \t]*version") font-lock-reference-face) - "[ \t]*" - '(("1.0 2.0 2.1 3.0 3.1 4.0 5.0 6 6.0") font-lock-type-face) - )) - (eval-when-compile - (make-regexps - "^" - '(("end" "pause" - ) font-lock-keyword-face) - "[ /t]*.*$" - )) - ;; delimit command - (eval-when-compile - (make-regexps - '(("^[ \t]*#delimit") font-lock-reference-face) - "\\s-*" - '(("\\(cr\\|;\\)\\s-*$") font-lock-type-face nil) - )) - ;; set command (with endless options!) - (eval-when-compile - (make-regexps - '(("^[ \t]*set") font-lock-reference-face) - "[ \t]+" - '(("adosize" "ANSI" - "b" "be" "bee" "beep" "checksum" "contents" - "d" "di" "dis" "disp" "displ" "displa" "display" - "g" "gr" "gra" "grap" "graph" "graphi" "graphic" "graphics" - "help" - "IBM" - "l" "le" "lev" "leve" "level" - "linesize" - "lo" "log" - "mat" "mats" "matsi" "matsiz" "matsize" - "maxobs" "maxvar" - "mem" "memo" "memor" "memory" - "mo" "mor" "more" - "obs" - "ou" "out" "outp" "outpu" "output" - "pagesize" - "r" "rm" "rms" "rmsg" - "se" "see" "seed" "seed0" "shell" - "te" "tex" "text" "texts" "textsi" "textsiz" "textsize" - "tr" "tra" "trac" "trace" - "t" "ty" "typ" "type" "video" - "vir" "virt" "virtu" "virtua" "virtual" - ) - font-lock-reference-face t) - "[ \t]*" - '(("[a-zA-Z0-9]*") font-lock-type-face) - )) - ;; the constraint commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "cons" "const" "constr" "constra" "constrai" "constrain" "constraint" - ) font-lock-reference-face) - "[ \t]+" - '(( - "d" - "de" "def" "defi" "defin" "define" - "di" "dir" - "drop" - "l" "li" "lis" "list" - ) - font-lock-type-face) - "\\b" - )) - ;; the confirm commands - could be a mess! - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "conf" "confi" "confir" "confirm" - ) font-lock-reference-face) - "[ \t]+" - '(( - "e" "ex" "exi" "exis" "exist" "existe" "existen" "existenc" "existence" - "f" "fi" "fil" "file" - "n" "nu" "num" "numb" "numbe" "number" - "v" "va" "var" "vari" "varia" "variab" "variabl" "variable" - ) font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "conf" "confi" "confir" "confirm" - ) font-lock-reference-face) - "[ \t]+" - '(( - "integer" - ) font-lock-type-face) - "[ \t]+" - '(( - "n" "nu" "num" "numb" "numbe" "number" - ) font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "conf" "confi" "confir" "confirm" - ) font-lock-reference-face) - "[ \t]+" - '(( - "n" "ne" "new" - ) font-lock-type-face) - "[ \t]+" - '(( - "f" "fi" "fil" "file" - "v" "va" "var" "vari" "varia" "variab" "variabl" "variable" - ) font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "conf" "confi" "confir" "confirm" - ) font-lock-reference-face) - "[ \t]+" - '(( - "byte" "double" "float" "int" "long" - "numeric" - "str" "stri" "strin" "string" - ) font-lock-type-face) - "[ \t]+" - '(( - "v" "va" "var" "vari" "varia" "variab" "variabl" "variable" - ) font-lock-type-face) - "\\b" - )) - ;;; the str# won't quite look right, but that's the breaks for using - ;;; a tool like this... - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "conf" "confi" "confir" "confirm" - ) font-lock-reference-face) - "[ \t]+" - '(( - "str" - ) font-lock-type-face) - "[1-9]+[0-9]*[ \t]+" - '(( - "v" "va" "var" "vari" "varia" "variab" "variabl" "variable" - ) font-lock-type-face) - "\\b" - )) - ;; the estimates commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "est" "esti" "estim" "estima" "estimat" "estimate" "estimates" - ) font-lock-reference-face) - "[ \t]+" - '(( - "clear" - "di" "dir" "dis" "disp" "displ" "displa" "display" - "drop" - "h" "ho" "hol" "hold" - "li" "lis" "list" - "loc" "loca" "local" - "mat" "matr" "matri" "matrix" - "post" - "repost" - "sca" "scal" "scala" "scalar" - "u" "un" "unh" "unho" "unhol" "unhold" - ) - font-lock-type-face) - "\\b" - )) - ;; the gph commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "gph" - ) font-lock-reference-face) - "[ \t]+" - '(( - "arc" - "box" - "clear" "close" - "font" - "line" - "open" - "pen" "point" - "text" - "vline" "vpoint" "vpoly" "vtext" - ) - font-lock-type-face) - "\\b" - )) - - ;; some of the matrix commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("mat" "matr" "matri" "matrix") font-lock-reference-face) - "[ \t]+" - '(("ac" "acc" "accu" "accum" - "cole" "coleq" - "coln" "colna" "colnam" "cloname" "colnames" - "d" "def" "defi" "defin" "define" - "di" "dir" "dispCns" "drop" "drop _all" - "glsa" "glsac" "glsacc" "glsaccu" "glsaccum" - "l" "li" "lis" "list" "makeCns" "mlou" "mlout" "post" - "rowe" "roweq" - "rown" "rowna" "rownam" "rowname" "rownames" - "sco" "scor" "score" - "sub" "subs" "subst" "substi" "substit" "substitu" "substitut" "substitute" - "svd" "syme" "symei" "symeig" "symeige" "symeigen" - "veca" "vecac" "vecacc" "vecaccu" "vecaccum" - ) - font-lock-type-face) - "\\b" - )) - ;; the ml commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("ml") font-lock-reference-face) - "[ \t]+" - '(("b" "be" "beg" "begi" "begin" - "check" "count" - "de" "dep" "depn" "depna" "depnam" "depname" "depnames" - "di" "dis" "disp" "displ" "displa" "display" - "f" "fu" "fun" "func" "funct" "functi" "functio" "function" - "gr" "gra" "grap" "graph" - "init" - "max" "maxi" "maxim" "maximi" "maximiz" "maximize" - "me" "met" "meth" "metho" "method" - "ml" "mlo" "mlou" "mlout" - "mo" "mod" "mode" "model" - "pl" "plo" "plot" - "po" "pos" "post" - "q" "qu" "que" "quer" "query" - "re" "rep" "repo" "repor" "report" - "sa" "sam" "samp" "sampl" "sample" - "se" "sea" "sear" "searc" "search" - "trace") - font-lock-type-face) - "\\b" - )) - ;; the net commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("net") font-lock-reference-face) - "[ \t]+" - '(( - "cd" - "d" "de" "des" "desc" "descr" "descri" "describ" "describe" - "from" "get" "install" - "link" - "q" "qu" "que" "quer" "query") - font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(("net") font-lock-reference-face) - "[ \t]+" - '(("set") font-lock-reference-face) - "[ \t]+" - '(("ado" "other") font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(("ado") font-lock-reference-face) - "[ \t]+" - '(("d" "de" "des" "desc" "descr" "descri" "describ" "describe" - "dir" - "uninstall") - font-lock-type-face) - "\\b" - )) - ;; the reshape commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("reshape") font-lock-keyword-face) - "[ \t]+" - '(( - "clear" - "error" - "i" "j" - "long" - "wide" - "xi" "xij") - font-lock-type-face) - "\\b" - )) - ;; the return commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("ret" "retu" "retur" "return") font-lock-reference-face) - "[ \t]+" - '(("add" "clear" "local" "matrix" "scalar") font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(("sret" "sretu" "sretur" "sreturn") font-lock-reference-face) - "[ \t]+" - '(("clear" "local") font-lock-type-face) - "\\b" - )) - ;; the sts commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("sts") font-lock-reference-face) - "[ \t]+" - '(( - "g" - "gen" "gene" "gener" "genera" "generat" "generate" - "gr" "gra" "grap" "graph" - "l" "li" "lis" "list" - "t" "te" "tes" "test" - ) - font-lock-type-face) - "\\b" - )) - ;; the sw commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(("sw") font-lock-reference-face) - "[ \t]+" - '(( - "cloglog" "cnreg" "cox" "ereg" "gamma" "glm" "gompertz" "hetprob" - "llogist" "lnormal" "logistic" "logit" "ologit" "oprobit" - "poisson" "probit" "qreg" "reg" "regr" "regre" "regres" "regress" - "scobit" "tobit" "weibull" - ) - font-lock-type-face) - "\\b" - )) - ;; the window commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "win" "wind" "windo" "window" - ) font-lock-reference-face) - "[ \t]+" - '(( - "d" - "di" "dia" "dial" "dialo" "dialog" - "dir" "drop" - "fo" "fop" "fope" "fopen" - "fs" "fsa" "fsav" "fsave" - "l" "list" - "push" - "stop" "stopb" "stopbo" "stopbox" - ) font-lock-type-face) - "\\b" - )) - ;; the window controls - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "win" "wind" "windo" "window" - ) font-lock-reference-face) - "[ \t]+" - '(( - "c" "co" "con" "cont" "contr" "contro" "control" - ) font-lock-reference-face) - '(( - "button" "check" "clear" - "edit" - "mcombo" "msimple" - "radbegin" - "radend" - "radio" - "scombo" - "ssimple" - "static" - ) font-lock-type-face) - "\\b" - )) - ;; the window manage commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "win" "wind" "windo" "window" - ) font-lock-reference-face) - "[ \t]+" - '(( - "man" "mana" "manag" "manage" - ) font-lock-reference-face) - "[ \t]+" - '(( - "forward" - "minimize" - "prefs load" - "prefs save" - "prefs default" - "print graph" - "print log" - "restore" - "update variable" - ) - font-lock-type-face) - "\\b" - )) - ;; the window menu commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "win" "wind" "windo" "window" - ) font-lock-reference-face) - "[ \t]+" - '(( - "m" "me" "men" "menu" - ) font-lock-reference-face) - "[ \t]+" - '(( - "append popout" - "append string" - "append separator" - "clear" - "popout" - "set" - ) - font-lock-type-face) - "\\b" - )) - ;; the xwindow commands - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "xwin" "xwind" "xwindo" "xwindow" - ) font-lock-reference-face) - "[ \t]+" - '(( - "de" "def" "defi" "defin" "define" - "di" "dir" - "drop" - "l" "li" "lis" "list" - ) - font-lock-type-face) - "\\b" - )) - - ;; all the endless Stata keywords (not in a good order) - ;; first those keywords which must start line - ;; note that these will look like text if preceded by a comment - ;; (but comments shouldn't be before the command, anyway) - - (eval-when-compile - (make-regexps - "^[ \t]+" - '(( - "cap" "capt" "captu" "captur" "capture" - "char" "err" "erro" "error" "e" "ex" "exi" "exit" - "par" "pars" "parse" - "set" - ) font-lock-reference-face) - "\\b" - )) - ;; here are some keywords which appear in the middle of lines - ;; note that the really short abbreviations could make a mess of things - ;; - ;; These are split to allow compiling! - (eval-when-compile - (make-regexps - "\\b" - '(( - "_huber" "_qreg" "_robust" - "acprplot" "adjust" - "adopath" "alpha" - "an" "ano" "anov" "anova" "arch" - "areg" "arima" - "as" "ass" "asse" "asser" "assert" - "avplot" "avplots" - "bcskew0" - "be" "bee" "beep" - "biprobit" "bitest" "bitesti" "blogit" - "boxcox" "bprobit" "br" "break" "brier" - "bro" "brow" "brows" "browse" - "bsqreg" "bstat" "by" - "canon" "cat" "cc" "cci" "cchart" "centile" "cf" "ci" "cii" - "clogi" "clogit" "clogitp" "cloglog" - "close" "cmdtool" - "cnr" "cnre" "cnreg" "cnsreg" "codebook" "compare" - "copy" - "cor" "corc" "corr" "corre" "correl" "correla" "correlat" "correlate" - "corrgram" - "cou" "coun" "count" - "cox" "cprplot" "_crcswxx" "cs" "csi" - "ct" "ctset" "cttost" - "cumul" "cusum") - font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "d" "de" "des" "desc" "descr" "descri" "describ" "describe" - "dfbeta" "dfuller" "di" - "dir" "dis" "disp" "disp_res" "disp_s" - "displ" "displa" "display" - "do" "dotplot" - "dprobit" "ds" "dstdize" "dwstat" - "eivreg" "eq" "ereg" - "fac" "fact" "facto" "factor" - "fit" "for" "fpredict" - "fracplot" "fracpoly" "fsl" - ) font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "gettoken" "gladder" "glm" "glmpred" "glogit" "gnbreg" "gompertz" - "gphdot" "gphpen" "graph" "gprobit" "greigen" "grmeanby" - "hadimvo" "hausman" "heckman" "heckprob" "hetprob" "hettest" "hilite" - "hist" "hlu" "hotel" - "iqreg" "istdize" "iis" - "ins" "insp" "inspe" "inspec" "inspect" - "integ" "intreg" "ir" "iri" "ivreg" - "kap" "kappa" "kapwgt" "kdensity" "ksm" "ksmirnov" "ktau" - "kwallis" - ) font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "l" "ladder" "lfit" "lincom" "linktest" - "li" "lis" "list" - "log" - "logistic" - "logi" "logit" - "loneway" "lookfor" - "lo" "loo" "look" "looku" "lookup" - "lpredict" "lroc" "lrtest" "ls" "lsens" "lstat" "ltable" "lv" "lvr2plot" - "man" "matcproc" "mcc" "mcci" - "means" - "mlog" "mlogi" "mlogit" - "mor" "more" - "mvreg" "mx_param" - "n" "nbreg" "newey" "news" - "nl" "nlinit" - "no" "noi" "nois" "noisi" "noisil" "noisily" - "note" "notes" - "nptrend" "numlist" - "olog" "ologi" "ologit" - "ologitp" - "on" "one" "onew" "onewa" "oneway" - "oprob" "oprobi" "oprobit" - "oprobitp" - "orthog" "orthpoly" - "ovtest") - font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(("pac" "pchart" "pchi" "pcorr" "pergram" - "pl" "plo" "plot" - "pnorm" "poisgof" "poisson" "pperron" - "prais" - "prob" "probi" "probit" - "prtest" "prtesti" - "pwcorr" "pwd" - "q" "qchi" "qnorm" "qqplot" "qreg" "quadchk" "quantile" - "qu" "que" "quer" "query" - "qui" "quie" "quiet" "quietl" "quietly" - "ranksum" "rchart" "regdw" "regph" - "reg" "reg3" "regr" "regre" "regres" "regress" "reshape" - "rot" "rota" "rotat" "rotate" - "rreg" - "run" "runtest" "rvfplot" "rvpplot" - ) font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "sampsi" "sconfirm" - "sco" "scobit" "scor" "score" - "sdtest" "sdtesti" "search" "serrbar" - "sfrancia" "shell" "shelltool" "shewhart" "signrank" "signtest" - "sktest" "slog" "spearman" "spikeplt" "sqreg" - "st" "st_is" "st_show" "st_ct" - "stcox" "stcoxkm" "stcurv" "stdes" - "stem" - "stereg" "stir" "stmc" "stmh" "stphplot" "stphtest" - "strate" "streg" - "sts" "stse" "stset" "stsum" "stvary" "stweib" - "su" "sum" "summ" "summa" "summar" "summari" "summariz" "summarize" - "sureg" - "svydes" "svyintrg" "svyivreg" "svylc" "svylogit" - "svymean" "svymean" "svymlog" "svyolog" "svyoprob" "svypois" "svyprobt" - "svyprop" "svyratio" "svyreg" "svyset" "svytab" "svytest" "svytotal" - "swilk" "symmetry" "symmi" "symplot" "syntax" "sysdir" - ) font-lock-reference-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "ta" "tab" - "tab1" "tab2" - "tabdisp" - "tabi" - "table" - "tabu" "tabul" "tabula" "tabulat" "tabulate" - "te" "tes" "test" - "testnl" "testparm" "tis" - "tob" "tobi" "tobit" - "token" "tokeni" "tokeniz" "tokenize" - "touch" "tsreport" "tsset" "tsunab" "ttest" "ttesti" - "ty" "typ" "type" - "unab" "using" - "vce" - "verinst" "vif" "vwls" - "weibull" "which" "who" "wntestb" "wntestq" - "xchart" "xcorr" - "xtclog" "xtdes" "xtgee" "xtgls" "xthaus" "xtintreg" - "xtlogit" "xtnbreg" "xtpois" "xtprobit" - "xtrchh" "xtreg" "xtsum" "xttab" "xttest0" "xttobit" "xttrans" - "zip" "zinb" - ) font-lock-reference-face) - "\\b" - )) - - ;; conditional statements - ;; if might not work right ('cuz it is also a keyword) - (eval-when-compile - (make-regexps - "^[ \t]*\\sw+[ \t]*" - '(("if" - ) font-lock-reference-face t t) - "\\b" - )) - - (eval-when-compile - (make-regexps - "^[ \t]*" - '(("if" "while" - ) font-lock-reference-face t t) - "[ \t]+.*{" - )) - ;; else statement (which must just have a {) - (eval-when-compile - (make-regexps - "^[ \t]*" - '(("else" - ) font-lock-reference-face) - "[ \t]*{" - )) - - ;; short version of list --- which can get fooled if used as a var - (eval-when-compile - (make-regexps - '(("^[ \t]*l\\b" - ) font-lock-reference-face) - )) - - ;; all the Stata options - ;; commonly used options - (eval-when-compile - (make-regexps - "[ \t]+" - '(("byte" "int" "long" "str[1-9]+[0-9]?" "float" "double" - "width" "maxobs" "maxvar" - ) font-lock-type-face) - "[ \t]+" - )) - ;; special local variables (used in parsing) - (eval-when-compile - (make-regexps - "^[ \t]+\\(local\\)+[ \t]+" - '(("varlist" "exp" "weight" "if" "in" "using" "options" - ) font-lock-type-face nil t t) - "\\b" - )) - - ;; things used with display - ;; since these are often split across lines, and Stata commands are hard - ;; to delimit, this will highlight even if out of context - - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "_c" "_co" "_con" "_cont" "_conti" "_contin" "_continu" "_continue" - "_n" "_ne" "_new" "_newl" "_newli" "_newlin" "_newline" - "_quote" - "_r" "_re" "_req" "_requ" "_reque" "_reques" "_request" - ) - font-lock-type-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "[ \t]+" - '(( - "_col" "_colu" "_colum" "_column" - "_d" "_du" "_dup" - "_s" "_sk" "_ski" "_skip" - ) - font-lock-type-face) - "([1-9]+[0-9]*)\\b" - )) - (eval-when-compile - (make-regexps - "\\bin[ \t]+" - '(( - "b" "bl" "blu" "blue" - "g" "gr" "gre" "gree" "green" - "r" "re" "red" - "w" "wh" "whi" "whit" "white" - "y" "ye" "yel" "yell" "yello" "yellow" - ) font-lock-type-face) - "\\b" - )) - - ;; labels - (eval-when-compile - (make-regexps - "[ \t]+" - '(("lab" "labe" "label" - ) font-lock-reference-face t) - "[ \t]+" - '(( - "da" "dat" "data" - "de" "def" "defi" "defin" "define" - "di" "dir" - "drop" - "l" "li" "lis" "list" - "save" - "val" "valu" "value" "values" - "var" "vari" "varia" "variab" "variabl" "variable" - ) font-lock-type-face nil t t) - "[ \t]" - )) - - ;; all Stata data-altering stuff - (eval-when-compile - (make-regexps - "\\b" - '(( - "_pctile" "_predict" - "aorder" "append" - "bcskew0" "bsample" "bs" "bstrap" - "cd" "chdir" "clear" "compress" - "contract" "convert" "cross" - "dec" "deco" "decod" "decode" - "discard" "drop" "dydx" - "ed" "edi" "edit" "egen" - "en" "enc" "enco" "encod" "encode" - "erase" - "expand" - "fillin" - "form" "forma" "format" - "fracgen" "fracpred" - "g" "ge" "gen" "gene" "gener" "genera" "generat" "generate" - "gsort" - "impute" - "infile" "infix" "input" "insheet" "integ" "ipolate" - "joinby" - "keep" - "lnskew0" - ) font-lock-keyword-face) - "\\b" - )) - (eval-when-compile - (make-regexps - "\\b" - '(( - "mark" "markout" "marksample" - "matname" - "mer" "merg" "merge" - "mkdir" "mkmat" "mkspline" - "mleval" "mlmatsum" "mlsum""mlvecsum" - "modify" "mov" "move" - "mvdecode" "mvencode" "nlpred" "nobreak" "order" - "ou" "out" "outf" "outfi" "outfil" "outfile" - "outs" "outsh" "outshe" "outshee" "outsheet" - "pctile" - "post" "postclose" "postfile" - "pre" "pred" "predi" "predic" "predict" - "preserve" "range" - "recast" "recode" - "ren" "rena" "renam" "rename" - "renpfix" "replace" "restore" "rm" - "sappend" - "sa" "sav" "save" - "sample" "sdrop" - "separate" - "simul" "sinfile" "smerge" - "smooth" "snapspan" - "so" "sor" "sort" - "ssave" "ssort" "stack" - "stbase" "stfill" "stgen" "stjoin" "stsplit" "sttocc" "sttoct" - "suse" "svmat" - "tsfill" "tsrevar" - "u" "us" "use" - "xi" "xi:" "xtile" "xpose" - "xtdata" "xtpred" - ) font-lock-keyword-face) - "\\b" - )) - - ;; assignment of macros - (eval-when-compile - (make-regexps - "^[ \t]*" - '(("global" "local" "scalar" - ) font-lock-reference-face) - '(("\\([ \t]+[a-zA-Z_]+[a-zA-Z_0-9]*\\b\\)?" - ) font-lock-variable-name-face t) - )) - ;; choosing temp names - (eval-when-compile - (make-regexps - "^[ \t]*" - '(("tempname" "tempfile" "tempvar" - ) font-lock-reference-face) - '(("\\([ \t]+[a-zA-Z_]+[a-zA-Z_0-9`']*\\)+" - ) font-lock-type-face t) - )) - ;; all variable/macro stuff (put late so it will override) - ;; internal constants - (eval-when-compile - (make-regexps - "[^a-zA-Z]" - '(("_merge" "_n" "_pi" "_rc" "_N" - ) font-lock-variable-name-face) - "[^a-zA-Z]" - )) - ;; some generated vars - (eval-when-compile - (make-regexps - '(("_result([1-9]+)" - ) font-lock-variable-name-face) - )) - ;; global macros - (eval-when-compile - (make-regexps - '(("\\$[a-zA-Z_*]+[a-zA-Z_0-9]*" - ) font-lock-variable-name-face t) - )) - ;; local macros - (eval-when-compile - (make-regexps - "`+" - '(("[a-zA-Z_`*]+[a-zA-Z_0-9]*" ;has glitch interior ` is highlighted - ) font-lock-variable-name-face t) - "'+" - )) - ;; other macro commands - (eval-when-compile - (make-regexps - "[ \t]*" - '(( - "ma" "mac" "macr" "macro" - ) font-lock-reference-face) - "[ \t]+" - '(( - "de" "def" "define" - "di" "dir" - "drop" - "l" "li" "lis" "list" - "s" "sh" "shi" "shif" "shift" - ) - font-lock-type-face) - "[ \t]+" - )) - ;; stata 'functions' i.e. things which require () after them - (eval-when-compile - (make-regexps - "\\b" - '(("_caller" - "abs" "acos" "asin" "atan" "autocode" - "Binomial" - "binorm" - "chiprob" "comb" "cond" "cos" - "d" "date" "digamma" "day" - "dofh" "dofm" "dofq" "dofw" "dofy" "dow" "doy" - "e" "exp" - "float" "fprob" "gammap" "get" "group" - "h" "halfyear" "halfyearly" "hofd" - "ibeta" "index" "int" - "invbinomial" "invchi" "invfprob" "invgammap" "invnchi" "invnorm" "invt" - "length" "ln" "lnfact" "lngamma" "log" "log10" "lower" "ltrim" - "m" "matrix" "max" "mdy" "min" "missing" "mod" "mofd" "month" "monthly" - "nchi" "normd" "normprob" "npnchi" - "q" "qofd" "quarter" "quarterly" - "r" "real" "recode" "reldif" "replay" "return" "round" "rtrim" - "s" "scalar" "sign" "sin" "sqrt" "string" "substr" "sum" - "tan" "tprob" "trigamma" "trim" - "uniform" "uniform0" "upper" - "w" "week" "weekly" "wofd" - "y" "year" "yearly" "yh" "ym" "yofd" "yq" "yw" - ) - font-lock-reference-face t) - "(" - )) - ;; stata 'functions' i.e. things which require [] after them - (eval-when-compile - (make-regexps - "\\b" - '(("_b" "_coef" "_se") - font-lock-reference-face t) - "\\[" - )) - ;; common Stata options which require a () after them - (eval-when-compile - (make-regexps - "[, \t]+" - '(("bands" "by" "connect" "density" "gap" "iterate" "ltolerance" "margin" - "psize" "saving" "tlabel" "tolerance" - "xlabel" "xscale" "ylabel" "yscale") - font-lock-type-face t) - "(" - )) - ;; egen 'function' options - (eval-when-compile - (make-regexps - "[ \t]*egen[ \t]+.*=[ \t]*" - '(("count" "diff" "fill" "group" "iqr" - "ma" "max" "mean" "median" "min" "mtr" "pctile" - "rank" "rfirst" "rlast" "rmax" "rmean" "rmin" "rmiss" "robs" "rsd" "rsum" - "sd" "std" "sum") - font-lock-reference-face t) - "(.*)" - )) - ;; All Custom ado files which are 'reliable' and which are not file killers - ;; this might be a useless endeavor --- but I cannot generate tag files - ;; all the s-extensions are listed under Stata's name (since they alter - ;; data and will be moved to the utils directory - (eval-when-compile - (make-regexps - "[ \t]*" - '(("addnote" "anypath" "autolab" "checkvar" "ck1icd9" "ckicd9" - "datetoe" "dattomdy" "den2dem" "dishis" "dtapath" "dupclean" "echo" - "exdupbil" "ezip2hsa" "getdate" "getlbl" "getnames" "getobs" "gplur" - "icd9" "issorted" "isfile" "jultoe" "jultof" "jultomdy" "knowndup" - "labeldir" "linker" - "markit" "makewide" "missize" "mpcounts" - "nodups" "notefile" "prov2zip" - "qcolsum" "qorder" - "random" "readraw" "readzip" "repart" - "setup" "stdrate" - "timeslot" - "wdatetoe" "wdatomdy" "zip2ezip" - "_addext" "_brclean" "_brckado" "_brdlog" - "_ckbad" "_ckdunno" "_ckdupl" "_ckmiss" "_ckok" "_ckwarn" - "_delimit" "_filenm" "_lookup" "_mk_ck" - ) font-lock-function-name-face) - "\\b" - )) - )) - - -(defvar ess-STA-mode-font-lock-defaults (ado-set-font-lock-keywords) - "Set the Stata mode font-lock keywords to Bill Rising's ado-mode keywords.") - -(defvar STA-editing-alist - '((paragraph-start . (concat "[ \t\f]*$\\|" page-delimiter)) - (paragraph-separate . (concat "[ \t\f]*$\\|" page-delimiter)) - (paragraph-ignore-fill-prefix . t) - (comment-column . 40) - ;;(comment-indent-function . 'S-comment-indent) - ;;(ess-comment-indent . 'S-comment-indent) - ;;(ess-calculate-indent . 'ess-calculate-indent) - (ess-local-process-name . nil) - ;;(ess-keep-dump-files . 'ask) - (font-lock-defaults . '(ess-STA-mode-font-lock-defaults - nil nil ((?\. . "w"))))) - "General options for editing Stata do and ado source files.") - -;; YOU USED TO HAVE TO (with Thomas's version): -;;;;; Add the following to your .emacs file -;; -;;(autoload 'stata "~/ess-sta-l.el" "inferior stata mode" t ) -;;(autoload 'stata-help "stata" "stata help mode" t) -;;(autoload 'stata-mode "~/ess-sta-l.el" "stata mode" t) -;; -;;(if (assoc "\\.do$" auto-mode-alist) nil -;; (setq auto-mode-alist -;; (append -;; '(("\\.do$" . stata-mode) -;; ("\\.ado$" . stata-mode)) -;; auto-mode-alist))) -;; - - -;; QUESTIONS TO ASK THOMAS: -;; 1 - are 'help' and 'lookup' the same? -;; 2 - what is the point of the review buffer? -;; 3 - how to quit? - -;; -;; NOTE: all of Thomas's functions have been left here, to be removed -;; or merged into real locations as we work on this. -;; - - -;;;;;;;;; Things to change - -(defvar stata-switches "-q" - "Switches to apply to stata invocation.") - -(defvar stata-profile "~/.stataprofile" - "File to read on startup (nil for no file).") - -(define-obsolete-function-alias 'stata-help 'ess-display-help-on-object "ESS[15.09]") -(define-obsolete-function-alias 'stata-lookup 'ess-display-help-apropos "ESS[16.03]") - -;; fixme? Hook this on C-c C-s /ess-execute-search does an R search() right now/ -(defun stata-variables () - "Stata variable list in other buffer." - (interactive) - (let* ((stata-process (get-process "stata")) - (stata-buffer (if stata-process - (process-buffer stata-process) - (error "Stata is not running."))) - oldpf oldpb oldpm) - (set-buffer stata-buffer) - (setq oldpf (process-filter stata-process)) - (setq oldpb (process-buffer stata-process)) - (setq oldpm (marker-position (process-mark stata-process))) - (save-excursion - (if stata-process nil (error "Stata is not running.")) - (beginning-of-line) - (if (looking-at ". ") nil (error "Stata not ready.")) - (save-excursion - (set-process-buffer stata-process - (get-buffer-create "*stata variables*")) - (set-process-filter stata-process 'inferior-ess-ordinary-filter) - (set-buffer "*stata variables*") - (setq buffer-read-only nil) - (erase-buffer) - (process-send-string stata-process "desc \n ") - (stata-prompt-wait stata-process) - (setq buffer-read-only t) - (set-buffer stata-buffer) - (set-process-buffer stata-process oldpb) - (set-marker (process-mark stata-process) oldpm) - (set-process-filter stata-process oldpf))) - (display-buffer "*stata variables*") - (goto-char (point-max)))) - -(defun stata-prompt-wait (proc &optional start-of-output) - "Wait for a prompt to appear at BOL of current buffer. -PROC is the stata process. Does not change point." - (if start-of-output nil (setq start-of-output (point-min))) - (save-excursion - (while (progn - ;; get output if there is some ready - (accept-process-output proc 0 50) - (goto-char (marker-position (process-mark proc))) - (beginning-of-line) - (if (< (point) start-of-output) (goto-char start-of-output)) - (not (looking-at "^. ")))))) - -(cl-defmethod ess--help-major-mode (&context (ess-dialect "stata")) - (ess-stata-help-mode)) - -(define-derived-mode ess-stata-help-mode ess-help-mode "Stata help" - "Major mode for displaying Stata help in a read-only buffer. -Active commands are Help (\\[stata-help]) and hyperlink -(\\[stata-rehelp] or mouse-2)." - :group 'ess-Stata) - -;;; Suggested function from Brendan Halpin: -(defvar ess-STA-delimit-do-file "delimit-do.do") - -(defun ess-STA-delimit-do () - (save-excursion - (let ((commands (buffer-substring-no-properties (region-beginning) - (region-end)))) - (set-buffer (get-buffer-create ess-STA-delimit-do-file)) - (delete-region (point-min) (point-max)) - (insert "#delimit ;\n" - commands - "\n#delimit cr\n") - (write-file ess-STA-delimit-do-file nil) - (comint-send-string "Stata" - (format "do %s \n" ess-STA-delimit-do-file))))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -(provide 'ess-stata-lang) - -;;; ess-stata-lang.el ends here diff --git a/elpa/ess-20191014.1343/ess-stata-mode.el b/elpa/ess-20191014.1343/ess-stata-mode.el deleted file mode 100644 index b56299a2..00000000 --- a/elpa/ess-20191014.1343/ess-stata-mode.el +++ /dev/null @@ -1,219 +0,0 @@ -;;; ess-stata-mode.el --- Stata customization -*- lexical-binding: t; -*- - -;; Copyright (C) 1997--1999 A. J. Rossini, Thomas Lumley -;; Copyright (C) 1997--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: A.J. Rossini -;; Created: 9 Sep 1998 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This file defines all the Stata customizations for ess-mode. It is somewhat -;; based on Stata-mode by Thomas Lumley . - -;;; Code: - -(require 'ess-mode) -(require 'ess-stata-lang) - -(defvar STA-dialect-name "stata" - "Name of 'dialect' for Stata.");easily changeable in a user's .emacs - -(defvar ess-stata-mode-syntax-table - (let ((tbl (copy-syntax-table ess-mode-syntax-table))) - (modify-syntax-entry ?\\ "." tbl) ;nullify escape meaning - (modify-syntax-entry ?\$ "." tbl) - (modify-syntax-entry ?` "(\'" tbl) - (modify-syntax-entry ?\' ")`" tbl) - (modify-syntax-entry ?/ ". 124b" tbl) - ;; asterisk at bol comments taken care of by - ;; `syntax-propertize-function'. - (modify-syntax-entry ?* ". 23b" tbl) - (modify-syntax-entry ?\n ">" tbl) - (modify-syntax-entry ?+ "." tbl) - (modify-syntax-entry ?- "." tbl) - (modify-syntax-entry ?= "." tbl) - (modify-syntax-entry ?% "." tbl) - (modify-syntax-entry ?< "." tbl) - (modify-syntax-entry ?> "." tbl) - (modify-syntax-entry ?& "." tbl) - (modify-syntax-entry ?| "." tbl) - (modify-syntax-entry ?~ "." tbl) - tbl) - "Syntax table for `ess-stata-mode'.") - -(defvar STA-customize-alist - '((ess-local-customize-alist . 'STA-customize-alist) - (ess-language . "STA") - (ess-dialect . STA-dialect-name) - (ess-suffix . "ado") - (ess-mode-editing-alist . STA-editing-alist) - (ess-help-sec-regex . ess-help-STA-sec-regex) - (ess-help-sec-keys-alist . ess-help-STA-sec-keys-alist) - (ess-loop-timeout . 500000 ) - (ess-object-name-db-file . "ess-sta-namedb.el" ) - (inferior-ess-program . inferior-STA-program) - (inferior-ess-objects-command . "describe\n") - (inferior-ess-help-command . "help %s\n") ;; assumes set more off - (inferior-ess-exit-command . "exit\n") - ;; --more-- is necessary here (hangs otherwise if startup stata.msg is big) - (inferior-ess-primary-prompt . "[.:] \\|--more--") - (inferior-ess-secondary-prompt . ">\\|--more--") - (inferior-ess-prompt . "\\([.:>] \\|--more--\\)") - (comint-use-prompt-regexp . t) - (inferior-ess-search-list-command . "set more off\n search()\n") - (ess-execute-screen-options-command . "set linesize %s\n") - (ess-getwd-command . "pwd\n") - (ess-setwd-command . "cd \"%s\"\n") - (ess-load-command . "run \"%s\"\n")) - "Variables to customize for Stata.") - -(cl-defmethod ess--help-web-search-override (cmd &context (ess-dialect "stata")) - "Browse the web for documentation about CMD in Stata." - (browse-url - (format - "https://www.stata.com/search/?q=%s&restrict=&btnG=Search&client=stata&num=&output=xml_no_dtd&site=stata&ie=&oe=UTF-8&sort=&proxystylesheet=stata" - cmd))) - -;;;###autoload -(define-derived-mode ess-stata-mode ess-mode "ESS[STA]" - "Major mode for editing Stata source." - :group 'ess-Stata - (ess-setq-vars-local STA-customize-alist) - (setq-local comint-use-prompt-regexp t) - (setq-local comment-column 40) - (setq-local comment-end " */") - (setq-local comment-start "/* ") - (setq-local comment-start-skip "/\\*+ *") - (setq-local comment-use-syntax t) - (setq-local syntax-propertize-function - (syntax-propertize-rules ("^\\*" (0 "<")))) - (setq-local paragraph-ignore-fill-prefix t) - (setq-local paragraph-separate (concat "[ \t\f]*$\\|" page-delimiter)) - (setq-local paragraph-start (concat "[ \t\f]*$\\|" page-delimiter)) - (setq font-lock-defaults '(ess-STA-mode-font-lock-defaults nil nil ((?\. . "w"))))) - -(defalias 'STA-mode 'ess-stata-mode) -(defalias 'stata-mode 'ess-stata-mode) -(defalias 'Stata-mode 'ess-stata-mode) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.do\\'" . ess-stata-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.ado\\'" . ess-stata-mode)) - - -(defun ess-sta-remove-comments (string) - "Remove one-line comments before sending the STRING to process. - -This function is placed in `ess-presend-filter-functions'." - (replace-regexp-in-string "/\\*.*\\*/\\|^//.*$" "" string)) - -;; (ess-sta-remove-comments "aaa /* sdfdsf */ bbb -;; sdfsd -;; ccc -;; // sdfsf -;; sdf /* sdfdsf */ -;; sdfsf -;; " ) - - -(defvar ess-stata-post-run-hook nil - "Functions run in process buffer after the initialization of stata process.") - -(defun stata (&optional start-args) - "Call Stata with START-ARGS." - (interactive "P") - (ess-write-to-dribble-buffer - (format "(STA): ess-dialect=%s , buf=%s \n" - ess-dialect - (current-buffer))) - (let* ((sta-start-args - (concat inferior-STA-start-args - (when start-args (read-string "Starting Args [possibly -k####] ? ")))) - (inf-buf (inferior-ess sta-start-args STA-customize-alist)) - (inf-proc (get-buffer-process inf-buf))) - (while (process-get inf-proc 'sec-prompt) - ;; get read of all --more-- if stata.msg is too long. - (ess-send-string inf-proc "q") - (ess-wait-for-process inf-proc t)) - (ess-send-string inf-proc "set more off") - (goto-char (point-max)) - (with-current-buffer inf-buf - (add-hook 'ess-presend-filter-functions 'ess-sta-remove-comments nil 'local) - (run-mode-hooks 'ess-stata-post-run-hook)) - inf-buf)) - -(defvar inferior-ess-stata-mode-syntax-table - (let ((tab (copy-syntax-table ess-stata-mode-syntax-table))) - tab) - "Syntax table for `inferior-ess-stata-mode'.") - -(define-derived-mode inferior-ess-stata-mode inferior-ess-mode "iESS" - "Inferior `stata' mode." - :group 'ess-proc - (ess-setq-vars-local STA-customize-alist) - (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) - (setq-local comint-use-prompt-regexp t) - (setq font-lock-defaults '(ess-STA-mode-font-lock-defaults nil nil ((?\. . "w"))))) - - -(define-derived-mode ess-stata-transcript-mode ess-transcript-mode "ESS Transcript" - "Stata transcript mode." - :group 'ess-Stata - :syntax-table ess-stata-mode-syntax-table - (ess-setq-vars-local STA-customize-alist) - (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) - (setq-local comint-use-prompt-regexp t) - (setq-local comment-column 40) - (setq-local comment-end " */") - (setq-local comment-start "/* ") - (setq-local comment-start-skip "/\\*+ *") - (setq-local comment-use-syntax t) - (setq-local paragraph-ignore-fill-prefix t) - (setq-local paragraph-separate (concat "[ \t\f]*$\\|" page-delimiter)) - (setq-local paragraph-start (concat "[ \t\f]*$\\|" page-delimiter)) - (setq font-lock-defaults '(ess-STA-mode-font-lock-defaults nil nil ((?\. . "w"))))) - -(defalias 'STA-transcript-mode 'ess-stata-mode-syntax-table) - -(defun ess--STA-retrive-topics-from-search () - (with-current-buffer (ess-command inferior-ess-search-list-command) - (goto-char (point-min)) - (let (topics) - (while (re-search-forward "(help \\(.+?\\)\\( if installed\\| for replacement.*\\)?)$" nil t) - (setq topics - (nconc (split-string (match-string-no-properties 1) ",\\|; +") - topics))) - (nreverse (delete-dups topics)) - ))) - -(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "stata")) - "Return a list of current STA help topics associated with process PROC." - (or (ess-process-get 'help-topics proc) - (progn - (ess-process-put 'help-topics (ess--STA-retrive-topics-from-search)) - (ess-process-get 'help-topics)))) - -(provide 'ess-stata-mode) - -;;; ess-stata-mode.el ends here diff --git a/elpa/ess-20191014.1343/ess-toolbar.el b/elpa/ess-20191014.1343/ess-toolbar.el deleted file mode 100644 index 0ba4a832..00000000 --- a/elpa/ess-20191014.1343/ess-toolbar.el +++ /dev/null @@ -1,184 +0,0 @@ -;;; ess-toolbar.el --- Support for a toolbar in ESS. -*- lexical-binding: t; -*- - -;; Copyright (C) 1997--2009 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Stephen Eglen -;; Created: 2004-05-06 -;; Revised: 2009-03-16 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This code adds a toolbar to ESS modes for editing R and S code. -;; Support can be added for other modes (e.g. STATA), just ask! -;; -;; This code is experimental. It has been tested only on Linux -;; machines. All feedback appreciated. -;; -;; If your Emacs can support images, the ESS toolbar should be loaded. -;; -;; If you see a toolbar, but no icons, check out the value of -;; ess-icon-directory. -;; -;; The toolbar can be customized in several ways. To see options, do: -;; M-x customize-group RET ess-toolbar RET -;; If you change any of the variables, you _may_ need to restart Emacs -;; to see any effect. See also the documentation for ess-toolbar-items -;; if you wish to change its value. - -;;; Technical issues. - -;; 2009-03-16: toolbar code in Emacs 23 has changed slightly to 22, -;; and presumably once Emacs 22 is no longer supported, this code can -;; be cleaned up a bit (i.e. no need to set load-path.) - -;;; Code: - -(require 'ess-mode) - -(defgroup ess-toolbar nil - "ESS: toolbar support." - :group 'ess - :link '(emacs-commentary-link :tag "Commentary" "ess-toolbar.el") - :prefix "ess-") - -(defcustom ess-use-toolbar - (and (fboundp 'display-images-p) (display-images-p)) - "Non-nil means ESS should support the toolbar." - :type 'boolean) - - -(defcustom ess-toolbar-own-icons nil - "Non-nil means that we only put our toolbar entries in ESS. -Otherwise we get standard toolbar as well as ESS entries. -The standard toolbar items are copied from the default toolbar." - :type 'boolean) - -(defcustom ess-toolbar-global nil - "*Non-nil means that the ESS toolbar is available in all Emacs buffers. -Otherwise, the ESS toolbar is present only in R/S mode buffers. -For beginners, this is probably better set to a non-nil value." - :type 'boolean) - -(defcustom ess-toolbar-items - '( (R "startr") - ;;(S "spluslogo" "Start S process") - (S "splus_letter_small") - (ess-eval-line-and-step "rline") - (ess-eval-region "rregion") - (ess-eval-function-or-paragraph-and-step "rregion") - (ess-load-file "rbuffer") - (ess-eval-function "rfunction") - (ess-switch-to-ESS "switch_ess")) - "Items to be added to the ESS toolbar. -Each list element has two items: -1. the name of the function to run -2. the icon to be used (without .xpm extension) - -General toolbar items are also added to the ESS toolbar -iff `ess-toolbar-own-icons' is nil. - -Setting this variable with setq doesn't take effect once you have -loaded ess-site, unless you follow it by a call to -`ess-make-toolbar' afterwards. Instead, change its value using -Custom, and then on all new ESS buffers you should see the -toolbar has changed." - :set (lambda (symbol value) - (set-default symbol value) - (if (fboundp 'ess-make-toolbar) - (ess-make-toolbar))) - :type '(repeat (list (function :tag "Function to run") - (string :tag "Icon")))) - -(defvar ess-icon-directory - (expand-file-name "icons" ess-etc-directory) - "*Location for ESS icons. -This variable should be set automatically by the ESS install process. -Icons should be found in ESS/etc/icons/ directory. -If `ess-icon-directory' is invalid, please report a bug.") - -(unless (file-directory-p ess-icon-directory) - (ess-write-to-dribble-buffer - "`ess-icon-directory' does not exist; using `ess-etc-directory'.\n") - (setq ess-icon-directory ess-etc-directory)) - -(defvar ess-toolbar nil - "Toolbar items to be added to ESS editing buffers.") - -(defun ess-make-toolbar () - "Make the ESS toolbar." - ;; Under Emacs, only worth building the toolbar if tool-bar-map is - ;; available. e.g. when running Emacs within a terminal, tool-bar-map - ;; is not available, so no need to make the tool-bar. - (when (boundp 'tool-bar-map) - (setq ess-toolbar - (if (or ess-toolbar-own-icons (null tool-bar-map)) - (make-sparse-keymap) - (copy-keymap tool-bar-map))) - (let ((tool-bar-map ess-toolbar) - (load-path (list ess-icon-directory))) - ;; in Emacs 22, icons are found by examining load-path, bound here - ;; whereas Emacs 23 seems to want them in image-load-path, set at the - ;; bottom of this file. - (mapc #'ess-add-icon ess-toolbar-items)))) - -(defun ess-add-icon (x) - "Add an ESS item to the Emacs toolbar. -X should be a list, see `ess-toolbar-items' for the format." - ;; By using tool-bar-add-item-from-menu instead of tool-bar-add-item - ;; we get the tooltips "for free" from ess-mode-map. - (tool-bar-add-item-from-menu (car x) (cadr x) ess-mode-map)) - -(defun ess-add-toolbar () - "Add the ESS toolbar to a particular mode. -The toolbar is added iff `ess-toolbar-global' is nil, else the toolbar -is added globally when ess-toolbar.el is loaded." - (when (and ess-toolbar (not ess-toolbar-global)) - (setq-local tool-bar-map ess-toolbar))) - -;; Make the toolbars. Each toolbar is hopefully made only when this file -;; is loaded; we don't need it to be remade every time. -(if ess-use-toolbar - (progn - (ess-make-toolbar) - ;; After making the toolbar, if ESS toolbar is needed globally, - ;; add it here. - (if ess-toolbar-global - (setq tool-bar-map ess-toolbar) - (ess-write-to-dribble-buffer "Creating global Emacs toolbar")) - - ;; Check for toolbar support - needed iff ess-use-toolbar is non-nil. - (or - ;; Emacs support for images: - (and (fboundp 'display-images-p) (display-images-p)) - ;; if above tests failed, give a warning. - (progn - (message "Toolbar support for ESS not available in this Emacs.") - ;; Not sure if we want to delay startup of ESS. - ;;(sit-for 2) - )) - )) - -;; Following needed for Emacs 23, not Emacs 22 -(when (boundp 'image-load-path) - (add-to-list 'image-load-path ess-icon-directory)) - -(provide 'ess-toolbar) - -;;; ess-toolbar.el ends here diff --git a/elpa/ess-20191014.1343/ess-tracebug.el b/elpa/ess-20191014.1343/ess-tracebug.el deleted file mode 100644 index 1e4518eb..00000000 --- a/elpa/ess-20191014.1343/ess-tracebug.el +++ /dev/null @@ -1,2798 +0,0 @@ -;; ess-tracebug.el --- Tracing and debugging facilities for ESS. -*- lexical-binding: t; -*- -;; -;; Copyright (C) 2011--2017 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. -;; -;; Filename: ess-tracebug.el -;; Author: Vitalie Spinu -;; Maintainer: Vitalie Spinu -;; Copyright (C) 2010-2012, Vitalie Spinu, all rights reserved. -;; Created: Oct 14 14:15:22 2010 -;; URL: https://code.google.com/p/ess-tracebug/ -;; Keywords: tools, languages -;; -;; This file is *NOT* part of GNU Emacs. -;; -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3, any later version. -;; -;; This program is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -;; details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: -;; Ess-tracebug is a package for interactive debugging of R code from -;; ESS and provides such features as: -;; - visual debugging -;; - browser, recover and conditional breakpoints -;; - watch window and loggers -;; - on the fly debug/undebug of R functions and methods -;; - highlighting of error source references and easy error navigation -;; - interactive traceback. -;; -;; For a complete description please see the documentation in the ESS -;; manual. -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Code: - -(eval-when-compile - (when (< emacs-major-version 26) - (require 'cl)) - (require 'cl-lib) - (require 'tramp) - (require 'subr-x)) -(require 'comint) -(require 'compile) -(require 'ring) -(require 'ess-utils) - -(defvar text-scale-mode-amount) -(autoload 'text-scale-mode "face-remap" "[autoload]" nil) - -;; Silence the byte compiler. This is OK here because this file is -;; only loaded from ess-inf and has no autoloads. -;; TODO: This is a LOT. Can we move some of this around? -(defvar ess--dbg-del-empty-p) -(defvar inferior-ess-mode-map) -(defvar ess-mode-map) -(defvar ess--inhibit-presend-hooks) -(declare-function ess--accumulation-buffer "ess-inf") -(declare-function ess--if-verbose-write-process-state "ess-inf") -(declare-function ess--run-presend-hooks "ess-inf") -(declare-function ess-boolean-command "ess-inf") -(declare-function ess-build-eval-command "ess-inf") -(declare-function ess-build-load-command "ess-inf") -(declare-function ess-command "ess-inf") -(declare-function ess-dirs "ess-inf") -(declare-function ess-force-buffer-current "ess-inf") -(declare-function ess-get-process "ess-inf") -(declare-function ess-get-process-variable "ess-inf") -(declare-function ess-get-words-from-vector "ess-inf") -(declare-function ess-process-get "ess-inf") -(declare-function ess-process-live-p "ess-inf") -(declare-function ess-process-put "ess-inf") -(declare-function ess-send-string "ess-inf") -(declare-function ess-switch-process "ess-inf" ()) -(declare-function ess-switch-to-ESS "ess-inf") -(declare-function ess-wait-for-process "ess-inf") -(declare-function ess-switch-to-end-of-ESS "ess-inf" ()) -(declare-function ess-eval-region--normalise-region "ess-inf" ) -(declare-function inferior-ess-run-callback "ess-inf") -(declare-function inferior-ess--set-status "ess-inf") -(declare-function ess-helpobjs-at-point--read-obj "ess-help") -(declare-function ess-r-get-evaluation-env "ess-r-mode") -(declare-function ess-r-package--all-source-dirs "ess-r-package") -(declare-function ess-r-package-name "ess-r-package") -(declare-function ess-r-package-source-dirs "ess-r-package") - -;; Do not require tramp at runtime. It is expensive to load. Instead, -;; guard calls with (require 'tramp) and silence the byte compiler -;; here. -(declare-function tramp-dissect-file-name "tramp") -(declare-function tramp-get-remote-tmpdir "tramp") -;; The following declares can be removed once we drop Emacs 25 -(declare-function tramp-file-name-method "tramp") -(declare-function tramp-file-name-user "tramp") -(declare-function tramp-file-name-host "tramp") -(declare-function tramp-file-name-localname "tramp") -(declare-function tramp-file-name-hop "tramp") - - -(defgroup ess-tracebug nil - "Error navigation and debugging for ESS. -Currently only R is supported." - :link '(emacs-library-link :tag "Source Lisp File" "ess-tracebug.el") - :group 'ess) - -(defvar ess-tracebug-indicator " TB" - "String to be displayed in mode-line alongside the process name. -Indicates that ess-tracebug-mode is turned on.") - -(defvar ess-watch-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "k" #'ess-watch-kill) - ;; (define-key ess-watch-mode-map "u" #'ess-watch-undelete) - ;; editing requires a little more work. - (define-key map "a" #'ess-watch-add) - (define-key map "i" #'ess-watch-insert) - (define-key map "e" #'ess-watch-edit-expression) - (define-key map "r" #'ess-watch-rename) - (define-key map "q" #'ess-watch-quit) - (define-key map "u" #'ess-watch-move-up) - (define-key map "U" #'ess-watch-move-down) - (define-key map "d" #'ess-watch-move-down) - (define-key map "n" #'ess-watch-next-block) - (define-key map "p" #'ess-watch-previous-block) - ;; R mode keybindings. - (define-key map "\C-c\C-s" #'ess-switch-process) - (define-key map "\C-c\C-y" #'ess-switch-to-ESS) - (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) - map) - "Keymap for `ess-watch-mode'.") - - -(defcustom ess-tracebug-prefix nil - "Key to be used as prefix for all `ess-tracebug' commands. -Set this to a key combination you don't use often, like: - - (setq ess-tracebug-prefix \"\\M-t\") - -The postfix keys are defined in `ess-tracebug-map': -\\{ess-tracebug-map}" - :type '(choice (const nil) (string)) - :group 'ess-tracebug) - -(defcustom ess-tracebug-search-path nil - "List of directories to search for source files. -Elements should be directory names, not file names of directories." - :type '(choice (const :tag "Unset" nil) - (repeat :tag "Directory list" (string :tag "Directory"))) - :group 'ess-debug) - -(defvar ess-watch-buffer "*R watch*" - "Name of the watch buffer.") - -(defcustom ess-watch-height-threshold nil - "Minimum height for splitting *R* window sensibly to make space for watch window. -See `split-height-threshold' for a detailed description. - -If nil, the value of `split-height-threshold' is used." - :group 'ess-debug - :type '(choice (const nil) (integer))) - -(defcustom ess-watch-width-threshold nil - "Minimum width for splitting *R* window sensibly to make space for watch window. -See `split-width-threshold' for a detailed description. - -If nil, the value of `split-width-threshold' is used." - :group 'ess-debug - :type '(choice (const nil) (integer))) - -(defcustom ess-watch-scale-amount -1 - "The number of steps to scale the watch font down (up). -Each step scales the height of the default face in the watch -window by the variable `text-scale-mode-step' (a negative number -of steps decreases the height by the same amount)" - :group 'ess-debug - :type 'integer) - -(defvar-local ess-watch-current-block-overlay nil - "The overlay for currently selected block in the R watch buffer .") - -(defcustom ess-inject-source 'function-and-buffer - "Control the source injection into evaluated code. - -If t, always inject source reference. -If function, inject only for functions, -If function-and-buffer, inject for functions and whole buffer (the default), -If nil, never inject. - -When tracebug is active (the default), ESS instructs the -subprocess to keep the source code references. - -If this variable is t, you won't be able to execute blocks which -don't form a valid R expression. That is, if your expression -spreads multiple paragraphs, and you call -\\[ess-eval-region-or-function-or-paragraph-and-step] on first -paragraph, R will report an error." - :group 'ess-tracebug - :type '(choice (const nil) (const function) (const function-and-buffer) (const t))) - -(defcustom ess-tracebug-enter-hook nil - "List of functions to call on entry to `ess-tracebug' mode. -Use `add-hook' to insert append your functions to this list." - :group 'ess-tracebug - :type 'hook) - -(defcustom ess-tracebug-exit-hook nil - "List of functions to call on exit of `ess-tracebug' mode. -Use `add-hook' to insert append your functions to this list." - :group 'ess-tracebug - :type 'hook) - -(defvaralias 'ess-tracebug-map 'ess-dev-map) - -(defvar ess--tracebug-eval-index 0 - "This is used by to track source references in evaluation with source. -For example, each time `ess-eval-function' is called the evaluated -region is marked. When debugger enters the code it displays -this reference number. Ess-debug finds this number in the -referenced buffer.") - -;; these vars are org variables that store the src block locations -(defvar org-edit-src-beg-marker nil) -(defvar org-babel-current-src-block-location nil - "Marker pointing to the src block currently being executed. -This may also point to a call line or an inline code block. If -multiple blocks are being executed (e.g., in chained execution -through use of the :var header argument) this marker points to -the outer-most code block.") - -;; hash to store source references of the form: tmpname -> (filename . src_start) -(defvar ess--srcrefs (make-hash-table :test 'equal :size 100)) - -(defvar ess-tracebug-original-buffer-marker nil - "Marker pointing to the beginning of original source code. -If non-nil, tracebug will insert the source references based on -this location instead of the current buffer. This is useful for -applications, like org-babel, that call ess evaluation functions -from temporary buffers.") - -(defun ess-tracebug-p () - "Return non-nil if tracebug is running." - (ess-process-get 'tracebug)) - -(defun ess-make-source-refd-command (beg end visibly process) - "Saves a region to a temporary file in order to add source references. -BEG and END delimit the region. Returns a string containing an -inferior process command for loading the temporary file. This -command conforms to VISIBLY." - (let* ((filename buffer-file-name) - (proc-dir (ess-get-process-variable 'default-directory)) - (remote (when (file-remote-p proc-dir) - (require 'tramp) - ;; should this be done in process buffer? - (tramp-dissect-file-name proc-dir))) - (orig-marker (or ess-tracebug-original-buffer-marker - org-edit-src-beg-marker - org-babel-current-src-block-location)) - orig-beg) - (setq ess--tracebug-eval-index (1+ ess--tracebug-eval-index)) - (goto-char beg) - (skip-chars-forward " \t\n") - (setq beg (point)) - (goto-char end) - (skip-chars-backward " \t\n") - (setq end (point) - orig-beg beg) - - ;; Delete all old temp files - (when (and (not (ess-process-get 'busy)) - (< 1 (float-time - (time-subtract (current-time) - (ess-process-get 'last-eval))))) - (dolist (f (ess-process-get 'temp-source-files)) - (and (file-exists-p f) - (delete-file f))) - (ess-process-put 'temp-source-files nil)) - - (when (markerp orig-marker) - (setq filename (buffer-file-name (marker-buffer orig-marker))) - (setq orig-beg (+ beg (marker-position orig-marker)))) - - (let ((tmpfile - (expand-file-name (make-temp-name - (concat (file-name-nondirectory - (or filename "unknown")) "!")) - (if remote - (tramp-get-remote-tmpdir remote) - temporary-file-directory)))) - - (ess-process-put 'temp-source-files - (cons tmpfile (ess-process-get 'temp-source-files))) - - (when remote - ;; Get local name (should this be done in process buffer?) - (setq tmpfile (with-parsed-tramp-file-name tmpfile nil localname))) - - (if (not filename) - (puthash tmpfile (list nil ess--tracebug-eval-index nil) ess--srcrefs) - (puthash tmpfile (list filename ess--tracebug-eval-index orig-beg) ess--srcrefs) - (puthash (file-name-nondirectory tmpfile) ; R sometimes strips dirs - (list filename ess--tracebug-eval-index orig-beg) ess--srcrefs) - (with-silent-modifications - (put-text-property beg end 'tb-index ess--tracebug-eval-index))) - (let ((string (ess-process-buffer-substring process beg end))) - (or - ;; Sending string to subprocess is considerably faster than tramp file - ;; transfer. So, give priority to `ess-eval-command' if available - (ess-build-eval-command string visibly t tmpfile) - ;; When no `ess-eval-command' available, use `ess-load-command' - (progn - (write-region beg end tmpfile nil 'silent) - (ess-build-load-command tmpfile visibly t))))))) - -(defun ess-process-buffer-substring (process start end) - (ess--run-presend-hooks process (buffer-substring-no-properties start end))) - -(defun ess-tracebug-send-region (process start end &optional visibly message type) - "Send region to process adding source references as specified -by `ess-inject-source' variable." - (ess-eval-region--normalise-region start end) - (let* ((inject-p (cond ((eq type 'function) - ess-inject-source) - ((eq type 'buffer) - (or (eq ess-inject-source t) - (eq ess-inject-source 'function-and-buffer))) - (t (or (eq ess-inject-source t) - ;; We need to always inject with namespaced - ;; evaluation (fixme: not right place for - ;; this). - (ess-r-get-evaluation-env))))) - (ess--dbg-del-empty-p (unless inject-p ess--dbg-del-empty-p)) - (string (if inject-p - (ess-make-source-refd-command start end visibly process) - (ess-process-buffer-substring process start end))) - (message (if (fboundp ess-build-eval-message-function) - (funcall ess-build-eval-message-function message) - message))) - ;; Don't run the presend hooks twice. - (let ((ess--inhibit-presend-hooks t)) - (process-put process :eval-visibly visibly) - ;; Visible evaluation is not nice when sourcing temporary files. You get - ;; .ess.eval(*code*) instead of *code*. - (setq visibly (unless inject-p visibly)) - (ess-send-string process string visibly message)))) - -(defun ess-tracebug-send-function (proc start end &optional visibly message) - "Like `ess-tracebug-send-region' but with tweaks for functions." - (ess-tracebug-send-region proc start end visibly message 'function)) - -(defvar ess-tracebug-help nil - "ess-dev-map prefix: \\[ess-dev-map] - -* Breakpoints (`ess-dev-map'): - - b . Set BP (repeat to cycle BP type) . `ess-bp-set' - B . Set conditional BP . `ess-bp-set-conditional' - k . Kill BP . `ess-bp-kill' - K . Kill all BPs . `ess-bp-kill-all' - o . Toggle BP state . `ess-bp-toggle-state' - l . Set logger BP . `ess-bp-set-logger' - n . Goto next BP . `ess-bp-next' - p . Goto previous BP . `ess-bp-previous' - - (C- prefixed equivalents are also defined) - -* Debugging (`ess-dev-map'): - ` . Show traceback . `ess-show-traceback' (also on C-c `) - ~ . Show callstack . `ess-show-call-stack' (also on C-c ~) - e . Toggle error action (repeat to cycle). `ess-debug-toggle-error-action' - d . Flag for debugging . `ess-debug-flag-for-debugging' - u . Unflag for debugging . `ess-debug-unflag-for-debugging' - w . Watch window . `ess-watch' - - (C- prefixed equivalents are also defined) - -* Interactive Debugging (`ess-debug-minor-mode-map'): - - M-C . Continue . `ess-debug-command-continue' - M-C-C . Continue multi . `ess-debug-command-continue-multi' - M-N . Next step . `ess-debug-command-next' - M-C-N . Next step multi . `ess-debug-command-next-multi' - M-U . Up frame . `ess-debug-command-up' - M-Q . Quit debugging . `ess-debug-command-quit' - -* Navigation to errors (general Emacs functionality): - - C-x `, M-g n . `next-error' - M-g p . `previous-error'") - - -;; * Input Ring: - -;; i . Goto input event marker forwards . `ess-debug-goto-input-event-marker' -;; I . Goto input event marker backwards . `ess-debug-goto-input-event-marker' - - -(defun ess-tracebug-show-help () - "Show help for `ess-tracebug'." - (interactive) - (describe-variable 'ess-tracebug-help)) - -(defun ess-tracebug--propertize (dummy bitmap face &optional string ) - "If `window-system' propertize DUMMY with fringe BITMAP and FACE. -Otherwise, propertize line-prefix and margin with STRING and FACE" - (unless string - (setq string dummy)) - (if window-system - (propertize dummy 'display (list 'left-fringe bitmap face)) - (propertize dummy - 'display (list '(margin left-margin) - (propertize string - 'font-lock-face face - 'face face))))) - - -(defun ess-tracebug (&optional arg) - "Toggle `ess-tracebug' mode. -With ARG, turn `ess-tracebug' mode on if and only if ARG is -positive. - -This mode adds to ESS the interactive debugging, breakpoint and -error navigation functionality. Strictly speaking `ess-tracebug' -is not a minor mode. It integrates globally into ESS and iESS. - -Note: Currently, `ess-tracebug' does not detect some of R's debug -related messages in non-English locales. To set your R messages -to English add the following line to your .Rprofile init file: - - Sys.setlocale(\"LC_MESSAGES\", \"C\") - - -See `ess-tracebug-help' for the overview of ess-tracebug functionality." - - ;; Note: The functionality in ess-tracebug is divided on conceptual - ;; grounds in tracing and debugging and could be - ;; activated/deactivate separately with `ess--tb-start' and - ;; `ess-debug-start' respectively. - - (interactive "P") - (ess-force-buffer-current "R process to activate tracebug in: ") - (with-current-buffer (process-buffer (get-process ess-local-process-name)) - (when (equal ess-dialect "R") - (setq arg - (if arg - (prefix-numeric-value arg) - (if (ess-process-get 'tracebug) -1 1))) - (if (> arg 0) - (unless (ess-process-get 'tracebug) ;; only if already not active - (ess--tb-start) - (ess-debug-start) - ;; (dolist (bf (buffer-list)) - ;; (with-current-buffer bf - ;; (when (and (eq major-mode 'ess-mode) - ;; (equal ess-dialect "R")) - ;; (ess-bp-recreate-all)))) - ;; watch functionality - (if ess-tracebug-prefix - (let ((comm (key-binding ess-tracebug-prefix))) - ;; (message "ess-tracebug-prefix will be removed in future versions. Electric debug keys are now on [C-c] and [C-c C-t] maps.") - ;; (sit-for 1) - (when (commandp comm) - (define-key ess-tracebug-map ess-tracebug-prefix comm)) - (define-key ess-mode-map ess-tracebug-prefix ess-tracebug-map) - (define-key inferior-ess-mode-map ess-tracebug-prefix ess-tracebug-map) - (define-key ess-watch-mode-map ess-tracebug-prefix ess-tracebug-map))) - (run-hooks 'ess-tracebug-enter-hook) - (ess-process-put 'tracebug t) - (message "ess-tracebug mode enabled")) - (when (ess-process-get 'tracebug) ;;only when active - (ess-process-put 'tracebug nil) - ;; unset the map - (when ess-tracebug-prefix - (define-key ess-mode-map ess-tracebug-prefix nil) - (define-key inferior-ess-mode-map ess-tracebug-prefix nil)) - (ess--tb-stop) - (ess-debug-stop) - (run-hooks 'ess-tracebug-exit-hook) - (message "ess-tracebug mode disabled")))))) - -(defalias 'ess-toggle-tracebug 'ess-tracebug) - - -;;;_* TRACEBACK - -;; (defface ess--tb-last-input-face -;; '((((class grayscale) -;; (background light)) (:background "DimGray")) -;; (((class grayscale) -;; (background dark)) (:background "LightGray")) -;; (((class color) (background light) (min-colors 88)) -;; (:overline "medium blue" )) -;; (((class color) (background dark) (min-colors 88)) -;; (:overline "deep sky blue" )) -;; (((background light)) (:weight bold)) -;; (((background dark)) (:weight bold)) -;; ) -;; "Face to highlight currently debugged line." -;; :group 'ess-tracebug ) - -(defface ess-tracebug-last-input-fringe-face - '((((background light) (min-colors 88)) (:foreground "medium blue" :overline "medium blue")) - (((background dark) (min-colors 88)) (:foreground "deep sky blue" :overline "deep sky blue")) - (((background light) (min-colors 8)) (:foreground "blue")) - (((background dark) (min-colors 8)) (:foreground "syan"))) - "Face for fringe bitmap for last-input position." - :group 'ess-tracebug) - -(if (fboundp 'define-fringe-bitmap) - (define-fringe-bitmap 'last-input-arrow - [#b00011111 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b00010000 - #b11010111 - #b01111100 - #b00111000 - #b00010000] nil nil 'top)) - - -(defvar ess--tb-last-input (make-marker) - "Marker pointing to the last user input position in iESS buffer. -This is the place where `ess--tb-last-input-overlay' is moved. -Local in iESS buffers with `ess-tracebug' mode enabled.") - -(defvar ess--tb-last-input-overlay nil - "Overlay to highlight the position of last input in iESS buffer. -Local in iESS buffers.") - -(defvar-local ess--busy-count 0 - "Used to compute the busy indicator.") - -;; (unless (boundp 'ess--busy-slash) -;; (defvar ess--busy-slash '(32 ?\u2014 92 47)) -;; (setq ess--busy-slash (mapcar (lambda (el) (format " %c " el)) -;; ess--busy-slash)) -;; ) - - -(defvar ess--busy-slash '(" " " - " " \\ " " / ")) -(defvar ess--busy-B '(" " " B " " ")) -(defvar ess--busy-stars '(" " " " " * " " ** " " *** " " **** ")) -(defvar ess--busy-vbars '(" " " " " | " " || " " ||| " " |||| ")) - -(defcustom ess-busy-strings ess--busy-slash - "List of strings to replace in turn for busy indication. -The first element of the list is used as an indicator of the -process being ready (i.e. not busy). Implemented lists that you -can use `ess--busy-slash', `ess--busy-B',`ess--busy-stars', -`ess--busy-vbars'" - :group 'ess - :type '(repeat string)) - -(defvar ess--busy-timer nil - "Timer used for busy process indication.") - -(defcustom inferior-ess-replace-long+ t - "Determines if ESS replaces long + sequences in output. -If 'strip, remove all such instances. Otherwise, if non-nil, '+ -+ + + ' containing more than 4 + is replaced by -`ess-long+replacement'." - :group 'ess-tracebug - :type '(choice (const nil :tag "No replacement") - (const 'strip :tag "Replace all") - (const t :tag "Replace 4 or more +"))) - -(defvar ess-long+replacement ". + " - "Replacement used for long + prompt. -Please don't customize this or other prompt related variables. -ESS internal code assumes default R prompts.") - -(defmacro ess-copy-key (from-map to-map fun) - `(define-key ,to-map - (car (where-is-internal ,fun ,from-map)) - ,fun)) - -;;;_ + traceback functions -(defun ess--tb-make-last-input-overlay (beg end) - "Create an overlay to indicate the last input position." - (let ((ove (make-overlay beg end))) - (overlay-put ove 'before-string - (ess-tracebug--propertize "!" 'last-input-arrow 'ess-tracebug-last-input-fringe-face)) - ;; (overlay-put ove 'face 'ess--tb-last-input-face) - (overlay-put ove 'evaporate t) - ove)) - - -(defun ess--tb-start () - "Start traceback session." - (with-current-buffer (process-buffer (get-process ess-local-process-name)) - (unless ess-error-regexp-alist - (error "Can not activate the traceback for %s dialect" ess-dialect)) - (setq-local compilation-error-regexp-alist ess-error-regexp-alist) - (let (compilation-mode-font-lock-keywords) - (compilation-setup t)) - (setq next-error-function 'ess-tracebug-next-error-function) - ;; new locals - (make-local-variable 'ess--tb-last-input) - (make-local-variable 'ess--tb-last-input-overlay) - (make-local-variable 'compilation-search-path) - (setq compilation-search-path ess-tracebug-search-path) ;; TODO: make this dialect specific - (ess-tracebug--set-left-margin) - (save-excursion - (goto-char comint-last-input-start) - (setq ess--tb-last-input (point)) - (setq ess--tb-last-input-overlay - (ess--tb-make-last-input-overlay - (point-at-bol) (point-at-eol)))) - ;; busy timer - (setq mode-line-buffer-identification - (list (car (propertized-buffer-identification "%3b")) - `(:eval (nth ess--busy-count ess-busy-strings)))) ;; 'face 'mode-line-buffer-id)))) - (make-local-variable 'ess--busy-timer) - (setq ess--busy-timer - (run-with-timer 2 .5 (ess--make-busy-timer-function (get-buffer-process (current-buffer))))) - (add-hook 'kill-buffer-hook (lambda () (when ess--busy-timer (cancel-timer ess--busy-timer)))) - (add-hook 'comint-input-filter-functions 'ess-tracebug-set-last-input nil 'local) - - ;; redefine - ;; TODO: all this part should go (partially gone now) - (unless (fboundp 'orig-ess-parse-errors) - (defalias 'orig-ess-parse-errors (symbol-function 'ess-parse-errors)) - (defalias 'ess-parse-errors (symbol-function 'next-error))))) - -(defun ess--tb-stop () - "Stop ess traceback session in the current ess process." - (with-current-buffer (process-buffer (get-process ess-current-process-name)) - ;; restore original definitions - (when (equal ess-dialect "R") - (when (fboundp 'orig-ess-parse-errors) - (defalias 'ess-parse-errors (symbol-function 'orig-ess-parse-errors)) - (fmakunbound 'orig-ess-parse-errors))) - (if (local-variable-p 'ess--tb-last-input-overlay) - (delete-overlay ess--tb-last-input-overlay)) - (kill-local-variable 'ess--tb-last-input-overlay) - (kill-local-variable 'ess--tb-last-input) - (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords)) - (font-lock-ensure) - (kill-local-variable 'compilation-error-regexp-alist) - (kill-local-variable 'compilation-search-path) - (cancel-timer ess--busy-timer) - (remove-hook 'comint-input-filter-functions 'ess-tracebug-set-last-input 'local) - (setq mode-line-buffer-identification (propertized-buffer-identification "%12b")))) - -(defvar ess--dbg-forward-ring (make-ring 10) - "Ring of markers to the positions of user inputs when the -debugger or traceback events are initiated. It is used in -`ess--dbg-goto-input-point'.") - -(defvar ess--dbg-backward-ring (make-ring 10) - "Ring of markers to the positions from which `ess--dbg-goto-input-point' is called. -See the also `ess--dbg-goto-debug-point'") - -;; (setq ess-R--tb-regexp-alist '(R R2 R3 R-recover)) -;;(pop compilation-error-regexp-alist-alist) - -(defun ess-show-traceback () - "Display R traceback and last error message. -Pop up a compilation/grep/occur like buffer. Usual global key -bindings are available (\\[next-error] and \\[previous-error]) -for `next-error' and `previous-error' respectively. - -You can bind 'no-select' versions of this commands: -\(define-key compilation-minor-mode-map [(?n)] #'next-error-no-select) -\(define-key compilation-minor-mode-map [(?p)] #'previous-error-no-select)" - (interactive) - (cl-assert ess-traceback-command nil - "Not implemented for dialect %s" ess-dialect) - (ring-insert ess--dbg-forward-ring (point-marker)) - (ess-force-buffer-current "R process to use: ") - (let ((trbuf (get-buffer-create "*ess-traceback*")) - (lproc-name ess-local-process-name) - (alist ess-mode-editing-alist) - (cmd ess-traceback-command) - (inhibit-read-only t)) - (setq next-error-last-buffer trbuf) - (with-current-buffer trbuf - (setq ess-local-process-name lproc-name) - (ess-command cmd trbuf) - (goto-char (point-min)) - ;; fixme: this is R specific check - (cl-assert (not (re-search-forward "No traceback available" nil t)) nil - "No traceback available") - (ess-dirs) - (when (boundp 'ess-r-error-regexp-alist) - (setq-local compilation-error-regexp-alist ess-r-error-regexp-alist)) - (setq-local compilation-search-path ess-tracebug-search-path) - (ess-setq-vars-local alist) - (font-lock-refresh-defaults) - (compilation-minor-mode 1) - (setq next-error-function #'ess-tracebug-next-error-function) - (setq buffer-read-only t) - (pop-to-buffer trbuf)))) - -(defvar ess-call-stack-command nil) -(defun ess-show-call-stack () - "Display current call stack. -Also see `ess-show-traceback'" - (interactive) - (let ((ess-traceback-command ess-call-stack-command)) - (ess-show-traceback))) - -(defalias 'ess-show-R-traceback 'ess-show-traceback) - -(defun ess--tb-next-error-goto-process-marker () - ;; assumes current buffer is the process buffer with compilation enabled - ;; used in ess-tracebug-next-error-function - ; (with-current-buffer (process-buffer (get-process ess-local-process-name)) ; already in comint buffer .. no need - (comint-goto-process-mark) - (set-window-point (get-buffer-window) (point)) ;moves the cursor - ;; FIXME: Should jump to current-debug-position, but messes the things if in recover - ;; (when (ess-debug-is-active) - ;; (ess-debug-goto-current-debug-position) - ;; ) - ) - -(defun ess-tracebug-next-error-function (n &optional reset) - "Advance to the next error message and visits the file. -This is the value of `next-error-function' in iESS buffers." - ;; Modified version of `compilation-next-error-function'. - (interactive "p") - (if reset (goto-char (point-max))) - (let* (;; (columns compilation-error-screen-columns) ; buffer's local value - ;; (proc (or (get-buffer-process (current-buffer)) - ;; (error "Current buffer has no process"))) - (pbuff-p (get-buffer-process (current-buffer))) - (n (or n 1)) - (beg-pos ; from where the search for next error starts - (if (and pbuff-p - (>= n 0) - (comint-after-pmark-p)) - ess--tb-last-input - (point))) - (at-error t) - (msg - (condition-case nil - (compilation-next-error n nil beg-pos) - (error - (when pbuff-p - (ess--tb-next-error-goto-process-marker)) - (if (< n 0) - (message "Before first reference") - (message "Beyond last reference"));(error-message-string err)) - (setq at-error nil)))) - (msg (if (or (not pbuff-p) - (eq n 0) - (> (point) ess--tb-last-input)) - msg - (ess--tb-next-error-goto-process-marker) - (message "Beyond last-input marker") - (setq at-error nil))) - (marker (point-marker)) - loc) - (when at-error - (setq compilation-current-error (point-marker) - overlay-arrow-position (if (bolp) - compilation-current-error - (copy-marker (line-beginning-position))) - loc (if (fboundp 'compilation--message->loc) - (compilation--message->loc msg) - (car msg))) - (let* ((file (caar (nth 2 loc))) - (col (car loc)) - (line (cadr loc)) - (mkrs (ess--dbg-create-ref-marker file line col))) - (if mkrs - ;; is this really needed? Shall we go directly to the location? - (compilation-goto-locus marker (car mkrs) (cadr mkrs)) - (message "Reference to '%s' not found" file)))))) - - -(defun inferior-ess-move-last-input-overlay () - "Move the overlay to the point." - (let ((pbol (point-at-bol))) - (move-overlay ess--tb-last-input-overlay - pbol (max (- (point) 2) (+ pbol 2))))) - - -;;;_* DEBUGGER -(defgroup ess-debug nil - "Debugging for ESS" - :link '(emacs-library-link :tag "Source Lisp File" "ess-tracebug.el") - :group 'ess-tracebug - :prefix "ess-debug-") - -(defcustom ess-debug-error-action-alist - '(( "" "NONE" "NULL" ) - ( " r" "RECOVER" "utils::recover") - ( " t" "TRACEBACK" "base::traceback")) - "Alist of 'on-error' actions. -Toggled with `ess-debug-toggle-error-action'. Each element must -have the form (DISP SYMB ACTION) where DISP is the string to be -displayed in the mode line when the action is in place. SYMB is -the symbolic name of an action. ACTION is the string giving the -actual expression to be assigned to 'error' user option. See R's -help ?options for more details." - :type '(alist :key-type string - :value-type (group string string)) - :group 'ess-debug) - -(defvar ess--dbg-output-buf-prefix " *ess.dbg" - "The prefix of the buffer name the R debug output is directed to." ) - -(defvar-local ess--dbg-current-ref (make-marker) - "Current debug reference in *ess.dbg* buffers (a marker).") - -(defvar-local ess--dbg-last-ref-marker (make-marker) - "Last debug reference in *ess.dbg* buffer (a marker).") - -(defvar-local ess--dbg-buf-p nil - "This is t in ess.dbg buffers.") - -;; (defcustom ess--dbg-auto-single-key-p t -;; "If t entering the debug state triggers single-key mode. -;; Set it to nil if you want to trigger single-key mode manually -;; with the `ess-tracebug-prefix' key. -;; ") - -(defvar ess--dbg-current-debug-position (make-marker) - "Marker to the current debugged line. -It always point to the beginning of the currently debugged line -and is used by overlay-arrow. -In no-windowed Emacs an `overlay-arrow' is displayed at this position.") - -(unless window-system - (add-to-list 'overlay-arrow-variable-list 'ess--dbg-current-debug-position)) - -(defface ess-debug-current-debug-line-face - '((default (:inherit highlight))) - "Face used to highlight currently debugged line." - :group 'ess-debug) - - -(defvar ess--dbg-current-debug-overlay - (let ((overlay (make-overlay (point) (point)))) - (overlay-put overlay 'face 'ess-debug-current-debug-line-face) - (overlay-put overlay 'evaporate t) - overlay) - ;; should be global variable!! - "The overlay for currently debugged line.") - - -(defcustom ess-debug-blink-interval .2 - "Time in seconds to blink the background of the debug line. -Currently two events are defined 'ref-not-found' and 'same-ref'. -Blinking colors for these events can be customized by -corresponding faces." - :group 'ess-debug - :type 'float) - -(defface ess-debug-blink-ref-not-found-face - '((((class grayscale) (background light)) (:background "DimGray")) - (((class grayscale) (background dark)) (:background "LightGray")) - (((class color) (background light) (min-colors 88)) (:background "IndianRed4")) - (((class color) (background dark) (min-colors 88)) (:background "dark red")) - (((background light) (min-colors 8)) (:foreground "red")) - (((background dark) (min-colors 8)) (:foreground "red"))) - "Face used to blink currently debugged line's background - when the reference file is not found. See also `ess-debug-ask-for-file'" - :group 'ess-debug ) - -(defface ess-debug-blink-same-ref-face - '((((class grayscale) (background light)) (:background "DimGray")) - (((class grayscale) (background dark)) (:background "LightGray")) - (((class color) (background light) (min-colors 88)) (:background "steel blue")) - (((class color) (background dark) (min-colors 88)) (:background "midnight blue")) - (((background light) (min-colors 8)) (:foreground "blue")) - (((background dark) (min-colors 8)) (:foreground "cyan"))) - "Face used to highlight currently debugged line when new debug -reference is the same as the preceding one. It is highlighted for -`ess-debug-blink-interval' seconds." - :group 'ess-debug ) - -(defcustom ess-debug-ask-for-file nil - "If non nil, ask for file if the current debug reference is not found. - -If nil, the currently debugged line is highlighted for -`ess-debug-blink-interval' seconds." - :group 'ess-debug - :type 'boolean) - -(defcustom ess-debug-skip-first-call t - "If non-nil, skip first debugger call. - -In R first call doesn't contain source references and is skipped -by default." - :group 'ess-debug - :type 'boolean) - -(defvar ess-electric-selection-map - (let (ess-electric-selection-map) - (define-prefix-command 'ess-electric-selection-map) - ;; command-c and command-Q are not always working reliably - (define-key ess-electric-selection-map "\M-N" #'ess-debug-command-continue) - (define-key ess-electric-selection-map "\M-C" #'ess-debug-command-continue) - (define-key ess-electric-selection-map "\M-Q" #'ess-debug-command-quit) - (define-key ess-electric-selection-map "0" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "1" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "2" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "3" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "4" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "5" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "6" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "7" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "8" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "9" #'ess-debug-command-digit) - (define-key ess-electric-selection-map "?" #'ess-tracebug-show-help) - ess-electric-selection-map) - "Keymap used to define commands for single key input mode. -This commands are triggered by `ess-electric-selection' . - -\\{ess-electric-selection-map}") - -;;;_ + debug functions -(defun ess-debug-set-error-action (spec) - "Set the on-error action. -The SPEC should be one of the components of -`ess-debug-error-action-alist'." - (let ((proc (get-process ess-local-process-name))) - (if spec - (with-current-buffer (process-buffer proc) - (process-put proc 'on-error-action (car spec)) - (ess-command (format "options(error= %s )\n" (nth 2 spec)))) - (error "Unknown action")))) - -(defun ess-debug-toggle-error-action () - "Toggle the 'on-error' action. -The action list is in `ess-debug-error-action-alist'." - (interactive) - (ess-force-buffer-current) - (let* ((ev last-command-event) - (com-char (event-basic-type ev)) - (cur-action (or (ess-process-get 'on-error-action) "")) - actions act) - (setq actions - (cdr (member (assoc cur-action ess-debug-error-action-alist) - ess-debug-error-action-alist))) - (unless actions - (setq actions ess-debug-error-action-alist)) - (setq act (pop actions)) - (ess-debug-set-error-action act) - (message "On-error action set to: %s" - (propertize (cadr act) 'face 'font-lock-function-name-face)) - (while (eq (event-basic-type (setq ev (read-event))) com-char) - (unless actions - (setq actions ess-debug-error-action-alist)) - (setq act (pop actions)) - (ess-debug-set-error-action act) - (force-mode-line-update) - (message "On-error action set to: %s" - (propertize (cadr act) 'face 'font-lock-function-name-face))) - (push ev unread-command-events))) - -(defun ess--dbg-activate-overlays () - "Initialize active debug line overlays." - (move-overlay ess--dbg-current-debug-overlay - (point-at-bol) (1+ (point-at-eol)) (current-buffer)) - ;; used by overlay-arrow functionality on no-X, should be bol - (move-marker ess--dbg-current-debug-position (point-at-bol))) - -(defun ess--dbg-deactivate-overlays () - "Deletes markers and overlays. Overlay arrow remains to indicate the last debug position." - (delete-overlay ess--dbg-current-debug-overlay) - (set-marker ess--dbg-current-debug-position nil)) - - -;;;_ + Work Flow -(defun ess-debug-goto-input-event-marker () - "Jump to the point where the last debugger/traceback etc event occurred. - - Mainly useful during/after debugging, to jump to the place -from where the code was initially executed. This is an -electric-command, which means that after the command is triggered a -single key event is enough to navigate through the input-event-S-ring. -If the key-event which triggered the command is Shift modified -the input-event-S-ring is traversed backwards. - -The input-event-S-ring is a virtual object which consists of two -rings `ess--dbg-forward-ring' and `ess--dbg-backward-ring' which -are joint at their tops. - -See the more info at https://code.google.com/p/ess-tracebug/#Work-Flow" - (interactive) - (let* ((ev last-command-event) - (com-char (event-basic-type ev)) - (ring-el 0) - input-point) - (if (memq 'shift (event-modifiers ev)) - (setq input-point (ring-ref ess--dbg-backward-ring 0)) - (ring-insert ess--dbg-backward-ring (point-marker)) ;; insert in backward ring ;;TODO: check if the marker to this (close by?) position is already in the ring - (setq input-point (ring-ref ess--dbg-forward-ring 0))) - (when (marker-buffer input-point) ;; TODO: give a message here if buff is not found - (pop-to-buffer-same-window (marker-buffer input-point)) - (when (marker-position input-point) - (goto-char (marker-position input-point)))) - (while (eq (event-basic-type (event-basic-type (setq ev (read-event)))) com-char) - (if (memq 'shift (event-modifiers ev)) - (setq ring-el (1- ring-el)) - (setq ring-el (1+ ring-el))) - (if (< ring-el 0) - (setq input-point (ring-ref ess--dbg-backward-ring (- ring-el))) ;; get it from backward-ring - ;; get it from forward-ring - (setq input-point (ring-ref ess--dbg-forward-ring ring-el)) ) - (when (marker-buffer input-point) - (pop-to-buffer-same-window (marker-buffer input-point)) - (when (marker-position input-point) - (goto-char (marker-position input-point))))) - (push ev unread-command-events))) - -(defun ess-debug-goto-debug-point () - "Return to the debugging position. -Jump to markers stored in `ess--dbg-backward-ring'. If debug -session is active, first jump to current debug line. - -This is an electric-command. Shift triggers the opposite traverse -of the ring." - (interactive) - (let* ((debug-point (ring-ref ess--dbg-backward-ring 0)) - (ev last-command-event) - (com-char (event-basic-type ev)) - (ring-el 0)) - (if (ess--dbg-is-active-p) - (progn - (pop-to-buffer-same-window (marker-buffer ess--dbg-current-debug-position)) - (goto-char (marker-position ess--dbg-current-debug-position )) - (back-to-indentation)) - (pop-to-buffer-same-window (marker-buffer debug-point)) - (goto-char (marker-position debug-point))) - (while (eq (event-basic-type (setq ev (read-event))) com-char) - (if (memq 'shift (event-modifiers ev)) - (setq ring-el (1- ring-el)) - (setq ring-el (1+ ring-el))) - (setq debug-point (ring-ref ess--dbg-backward-ring ring-el)) - (when (marker-buffer debug-point) - (pop-to-buffer-same-window (marker-buffer debug-point)) - (when (marker-position debug-point) - (goto-char (marker-position debug-point))))) - (push ev unread-command-events))) - -(defun ess-debug-insert-in-forward-ring () - "Insert `point-marker' into the forward-ring." - (interactive) - (ring-insert ess--dbg-forward-ring (point-marker)) - (message "Point inserted into the forward-ring")) - -(defvar ess-debug-indicator " DB" - "String to be displayed in mode-line alongside the process name. -Indicates that ess-debug-mode is turned on. When the debugger is -in active state this string is shown in upper case and -highlighted.") - -(defvar-local ess--dbg-mode-line-debug - '(:eval (let ((proc (get-process ess-local-process-name))) - (if (and proc (process-get proc 'dbg-active)) - (let ((str ess-debug-indicator)) - (ess-debug-minor-mode 1) ; activate the keymap - (put-text-property 1 (length str) - 'face '(:foreground "white" :background "red") - str) - str) - (ess-debug-minor-mode -1) - "")))) -(put 'ess--dbg-mode-line-debug 'risky-local-variable t) - -(defvar-local ess--dbg-mode-line-error-action - '(:eval (or (and (ess-process-live-p) - (ess-process-get 'on-error-action)) - ""))) -(put 'ess--dbg-mode-line-error-action 'risky-local-variable t) - -(defun ess--dbg-remove-empty-lines (string) - "Remove empty lines from STRING (which interfere with evals) during debug. -This function is placed in `ess-presend-filter-functions'." - (if (and ess--dbg-del-empty-p (ess-process-get 'dbg-active)) - (replace-regexp-in-string "\n\\s *$" "" string) - string)) - - -(defun ess-debug-start () - "Start the debug session. -Add to ESS the interactive debugging functionality, breakpoints, -watch and loggers. Integrates into ESS and iESS modes by binding -`ess-tracebug-map' to `ess-tracebug-prefix' in -`ess-mode-map' and `inferior-ess-mode-map' respectively." - (interactive) - (let ((dbuff (get-buffer-create (concat ess--dbg-output-buf-prefix "." ess-current-process-name "*"))) ;TODO: make dbuff a string! - (proc (ess-get-process ess-local-process-name)) - (lpn ess-local-process-name)) - (process-put proc 'dbg-buffer dbuff); buffer were the look up takes place - (process-put proc 'dbg-active nil) ; t if the process is in active debug state. - ; Active debug states are usually those, in which prompt start with Browser[d]> - (set-process-filter proc 'inferior-ess-tracebug-output-filter) - (with-current-buffer (process-buffer proc) - (unless (equal ess-dialect "R") - (error "Can not activate the debugger for %s dialect" ess-dialect)) - (add-to-list 'ess--mode-line-process-indicator 'ess--dbg-mode-line-debug t) - (add-to-list 'ess--mode-line-process-indicator 'ess--dbg-mode-line-error-action t) - - (add-hook 'ess-presend-filter-functions 'ess--dbg-remove-empty-lines nil 'local)) - (with-current-buffer dbuff - (setq ess-local-process-name lpn) - (buffer-disable-undo) - ;; (setq buffer-read-only nil) - (make-local-variable 'overlay-arrow-position) ;; indicator for next-error functionality in the *ess.dbg*, useful?? - (goto-char (point-max)) - (setq ess--dbg-buf-p t ;; true if in *ess.dbg* buffer - ess--dbg-current-ref (point-marker) ;; used by goto-error functionality - ess--dbg-last-ref-marker (point-marker) ;; gives marker to reference of the last debugged line - ) - ;; (beginning-of-line) - ;; (setq buffer-read-only t) - ))) - -(defun ess-debug-stop () - "End the debug session. -Kill the *ess.dbg.[R_name]* buffer." - ;;; process plist is not removed, TODO?low priority - (interactive) - (let ((proc (get-process ess-current-process-name))) ;;local? - (with-current-buffer (process-buffer proc) - (if (member ess-dialect '("XLS" "SAS" "STA")) - (error "Can not deactivate the debugger for %s dialect" ess-dialect)) - (delq 'ess--dbg-mode-line-debug ess--mode-line-process-indicator) - (delq 'ess--dbg-mode-line-error-action ess--mode-line-process-indicator) - (remove-hook 'ess-presend-filter-functions 'ess--dbg-remove-empty-lines 'local)) - (set-process-filter proc 'inferior-ess-output-filter) - (kill-buffer (process-get proc 'dbg-buffer)) - (process-put proc 'dbg-buffer nil) - (process-put proc 'dbg-active nil) - ;; (when (buffer-live-p ess--dbg-buffer) - ;; ;; (with-current-buffer ess--dbg-buffer - ;; ;; (set-buffer-modified-p nil) - ;; ;; ) - ;; (kill-buffer ess--dbg-buffer) - ;; ) - )) - - -(defun ess--make-busy-timer-function (process) - "Display the spinner of prompt if PROCESS is busy." - `(lambda () - (let ((pb ,process)) - (when (eq (process-status pb) 'run) ;; only when the process is alive - (with-current-buffer (process-buffer pb) - (if (not (process-get pb 'busy)) ;; if ready - (when (> ess--busy-count 0) - (setq ess--busy-count 0) - (force-mode-line-update) - (redisplay)) - (setq ess--busy-count (1+ (mod ess--busy-count (1- (length ess-busy-strings))))) - (force-mode-line-update) - (redisplay))))))) - -;; (ess--make-busy-prompt-function (get-process "R")) - -(defun ess--dbg-is-active-p () - "Return t if the current R process is in active debugging state." - (and (ess-process-live-p) - (ess-process-get 'dbg-active))) - -(defun ess--dbg-is-recover-p () - "Return t if the current R process is in active debugging state." - (and (ess-process-live-p) - (ess-process-get 'is-recover))) - -(defun ess-debug-active-p (&optional proc) - (and (ess-process-live-p proc) - (or (ess-process-get 'dbg-active proc) - (ess-process-get 'is-recover proc)))) - -(defvar ess--dbg-regexp-reference "debug \\w+ +\\(.+\\)#\\([0-9]+\\):") -(defvar ess--dbg-regexp-jump "debug \\w+ ") ;; debug at ,debug bei ,etc -(defvar ess--dbg-regexp-skip - ;; don't anchor to bol; secondary prompt can occur before (anything else?) - ;; "\\(\\(?:Called from: \\)\\|\\(?:debugging in: \\)\\|\\(?:#[0-9]*: +recover()\\)\\)") - "\\(\\(?:Called from: \\)\\|\\(?:#[0-9]*: +recover()\\)\\)") - -(defvar ess--dbg-regexp-no-skip - ;; exceptions for first skip (magrittr) - "debug_pipe") - -(defvar ess--dbg-regexp-debug "\\(\\(?:Browse[][0-9]+\\)\\|\\(?:debug: \\)\\)") -(defvar ess--dbg-regexp-selection "\\(Selection: \\'\\)") -(defvar ess--dbg-regexp-input (concat ess--dbg-regexp-debug "\\|" - ess--dbg-regexp-selection)) - -(defvar ess--suppress-next-output? nil) - - - -;;; MPI - -;; http://jkorpela.fi/chars/c0.html -;; https://en.wikipedia.org/wiki/ANSI_escape_code#Escape_sequences -(defvar ess-mpi-message-start-delimiter "_") -(defvar ess-mpi-message-field-separator "") -(defvar ess-mpi-message-end-delimiter "\\") - -(define-obsolete-variable-alias 'ess-mpi-alist 'ess-mpi-handlers "ESS 19.04") -(defvar ess-mpi-handlers - '(("message" . message) - ("error" . ess-mpi:error) - ("eval" . ess-mpi:eval) - ("y-or-n" . ess-mpi:y-or-n)) - "Alist of the MPI handlers. -Each element is of the form (TYPE . HANDLER), where TYPE is the -message type and HANDLER is a function (symbol) to be called on -the payload list of each message.") - -(defun ess-mpi:error (msg) - (error "MPI error: %s" msg)) - -(defun ess-mpi:eval (str &optional callback) - "Read STR and evaluate as Emacs expression. -If present, the CALLBACK string is passed through `format' with -returned value from EXPR and then sent to the subprocess." - (let ((result (eval (read str)))) - (when callback - (ess-send-string (ess-get-process) (format callback result))))) - -(defun ess-mpi:y-or-n (prompt callback) - "Ask `y-or-n-p' with PROMPT. -The CALLBACK string is passed through `format' with returned -value from EXPR and then sent to the subprocess." - (let ((result (y-or-n-p prompt))) - (when callback - (let ((result (if result "TRUE" "FALSE"))) - (ess-send-string (ess-get-process) (format callback result)))))) - -(defun ess-mpi-convert (el) - (cond - ((string= el "nil") nil) - ((string= el "t") t) - (t el))) - -(defun ess-mpi-handle-messages (buf) - "Handle all mpi messages in BUF and delete them. -The MPI message has the form TYPEFIELD... where TYPE is the -type of the messages on which handlers in `ess-mpi-handlers' are -dispatched. And FIELDs are strings. Return :incomplete if BUF -ends with an incomplete message." - (let ((obuf (current-buffer)) - (out nil)) - (with-current-buffer buf - (goto-char (point-min)) - ;; This should be smarter because Emacs might cut it in the middle of the - ;; message. In practice this almost never happen because we are - ;; accumulating output into the cache buffer. - (while (search-forward ess-mpi-message-start-delimiter nil t) - (let ((mbeg0 (match-beginning 0)) - (mbeg (match-end 0))) - (if (search-forward ess-mpi-message-end-delimiter nil t) - (let* ((mend (match-beginning 0)) - (mend0 (match-end 0)) - (msg (buffer-substring mbeg mend)) - (payload (mapcar #'ess-mpi-convert - (split-string msg ess-mpi-message-field-separator))) - (head (pop payload)) - (handler (cdr (assoc head ess-mpi-handlers)))) - (unwind-protect - (if handler - (with-current-buffer obuf - (apply handler payload)) - (error "No handler defined for MPI message '%s" head)) - (goto-char mbeg0) - (delete-region mbeg0 mend0))) - (setq out :incomplete)))) - out))) - -(defun ess--replace-long+-in-prompt (prompt is-final) - "Replace long + + + in PROMPT based on `inferior-ess-replace-long+' value. -If IS-FINAL means that PROMPT occurs at the end of the process -chunk. If non-nil, special care is taken not to drop last '+' -value as it might be a continuation prompt." - ;; see #576 for interesting input examples - (let ((len (length prompt))) - (if (or (null inferior-ess-replace-long+) - (< len 2)) - prompt - (let ((last+ (eq (elt prompt (- len 2)) ?+))) - (cond - ((eq inferior-ess-replace-long+ 'strip) - (if (and last+ is-final) - "+ " - "> ")) - ((eq inferior-ess-replace-long+ t) - (let ((prompt (replace-regexp-in-string "\\(\\+ \\)\\{2\\}\\(\\+ \\)+" - ess-long+replacement prompt))) - (if (and last+ (not is-final)) - ;; append > for aesthetic reasons - (concat prompt "> ") - prompt))) - (t (error "Invalid values of `inferior-ess-replace-long+'"))))))) - -(defun ess--offset-output (prev-prompt str) - "Add suitable offset to STR given the preceding PREV-PROMPT." - (if prev-prompt - (let ((len (length prev-prompt))) - ;; prompts have at least 2 chars - (if (eq (elt prev-prompt (- len 2)) ?+) - ;; when last + append > for aesthetic reasons - (concat "> \n" str) - (if (eq (elt str 0) ?\n) - ;; don't insert empty lines - str - (concat "\n" str)))) - str)) - -(defun ess--flush-accumulated-output (proc) - "Flush accumulated output of PROC into its output buffer. -Insertion happens chunk by chunk. A chunk is a region between two -prompts." - (let* ((abuf (ess--accumulation-buffer proc)) - (pbuf (process-buffer proc)) - (visibly (process-get proc :eval-visibly)) - (nowait (eq visibly 'nowait)) - (flush-timer (process-get proc 'flush-timer))) - (when (> (buffer-size abuf) 0) - (when (timerp flush-timer) - (cancel-timer flush-timer)) - (if (eq (buffer-local-value 'major-mode pbuf) 'fundamental-mode) - ;; FIXME: this cannot be, ess-command changes the filter - ;; Just in case if we are in *ess-command* buffer; restart the timer. - (process-put proc 'flush-timer - (run-at-time .02 nil #'ess--flush-accumulated-output proc)) - ;; Incomplete mpi should hardly happen. Only on those rare occasions - ;; when an mpi is issued after a long task and split by the Emacs input - ;; handler, or mpi printing itself takes very long. - (unless (eq :incomplete (ess-mpi-handle-messages abuf)) - (with-current-buffer abuf - (goto-char (point-min)) - (let ((case-fold-search nil)) - (when (re-search-forward "Error\\(:\\| +in\\)" nil t) - (unless (get-buffer-window pbuf 'visible) - (display-buffer (process-buffer proc) nil t)))) - (goto-char (point-min)) - ;; First long + + in the output mirrors the sent input by the user and - ;; is unnecessary in nowait case. A single + can be a continuation in - ;; the REPL, thus we check if there is an extra output after the + . - (when nowait - (when (looking-at "\\([+>] \\)\\{2,\\}\n?") - (goto-char (match-end 0)) - (when (eq (point) (point-max)) - ;; if this is the last prompt in the output back-up one prompt - ;; (cannot happen after \n) - (backward-char 2)))) - (let ((do-clean (not (eq visibly t))) - (pos2 (point)) - (pos1 (point)) - (tpos nil) - (prompt nil) - (regexp (if nowait - ;; we cannot disambiguate printed input fields and - ;; prompts in output in this case; match 2+ pluses or - ;; > and 2+ spaces - "\\(^\\([+>] \\)\\{2,\\}\\)\\|\\(> \\) +" - "^\\([+>] \\)+")) - (prev-prompt (process-get proc 'prev-prompt))) - (while (re-search-forward regexp nil t) - (setq pos1 (match-beginning 0) - tpos (if nowait - (or (match-end 1) (match-end 3)) - (match-end 0))) - ;; for debugging in R:accum window in order to see the pointer moving - ;; (set-window-point (get-buffer-window) tpos) - (when (> pos1 pos2) - (let ((str (buffer-substring pos2 pos1))) - (comint-output-filter proc (ess--offset-output prev-prompt str)))) - (setq pos2 tpos) - (setq prompt (let ((prompt (buffer-substring pos1 pos2))) - (if do-clean - (ess--replace-long+-in-prompt prompt (eq pos2 (point-max))) - prompt))) - ;; Cannot bypass this trivial call to comint-output-filter because - ;; external tools could rely on prompts (org-babel [#598] for - ;; example). Setting dummy regexp in order to avoid comint erasing - ;; this prompt which contrasts to how we output prompts in all - ;; other cases. - (with-current-buffer pbuf - (let ((comint-prompt-regexp "^$")) - (comint-output-filter proc prompt))) - (setq prev-prompt (and do-clean prompt) - pos1 pos2)) - ;; insert last chunk if any - (unless (eq pos1 (point-max)) - (let ((str (buffer-substring-no-properties pos1 (point-max)))) - (comint-output-filter proc (ess--offset-output prev-prompt str)) - (setq prev-prompt nil))) - (process-put proc 'prev-prompt prev-prompt) - (process-put proc 'flush-time (and (process-get proc 'busy) - (float-time))) - (erase-buffer)))))))) - -(defun inferior-ess-tracebug-output-filter (proc string) - "Standard output filter for the inferior ESS process. -When `ess-debug' is active, this is the filter. Call -`inferior-ess-output-filter'. Check for debug -reg-expressions (see `ess--dbg-regexp-debug',...), when found -puts iESS in the debugging state. If in debugging state, mirrors -the output into *ess.dbg* buffer." - (let* ((is-iess (or (derived-mode-p 'ess-watch-mode) - (derived-mode-p 'inferior-ess-mode))) - (pbuf (process-buffer proc)) - (abuf (ess--accumulation-buffer proc)) - (dbuff (process-get proc 'dbg-buffer)) - (wbuff (get-buffer ess-watch-buffer)) - (was-in-dbg (process-get proc 'dbg-active)) - (was-in-recover (process-get proc 'is-recover)) - (input-point (point-marker)) - (match-jump (string-match ess--dbg-regexp-jump string)) - (match-input (string-match ess--dbg-regexp-input string)) - (match-selection (and match-input - (match-string 2 string))) ;; Selection: - (match-skip (and ess-debug-skip-first-call - (string-match ess--dbg-regexp-skip string) - (not (string-match ess--dbg-regexp-no-skip string)))) - (match-dbg (or match-skip (and match-input (not match-selection)))) - (is-ready (inferior-ess--set-status proc string)) - (new-time (float-time)) - (last-time (process-get proc 'flush-time)) - (flush-timer (process-get proc 'flush-timer))) - - ;; current-buffer is still the user's input buffer here - (ess--if-verbose-write-process-state proc string) - (inferior-ess-run-callback proc string) - (process-put proc 'is-recover match-selection) - - (if (or (process-get proc 'suppress-next-output?) - ess--suppress-next-output?) - - ;; works only for suppressing short output, enough for now (for callbacks) - (process-put proc 'suppress-next-output? nil) - - (with-current-buffer abuf - (goto-char (point-max)) - (insert string)) - - ;; cancel the timer each time we enter this filter - (when (timerp flush-timer) - (cancel-timer flush-timer) - (process-put proc 'flush-timer nil)) - - (unless last-time ;; don't flush for the first time - (setq last-time new-time) - (process-put proc 'flush-time new-time)) - - ;; flush periodically - (let ((fast-flush (or is-ready - ;; for the sake of ess-eval-linewise - (process-get proc 'sec-prompt)))) - (if (or - ;; theoretically we should flush asynchronously in all cases but - ;; somewhat unexpectedly it introduces much more randomness during - ;; batch testing. TODO: flush directly for now and either remove or - ;; improve on the next refactoring iteration - fast-flush - (> (- new-time last-time) .5) - (bound-and-true-p edebug-mode) - ;; the flush is not getting called if the third party call - ;; accept-process-output in a loop (e.g. org-babel-execute-src-block) - (bound-and-true-p org-babel-current-src-block-location)) - (ess--flush-accumulated-output proc) - ;; Setup new flush timer. Ideally also for fast-flush case in order to - ;; avoid detecting intermediate prompts as end-of-output prompts. - (let ((timeout (if fast-flush .01 .2))) - (process-put proc 'flush-timer - (run-at-time timeout nil #'ess--flush-accumulated-output proc)))))) - - ;; WATCH - (when (and is-ready wbuff) ;; refresh only if the process is ready and wbuff exists, (not only in the debugger!!) - (ess-watch-refresh-buffer-visibly wbuff)) - - ;; JUMP to line if debug expression was matched - (when match-jump - (with-current-buffer dbuff ;; insert string in *ess.dbg* buffer - (goto-char (point-max)) - (insert (concat "|-" string "-|"))) - (ess--dbg-goto-last-ref-and-mark dbuff is-iess)) - - ;; (with-current-buffer dbuff ;; un-comment to see the value of STRING just before debugger exists - ;; (let ((inhibit-read-only t)) - ;; (goto-char (point-max)) - ;; (insert (concat " ---\n " string "\n ---")) - ;; )) - - ;; SKIP if needed - (when (and match-skip (not was-in-recover)) - (process-send-string proc "n\n")) - - ;; EXIT the debugger - (when (and was-in-dbg - (not (or match-jump match-dbg)) - (or is-ready match-selection)) - (ess--dbg-deactivate-overlays) - (process-put proc 'dbg-active nil) - ;; (message "|<-- exited debugging -->|") - (when wbuff - (ess-watch-refresh-buffer-visibly wbuff))) - - ;; ACTIVATE the debugger if entered for the first time - (when (and (not was-in-dbg) - (not match-selection) - (or match-jump match-dbg)) - (unless is-iess - (ring-insert ess--dbg-forward-ring input-point)) - (process-put proc 'dbg-active t) - (message - (ess--debug-keys-message-string)) - (unless match-jump - ;; no source reference, simply show the inferior - (display-buffer pbuf))) - - (when match-selection ;(and (not was-in-recover) match-selection) - (ess-electric-selection t)))) - - -(defvar ess-debug-minor-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "M-C") #'ess-debug-command-continue) - (define-key map [(control meta ?C)] #'ess-debug-command-continue-multi) - (define-key map (kbd "M-N") #'ess-debug-command-next) - (define-key map [(control meta ?N)] #'ess-debug-command-next-multi) - (define-key map (kbd "M-Q") #'ess-debug-command-quit) - (define-key map (kbd "M-U") #'ess-debug-command-up) - map) - "Keymap active when ESS process is in debugging state. -\\{ess-debug-minor-mode-map}") - - -(define-minor-mode ess-debug-minor-mode - "Minor mode activated when ESS process is in debugging state." - :lighter nil - :keymap ess-debug-minor-mode-map) - -(defun ess--dbg-goto-last-ref-and-mark (dbuff &optional other-window) - "Open the most recent debug reference, and set all the necessary marks and overlays. -It's called from `inferior-ess-tracebug-output-filter'. DBUFF -must be the *ess.dbg* buffer associated with the process. If -OTHER-WINDOW is non nil, attempt to open the location in a -different window." - (let (t-debug-position ref) - (with-current-buffer dbuff - (setq ref (ess--dbg-get-next-ref -1 (point-max) ess--dbg-last-ref-marker - ess--dbg-regexp-reference)) ; sets point at the end of found ref - (when ref - (move-marker ess--dbg-last-ref-marker (point-at-eol)) - ;; each new step repositions the current-ref! - (move-marker ess--dbg-current-ref ess--dbg-last-ref-marker))) - (when ref - (let ((buf (apply 'ess--dbg-goto-ref other-window ref))) - (if buf - ;; if referenced buffer has been found, put overlays: - (with-current-buffer buf - (setq t-debug-position (copy-marker (point-at-bol))) - (if (equal t-debug-position ess--dbg-current-debug-position) - (progn ;; highlights the overlay for ess--dbg-blink-interval seconds - (overlay-put ess--dbg-current-debug-overlay 'face 'ess--dbg-blink-same-ref-face) - (run-with-timer ess-debug-blink-interval nil - (lambda () - (overlay-put ess--dbg-current-debug-overlay 'face 'ess-debug-current-debug-line-face)))) - ;; else - (ess--dbg-activate-overlays))) - ;;else, buffer is not found: highlight and give the corresponding message - (overlay-put ess--dbg-current-debug-overlay 'face 'ess--dbg-blink-ref-not-found-face) - (run-with-timer ess-debug-blink-interval nil - (lambda () - (overlay-put ess--dbg-current-debug-overlay 'face 'ess-debug-current-debug-line-face))) - (message "Reference %s not found" (car ref))))))) - -(defun ess--dbg-goto-ref (other-window file line &optional col) - "Opens the reference given by FILE, LINE and COL. -Try to open in a different window if OTHER-WINDOW is nil. Return -the buffer if found, or nil otherwise be found. -`ess--dbg-find-buffer' is used to find the FILE and open the -associated buffer. If FILE is nil return nil." - (let ((mrk (car (ess--dbg-create-ref-marker file line col))) - (lpn ess-local-process-name)) - (when mrk - (let ((buf (marker-buffer mrk))) - (if (not other-window) - (pop-to-buffer-same-window buf) - (let ((this-frame (window-frame (get-buffer-window (current-buffer))))) - (display-buffer buf) - ;; simple save-frame-excursion - (unless (eq this-frame (window-frame (get-buffer-window buf t))) - (ess-select-frame-set-input-focus this-frame)))) - ;; set or re-set to lpn as this is the process with debug session on - (with-current-buffer buf - (setq ess-local-process-name lpn) - (goto-char mrk) - (set-window-point (get-buffer-window buf) mrk)) - buf)))) - -;; temporary, hopefully org folks implement something similar -(defvar org-babel-tangled-file nil) -(declare-function org-babel-tangle-jump-to-org "ob-tangle.el") - -(defun ess--dbg-create-ref-marker (file line &optional col) - "Create markers to the reference given by FILE, LINE and COL. -Return list of two markers MK-start and MK-end. MK-start is the -position of error. Mk-end is the end of the line where error -occurred. If buffer associated with FILE is not found, or line is -nil, or TB-INDEX is not found return nil." - (if (stringp line) (setq line (string-to-number line))) - (if (stringp col) (setq col (string-to-number col))) - (let* ((srcref (gethash file ess--srcrefs)) - (file (replace-regexp-in-string "^\n" "" ;; hack for gnu regexp - (or (car srcref) file))) - (tb-index (cadr srcref)) - (buffer (ess--dbg-find-buffer file)) - pos) - (when (and buffer line) - (save-excursion - (with-current-buffer buffer - (save-restriction - (widen) ;; how does this behave in narrowed buffers? tothink: - (goto-char 1) - (setq pos (point)) - (when tb-index - (while (and (not (eq tb-index (get-text-property pos 'tb-index))) - (setq pos (next-single-property-change pos 'tb-index))))) - (unless pos - ;; use beg position if index not found - (setq pos (nth 2 srcref))) - (when pos - (goto-char pos) - (forward-line (1- line)) - (if col - (goto-char (+ (point-at-bol) col)) - (back-to-indentation)) - (when (bound-and-true-p org-babel-tangled-file) - (org-babel-tangle-jump-to-org)) - (list (point-marker) (copy-marker (point-at-eol)))))))))) - -(defun ess--dbg-find-buffer (filename) - "Find a buffer for file FILENAME. -If FILENAME is not found at all, ask the user where to find it if -`ess--dbg-ask-for-file' is non-nil. Search the directories in -`ess-tracebug-search-path'." - (let ((dirs (append - (ess-r-package-source-dirs) - (cl-loop for d in ess-tracebug-search-path - append (ess-r-package--all-source-dirs d)))) - buffer name) - (setq dirs (cons default-directory dirs)) ;; TODO: should be R working dir - ;; 1. search already open buffers for match (associated file might not even exist yet) - (cl-dolist (bf (buffer-list)) - (with-current-buffer bf - (when (and buffer-file-name - (or (and (file-name-absolute-p filename) - (string-match (format "%s\\'" filename) buffer-file-name)) - (equal filename (file-name-nondirectory buffer-file-name)))) - (setq buffer bf) - (cl-return)))) - ;; 2. The file name is absolute. Use its explicit directory as - ;; the first in the search path, and strip it from FILENAME. - (when (and (null buffer) - (file-name-absolute-p filename)) - (setq filename (abbreviate-file-name (expand-file-name filename)) - dirs (cons (file-name-directory filename) dirs) - filename (file-name-nondirectory filename))) - ;; 3. Now search the path. - (while (and (null buffer) dirs) - (let ((thisdir (pop dirs))) - (setq name (expand-file-name filename thisdir) - buffer (and (file-exists-p name) - (find-file-noselect name))))) - ;; 4. Ask for file if not found (tothink: maybe remove this part?) - (if (and (null buffer) - ess-debug-ask-for-file) - (save-excursion ;This save-excursion is probably not right. - (let* ((pop-up-windows t) - (name (read-file-name - (format "Find next line in (default %s): " filename) - nil filename t nil)) - (origname name)) - (cond - ((not (file-exists-p name)) - (message "Cannot find file `%s'" name) - (ding) (sit-for 2)) - ((and (file-directory-p name) - (not (file-exists-p - (setq name (expand-file-name filename name))))) - (message "No `%s' in directory %s" filename origname) - (ding) (sit-for 2)) - (t - (setq buffer (find-file-noselect name))))))) - ;; nil if not found - buffer)) - -(defun ess--dbg-get-next-ref (n &optional pt BOUND REG nF nL nC) - "Move point to the next reference in the *ess.dbg* buffer. - -Must be called from *ess.dbg* buffer. -It returns the reference in the form (file line col) /all strings/ , -or NIL if not found . Prefix arg N says how many error messages -to move forwards (or backwards, if negative). Optional arg PT, -if non-nil, specifies the value of point to start looking for the -next message, default to (point). BOUND is the limiting position -of the search. REG is the regular expression to search with. nF -- sub-expression of REG giving the 'file'; defaults to 1. nL - -giving the 'line'; defaults to 2. nC - sub-expr giving the -'column'; defaults to 3." - (unless ess--dbg-buf-p - (error "Not in *ess.dbg* buffer")) - (setq nF (or nF 1) - nL (or nL 2) - nC (or nC 3)) - (or pt (setq pt (point))) - ;; (message "ess--dbg-last-ref-marker%s vs pt%s vs point-max%s" ess--dbg-last-ref-marker pt (point-max)) - (goto-char pt) - (if (search-forward-regexp REG BOUND t n) - (list (match-string nF) (match-string-no-properties nL) (match-string-no-properties nC)) - nil)) - -(defun ess--debug-keys-message-string (&optional map) - (let ((overriding-local-map (or map ess-debug-minor-mode-map))) - (substitute-command-keys - (mapconcat 'identity - '("(\\[ess-debug-command-continue])cont" - "(\\[ess-debug-command-continue-multi])cont-multi" - "(\\[ess-debug-command-next])next" - "(\\[ess-debug-command-next-multi])next-multi" - "(\\[ess-debug-command-up])up" - "(\\[ess-debug-command-quit])quit") - " ")))) - -(defun ess-electric-selection (&optional wait) - "Call commands defined in `ess-electric-selection-map'. -Single-key input commands are those, which once executed do not -require the prefix command for subsequent invocation. - -If WAIT is t, wait for next input and ignore the keystroke which -triggered the command." - (interactive) - (ess--execute-electric-command ess-electric-selection-map - "Selection: " wait - (not (ess-process-get 'is-recover)))) - -(defun ess-debug-command-digit (&optional ev) - "Digit commands in selection mode. -If supplied, EV must be a proper key event or a string representing the digit." - (interactive) - (ess-force-buffer-current) - (unless (ess--dbg-is-recover-p) - (error "Recover is not active")) - (unless ev - (setq ev last-command-event)) - (let* ((ev-char (if (stringp ev) - ev - (char-to-string (event-basic-type ev)))) - (proc (get-process ess-current-process-name)) - (mark-pos (marker-position (process-mark proc))) - (comint-prompt-read-only nil) - prompt depth) - (with-current-buffer (process-buffer proc) - (goto-char mark-pos) - (save-excursion - (when (re-search-backward "\\(?: \\|^\\)\\([0-9]+\\):[^\t]+Selection:" ess--tb-last-input t) - (setq depth (string-to-number (match-string 1))) - (when (> depth 9) - (setq ev-char (ess-completing-read "Selection" (mapcar 'number-to-string - (number-sequence depth 0 -1)) - nil t ev-char nil))))) - (setq prompt (delete-and-extract-region (point-at-bol) mark-pos)) - (insert (concat prompt ev-char "\n")) - (ess-send-string proc ev-char) - (move-marker (process-mark proc) (max-char))))) - -(defun ess-debug-command-next () - "Step next in debug mode. -Equivalent to 'n' at the R prompt." - (interactive) - (ess-force-buffer-current) - (unless (ess--dbg-is-active-p) - (error "Debugger is not active")) - (if (ess--dbg-is-recover-p) - (ess-send-string (ess-get-process) "0") - (ess-send-string (ess-get-process) "n"))) - -(defun ess-debug-command-next-multi (&optional N) - "Ask for N and step (n) N times in debug mode." - (interactive) - (ess-force-buffer-current) - (unless (ess--dbg-is-active-p) - (error "Debugger is not active")) - (let ((N (or N (read-number "Number of steps: " 10))) - (ess--suppress-next-output? t)) - (while (and (ess--dbg-is-active-p) (> N 0)) - (ess-debug-command-next) - (ess-wait-for-process) - (setq N (1- N)))) - (ess-debug-command-next)) - -(defun ess-debug-command-continue-multi (&optional N) - "Ask for N, and continue (c) N times in debug mode." - (interactive) - (ess-force-buffer-current) - (unless (ess--dbg-is-active-p) - (error "Debugger is not active")) - (let ((N (or N (read-number "Number of continuations: " 10))) - (ess--suppress-next-output? t)) - (while (and (ess--dbg-is-active-p) (> N 1)) - (ess-debug-command-continue) - (ess-wait-for-process) - (setq N (1- N)))) - (ess-debug-command-continue)) - -(defun ess-debug-command-up () - "Step up one call frame. -Equivalent to 'n' at the R prompt." - (interactive) - (ess-force-buffer-current) - (unless (ess--dbg-is-active-p) - (error "Debugger is not active")) - (let ((up-cmd "try(browserSetDebug(), silent=T)\nc\n")) - (ess-send-string (ess-get-process) up-cmd))) - -;; (defun ess-debug-previous-error (&optional ev) -;; "Go to previous reference during the debug process. -;; R doesn't support step backwards. This command just takes you through -;; debug history." -;; (interactive) -;; (previous-error)) - -(defun ess-debug-command-quit () - "Quits the browser/debug in R process. -Equivalent of `Q' at the R prompt." - (interactive) - (ess-force-buffer-current) - (cond ((ess--dbg-is-recover-p) - (ess-send-string (ess-get-process) "0" t)) - ;; if recover is called in a loop the following stalls Emacs - ;; (ess-wait-for-process proc nil 0.05) - ((ess--dbg-is-active-p) - (ess-send-string (ess-get-process) "Q" t)) - (t - (error "Debugger is not active")))) - -(defun ess-debug-command-continue () - "Continue the code execution. -Equivalent of `c' at the R prompt." - (interactive) - (ess-force-buffer-current) - (cond ((ess--dbg-is-recover-p) - (ess-send-string (ess-get-process) "0")) - ((ess--dbg-is-active-p) - (ess-send-string (ess-get-process) "c")) - (t - (error "Debugger is not active")))) - -(defun ess-tracebug-set-last-input (&rest _args) - "Move `ess--tb-last-input' marker to the process mark. -ARGS are ignored to allow using this function in process hooks." - (let* ((last-input-process (get-process ess-local-process-name)) - (last-input-mark (copy-marker (process-mark last-input-process)))) - (with-current-buffer (process-buffer last-input-process) - (when (local-variable-p 'ess--tb-last-input) ;; TB might not be active in all processes - (save-excursion - (setq ess--tb-last-input last-input-mark) - (goto-char last-input-mark) - (inferior-ess-move-last-input-overlay)))))) - -;;;_ + BREAKPOINTS - -(defface ess-bp-fringe-inactive-face - '((((class color) (background light) (min-colors 88)) (:foreground "DimGray")) - (((class color) (background dark) (min-colors 88)) (:foreground "LightGray")) - (((background light) (min-colors 8)) (:foreground "blue")) - (((background dark) (min-colors 8)) (:foreground "cyan"))) - "Face used to highlight inactive breakpoints." - :group 'ess-debug) - -(defface ess-bp-fringe-logger-face - '((((class color) (background light) (min-colors 88)) (:foreground "dark red")) - (((class color) (background dark) (min-colors 88)) (:foreground "tomato1")) - (((background light) (min-colors 8)) (:foreground "blue")) - (((background dark) (min-colors 8)) (:foreground "cyan"))) - "Face used to highlight loggers." - :group 'ess-debug) - -(defface ess-bp-fringe-browser-face - '((((class color) (background light) (min-colors 88)) (:foreground "medium blue")) - (((class color) (background dark) (min-colors 88)) (:foreground "deep sky blue")) - (((background light) (min-colors 8)) (:foreground "blue")) - (((background dark) (min-colors 8)) (:foreground "cyan"))) - "Face used to highlight 'browser' breakpoints." - :group 'ess-debug) - -(defface ess-bp-fringe-recover-face - '((((class color) (background light) (min-colors 88)) (:foreground "dark magenta")) - (((class color) (background dark) (min-colors 88)) (:foreground "magenta")) - (((background light) (min-colors 8)) (:foreground "magenta")) - (((background dark) (min-colors 8)) (:foreground "magenta"))) - "Face used to highlight 'recover' breakpoints fringe." - :group 'ess-debug) - -(defun ess--bp-pipe-block-p () - (save-excursion - (let ((inhibit-point-motion-hooks t) - (inhibit-field-text-motion t)) - (forward-line -1) - (end-of-line) - (looking-back "%>%[ \t]*" (point-at-bol))))) - -(defvar ess--bp-identifier 1) -(defcustom ess-bp-type-spec-alist - '((pipe ".ess_pipe_browser() %%>%%" "B %>%\n" filled-square ess-bp-fringe-browser-face ess--bp-pipe-block-p) - (browser "browser(expr=is.null(.ESSBP.[[%s]]));" "B>\n" filled-square ess-bp-fringe-browser-face) - (recover "recover()" "R>\n" filled-square ess-bp-fringe-recover-face)) - "List of lists of breakpoint types. -Each sublist has five elements: -1- symbol giving the name of specification -2- R expression to be inserted (%s is substituted with unique identifier). -3- string to be displayed instead of the expression -4- fringe bitmap to use -5- face for fringe and displayed string -6- optional, a function which should return nil if this BP doesn't apply to current context." - :group 'ess-debug - :type '(alist :key-type symbol - :value-type (group string string symbol face))) - -(defcustom ess-bp-inactive-spec - '(inactive "##" filled-square ess-bp-fringe-inactive-face) - "List giving the inactive breakpoint specifications." - ;; List format is identical to that of the elements of - ;; `ess-bp-type-spec-alist' except that the second element giving - ;; the R expression is meaningless here." ;;fixme: second element is missing make it nil for consistency with all other specs - :group 'ess-debug - :type 'list) - -(defcustom ess-bp-conditional-spec - '(conditional "browser(expr={%s})" "CB[ %s ]>\n" question-mark ess-bp-fringe-browser-face) - "List giving the conditional breakpoint specifications. -List format is identical to that of the elements of -`ess-bp-type-spec-alist'. User is asked for the conditional -expression to be replaced instead of %s in the second and third -elements of the specifications." - :group 'ess-debug - :type 'list) - -(defcustom ess-bp-logger-spec - '(logger ".ess_log_eval('%s')" "L[ \"%s\" ]>\n" hollow-square ess-bp-fringe-logger-face) - "List giving the loggers specifications. -List format is identical to that of `ess-bp-type-spec-alist'." - :group 'ess-debug - :type 'list) - - -(defun ess-bp-get-bp-specs (type &optional condition no-error) - "Get specs for TYPE." - (let ((spec-alist (cond - ((eq type 'conditional) - (let ((tl (copy-sequence ess-bp-conditional-spec))) - (when (eq (length condition) 0) - (setq condition "TRUE")) - (setcar (cdr tl) (format (cadr tl) condition)) - (setcar (cddr tl) (format (caddr tl) condition)) - (list tl))) - ((eq type 'logger) - (let ((tl (copy-sequence ess-bp-logger-spec))) - (when (eq (length condition) 0) - (setq condition "watchLog")) - (setcar (cdr tl) (format (cadr tl) condition)) - (setcar (cddr tl) (format (caddr tl) condition)) - (list tl))) - (t (copy-sequence ess-bp-type-spec-alist))))) - (or (assoc type spec-alist) - (if no-error - nil - (error "Undefined breakpoint type %s" type))))) - -(defun ess-bp-create (type &optional condition no-error) - "Set breakpoint for the current line. -Returns the beginning position of the hidden text." - (let* ((bp-specs (ess-bp-get-bp-specs type condition no-error)) - (init-pos (point-marker)) - (fringe-bitmap (nth 3 bp-specs)) - (fringe-face (nth 4 bp-specs)) - (displ-string (nth 2 bp-specs)) - (bp-id (format "\"@%s@\"" - (setq ess--bp-identifier (1+ ess--bp-identifier)))) - (bp-command (concat (format (nth 1 bp-specs) bp-id) - "##:ess-bp-end:##\n")) - (dummy-string (format "##:ess-bp-start::%s@%s:##\n" (car bp-specs) condition)) - insertion-pos) - (when bp-specs - (set-marker init-pos (1+ init-pos)) - (setq displ-string (propertize displ-string - 'face fringe-face - 'font-lock-face fringe-face)) - (setq bp-command (propertize bp-command - 'ess-bp t - 'bp-id bp-id - 'bp-active t - 'cursor-intangible 'ess-bp - 'rear-nonsticky '(cursor-intangible ess-bp bp-type) - 'bp-type type - 'bp-substring 'command - 'display displ-string)) - (setq dummy-string (propertize - (ess-tracebug--propertize dummy-string fringe-bitmap fringe-face "*") - 'ess-bp t - 'cursor-intangible 'ess-bp - 'bp-type type - 'bp-substring 'dummy)) - (ess-tracebug--set-left-margin) - (back-to-indentation) - (setq insertion-pos (point) ) - (insert (concat dummy-string bp-command)) - (indent-for-tab-command) - (goto-char (1- init-pos)) ;; sort of save-excursion - insertion-pos))) - -(defun ess-bp-recreate-all () - "Internal function to recreate all bp." - (save-excursion - (save-restriction - (with-silent-modifications - (cursor-intangible-mode) - (widen) - (goto-char (point-min)) - (while (re-search-forward - "\\(##:ess-bp-start::\\(.*\\):##\n\\)\\(.+##:ess-bp-end:##\n\\)" nil t) - (let ((dum-beg (match-beginning 1)) - (dum-end (match-end 1)) - (comm-beg (match-beginning 3)) - (comm-end (match-end 3)) - (type (match-string 2)) - (bp-command (match-string 3)) - bp-id dum-props condition) - (when (string-match "^\\(\\w+\\)@\\(.*\\)\\'" type) - (setq condition (match-string 2 type)) - (setq type (match-string 1 type))) - (setq bp-id - (if (string-match "\"@[0-9]+@\"" bp-command) - (match-string 0 bp-command) - (setq ess--bp-identifier (1+ ess--bp-identifier)))) - (setq type (intern type)) - (let* ((bp-specs (ess-bp-get-bp-specs type condition t)) - (displ-string (nth 2 bp-specs)) - (fringe-face (nth 4 bp-specs)) - (fringe-bitmap (nth 3 bp-specs))) - (when bp-specs - (setq displ-string (propertize displ-string - 'face fringe-face - 'font-lock-face fringe-face)) - (add-text-properties comm-beg comm-end - (list 'ess-bp t - 'bp-id bp-id - 'cursor-intangible 'ess-bp - 'rear-nonsticky '(cursor-intangible ess-bp bp-type) - 'bp-type type - 'bp-substring 'command - 'display displ-string)) - (setq dum-props - (if window-system - (list 'display (list 'left-fringe fringe-bitmap fringe-face)) - (list 'display (list '(margin left-margin) - (propertize "dummy" - 'font-lock-face fringe-face - 'face fringe-face))))) - (add-text-properties dum-beg dum-end - (append dum-props - (list 'ess-bp t - 'cursor-intangible 'ess-bp - 'bp-type type - 'bp-substring 'dummy))) - ;; (when comment-beg - ;; (add-text-properties comment-beg comment-end - ;; (list 'ess-bp t - ;; 'bp-id bp-id - ;; 'cursor-intangible 'ess-bp - ;; 'display (propertize (nth 1 ess-bp-inactive-spec) 'face fringe-face) - ;; 'bp-type type - ;; 'bp-substring 'comment))) - )))))))) - -(add-hook 'ess-r-mode-hook 'ess-bp-recreate-all) - - -(defun ess-bp-get-bp-position-nearby () - "Get nearby break points. -Return the cons (beg . end) of breakpoint limit points closest to -the current position. Only currently visible region of the buffer -is searched. This command is intended for use in interactive -commands like `ess-bp-toggle-state' and `ess-bp-kill'. Use -`ess-bp-previous-position' in programs." - (interactive) - (let* ((pos-end (if (get-char-property (1- (point)) 'ess-bp) - (point) - (previous-single-property-change (point) 'ess-bp nil (window-start)))) - (pos-start (if (get-char-property (point) 'ess-bp) ;;check for bobp - (point) - (next-single-property-change (point) 'ess-bp nil (window-end)))) - dist-up dist-down) - (unless (eq pos-end (window-start)) - (setq dist-up (- (line-number-at-pos (point)) - (line-number-at-pos pos-end)))) - (unless (eq pos-start (window-end)) - (setq dist-down (- (line-number-at-pos pos-start) - (line-number-at-pos (point))))) - (if (and dist-up dist-down) - (if (< dist-up dist-down) - (cons (previous-single-property-change pos-end 'ess-bp nil (window-start)) pos-end) - (cons pos-start (next-single-property-change pos-start 'ess-bp nil (window-end)))) - (if dist-up - (cons (previous-single-property-change pos-end 'ess-bp nil (window-start)) pos-end) - (if dist-down - (cons pos-start (next-single-property-change pos-start 'ess-bp nil (window-end)))))))) - - -(defun ess-bp-previous-position () - "Get previous breakpoints. -Return the cons (beg . end) of breakpoint limit points closest -to the current position, nil if not found." - (let* ( (pos-end (if (get-char-property (1- (point)) 'ess-bp) - (point) - (previous-single-property-change (point) 'ess-bp )))) - (if pos-end - (cons (previous-single-property-change pos-end 'ess-bp) pos-end)))) - -(defun ess-bp-set () - "Set a breakpoint." - (interactive) - (let* ((pos (ess-bp-get-bp-position-nearby)) - (same-line (and pos - (<= (point-at-bol) (cdr pos)) - (>= (point-at-eol) (car pos)))) - (types ess-bp-type-spec-alist) - (ev last-command-event) - (com-char (event-basic-type ev)) - bp-type) - (when same-line - ;; set bp-type to next type in types - (setq bp-type (get-text-property (car pos) 'bp-type)) - (setq types (cdr (member (assq bp-type types) types))) ; nil if bp-type is last in the list - (when (null types) - (setq types ess-bp-type-spec-alist)) - (ess-bp-kill) - (indent-for-tab-command)) - ;; skip contextual bps - (while (and (nth 5 (car types)) - (not (funcall (nth 5 (car types))))) - (pop types)) - (setq bp-type (pop types)) - (ess-bp-create (car bp-type)) - (while (eq (event-basic-type (setq ev (read-event (format "'%c' to cycle" com-char)))) - com-char) - (if (null types) (setq types ess-bp-type-spec-alist)) - (ess-bp-kill) - ;; skip contextual bps - (while (and (nth 5 (car types)) - (not (funcall (nth 5 (car types))))) - (pop types)) - (setq bp-type (pop types)) - (ess-bp-create (car bp-type)) - (indent-for-tab-command)) - (push ev unread-command-events))) - - -(defun ess-bp-set-conditional (condition) - (interactive "sBreakpoint condition: ") - (ess-bp-create 'conditional condition) - (indent-for-tab-command)) - -(defun ess-bp-set-logger (name) - (interactive "sLogger name : ") - (ess-bp-create 'logger name) - (indent-for-tab-command)) - -(defun ess-bp-kill (&optional interactive?) - "Remove the breakpoint nearby." - (interactive "p") - (let ((pos (ess-bp-get-bp-position-nearby)) - (init-pos (make-marker))) - (if (null pos) - (if interactive? (message "No breakpoints nearby")) - (if (eq (point) (point-at-eol)) - (goto-char (1- (point)))) ;; work-around for issue 3 - (set-marker init-pos (point)) - (goto-char (car pos)) - (delete-region (car pos) (cdr pos)) - (indent-for-tab-command) - (goto-char init-pos) - (if (eq (point) (point-at-eol)) (forward-char))))) - -(defun ess-bp-kill-all nil - "Delete all breakpoints in current buffer." - (interactive) - (let ((count 0) - (init-pos (make-marker)) - pos) - (set-marker init-pos (1+ (point))) - (save-excursion ;; needed if error - (goto-char (point-max)) - (while (setq pos (ess-bp-previous-position)) - (goto-char (car pos)) - (delete-region (car pos) (cdr pos)) - (indent-for-tab-command) - (setq count (1+ count))) - (if (eq count 1) - (message "Killed 1 breakpoint") - (message "Killed %d breakpoint(s)" count))) - (goto-char (1- init-pos)))) - - -(defun ess-bp-toggle-state () - "Toggle the breakpoint between active and inactive states. - -For standard breakpoints, the effect of this command is -immediate, that is you don't need to source your code and it -works even in the process of debugging. - -For loggers, recover and conditional breakpoints this command -just comments the breakpoint in the source file. - -If there is no active R session, this command triggers an error." - (interactive) - (unless (and ess-local-process-name - (get-process ess-local-process-name)) - (error "No R session in this buffer")) - (save-excursion - (let ((pos (ess-bp-get-bp-position-nearby)) - (fringe-face (nth 3 ess-bp-inactive-spec)) - (cursor-sensor-inhibit 'ess-bp-toggle-state) - bp-id bp-specs beg-pos-command) - (if (null pos) - (message "No breakpoints in the visible region") - (goto-char (car pos)) - (setq beg-pos-command (previous-single-property-change - (cdr pos) 'bp-substring nil (car pos)) - bp-id (get-char-property beg-pos-command 'bp-id)) - (goto-char beg-pos-command) - (if (get-char-property beg-pos-command 'bp-active) - (progn - (put-text-property (car pos) beg-pos-command ;; dummy display change - 'display (list 'left-fringe (nth 2 ess-bp-inactive-spec) fringe-face)) - (put-text-property beg-pos-command (cdr pos) - 'bp-active nil) - (ess-command (format ".ESSBP.[[%s]] <- TRUE\n" bp-id))) - (setq bp-specs (assoc (get-text-property (point) 'bp-type) ess-bp-type-spec-alist)) - (put-text-property beg-pos-command (cdr pos) - 'bp-active t) - (put-text-property (car pos) beg-pos-command - 'display (list 'left-fringe (nth 3 bp-specs) (nth 4 bp-specs))) - (ess-command (format ".ESSBP.[[%s]] <- NULL\n" bp-id)) - ;; (insert (propertize "##" - ;; 'ess-bp t - ;; 'cursor-intangible 'ess-bp - ;; 'display (propertize (nth 1 ess-bp-inactive-spec) 'face fringe-face) - ;; 'bp-type (get-char-property (point) 'bp-type) - ;; 'bp-substring 'comment)) - ))))) - - -(defun ess-bp-make-visible () - "Make bp text visible." - (interactive) - (let ((pos (ess-bp-get-bp-position-nearby))) - (set-text-properties (car pos) (cdr pos) (list 'display nil)))) - - - -(defun ess-bp-next nil - "Goto next breakpoint." - (interactive) - (when-let ((bp-pos (next-single-property-change (point) 'ess-bp))) - (save-excursion - (goto-char bp-pos) - (when (get-text-property (1- (point)) 'ess-bp) - (setq bp-pos (next-single-property-change bp-pos 'ess-bp)))) - (if bp-pos - (goto-char bp-pos) - (message "No breakpoints found")))) - - -(defun ess-bp-previous nil - "Goto previous breakpoint." - (interactive) - (if-let ((bp-pos (previous-single-property-change (point) 'ess-bp))) - (goto-char (or (previous-single-property-change bp-pos 'ess-bp) - bp-pos)) - (message "No breakpoints before the point found"))) - -;;;_ + WATCH - -(defvar ess-watch-command - ;; assumes that every expression is a structure of length 1 as returned by parse. - ".ess_watch_eval()\n") - -(if (fboundp 'define-fringe-bitmap) ;;not clear to me why is this not bound in SSH session? - :TODO check - (define-fringe-bitmap 'current-watch-bar - [#b00001100] nil nil '(top t))) - -(defun ess-tracebug--set-left-margin () - "Set the margin on non-X displays." - (unless window-system - (when (= left-margin-width 0) - (setq left-margin-width 1) - (set-window-buffer (selected-window) (current-buffer))))) - -(define-derived-mode ess-watch-mode special-mode "ESS watch" - "Major mode in `ess-watch' window." - :group 'ess-tracebug - (let ((cur-block (max 1 (ess-watch-block-at-point))) - (dummy-string - (ess-tracebug--propertize "|" 'current-watch-bar 'font-lock-keyword-face))) - (ess-tracebug--set-left-margin) - (setq-local revert-buffer-function 'ess-watch-revert-buffer) - (turn-on-font-lock) - (setq ess-watch-current-block-overlay - (make-overlay (point-min) (point-max))) - (overlay-put ess-watch-current-block-overlay 'line-prefix dummy-string) - (overlay-put ess-watch-current-block-overlay 'face 'ess-watch-current-block-face) - (ess-watch-set-current cur-block) ;; - (require 'face-remap) - ;; scale the font - (setq text-scale-mode-amount ess-watch-scale-amount) - (text-scale-mode))) - -(defun ess-watch () - "Run `ess-watch-mode' on R objects. -This is the trigger function. See documentation of -`ess-watch-mode' for more information." - (interactive) - (ess-force-buffer-current) - (let ((wbuf (get-buffer-create ess-watch-buffer)) - (pname ess-local-process-name)) - (pop-to-buffer wbuf - ;; not strongly dedicated - '(nil . ((dedicated . 1)))) - (setq ess-local-process-name pname) - (ess-watch-mode) - ;; evals the ess-command and displays the buffer if not visible - (ess-watch-refresh-buffer-visibly wbuf))) - - -(defun ess-watch-refresh-buffer-visibly (wbuf &optional sleep no-prompt-check) - "Eval `ess-watch-command' and direct the output into the WBUF. -Call `ess-watch-buffer-show' to make the buffer visible, without -selecting it. SLEEP and NO-PROMPT-CHECK get passed to `ess-command'. - -This function is used for refreshing the watch window after each step during -the debugging." - ;; assumes that the ess-watch-mode is on!! - ;; particularly ess-watch-current-block-overlay is installed - (ess-watch-buffer-show wbuf) ;; if visible do nothing - (let ((pname ess-local-process-name)) ;; watch might be used from different dialects, need to reset - (with-current-buffer wbuf - (let ((curr-block (max 1 (ess-watch-block-at-point))) ;;can be 0 if - (inhibit-read-only t)) - (when pname - (setq ess-local-process-name pname)) - (ess-command ess-watch-command wbuf sleep no-prompt-check) - ;; delete the ++++++> line ;; not very reliable but works fine so far. - (goto-char (point-min)) - (delete-region (point-at-bol) (+ 1 (point-at-eol))) - (ess-watch-set-current curr-block) - (set-window-point (get-buffer-window wbuf) (point)))))) - -(defun ess-watch-buffer-show (buffer-or-name) - "Make watch buffer BUFFER-OR-NAME visible, and position accordingly. -If already visible, do nothing. - -Currently the only positioning rule implemented is to split the R -process window in half. The behavior is controlled by -`split-window-sensibly' with parameters `split-height-threshold' -and `split-width-threshold' replaced by -`ess-watch-height-threshold' and `ess-watch-width-threshold' -respectively." - (interactive) - (unless (get-buffer-window ess-watch-buffer 'visible) - (save-selected-window - (ess-switch-to-ESS t) - (let* ((split-width-threshold (or ess-watch-width-threshold - split-width-threshold)) - (split-height-threshold (or ess-watch-height-threshold - split-height-threshold)) - (win (split-window-sensibly (selected-window)))) - (if win - (set-window-buffer win buffer-or-name) - (display-buffer buffer-or-name) ;; resort to usual mechanism if could not split - ))))) - - -(defun ess-watch-revert-buffer (_ignore _noconfirm) - "Update the watch buffer. -Arguments IGNORE and NOCONFIRM currently not used." - (ess-watch) - (message "Watch reverted")) - - -(defface ess-watch-current-block-face - '((default (:inherit highlight))) - "Face used to highlight current watch block." - :group 'ess-debug) - -(defvar ess-watch-start-block "@----" ;; fixme: make defcustom and modify the injected command correspondingly - "String indicating the beginning of a block in watch buffer." - ;; :group 'ess-debug - ;; :type 'string - ) - -(defvar ess-watch-start-expression "@---:" - "String indicating the beginning of an R expression in watch buffer." - ;; :group 'ess-debug - ;; :type 'string - ) - -(defun ess-watch-block-limits-at-point () - "Return start and end positions of the watch block." - (interactive) - (save-excursion - (let ((curr (point)) - start-pos end-pos) - (end-of-line) - (setq start-pos - (if (re-search-backward ess-watch-start-block nil t ) - (point) - (point-min))) - (goto-char curr) - (beginning-of-line) - (setq end-pos - (if (re-search-forward ess-watch-start-block nil t) - (match-beginning 0) - (point-max))) - (list start-pos end-pos)))) - -(defun ess-watch-block-at-point () - "Return the current block's order count, 0 if no block was found." - (save-excursion - (let ((cur-point (point)) - (count 0)) - (goto-char (point-min)) - (while (re-search-forward ess-watch-start-block cur-point t) - (setq count (1+ count))) - count))) - -(defun ess-watch-set-current (nr) - "Move the overlay over the block with count NR in current watch buffer." - (goto-char (point-min)) - (re-search-forward ess-watch-start-expression nil t nr) - (goto-char (match-end 0)) - (apply 'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) - - -(defun ess-watch--make-alist () - "Create an alist of expressions from the current watch buffer. -Each element of assoc list is of the form (pos name expr) where -pos is an unique integer identifying watch blocks by position, -name is a string giving the name of expression block, expr is a -string giving the actual R expression." - (interactive) - (save-excursion - (let* ((reg-name (concat "^" ess-watch-start-block " *\\(\\S-*\\).*$")) - (reg-expr (concat "^" ess-watch-start-expression "\\s-*\\(.*\\)$")) - (reg-all (concat "\\(" reg-name "\\)\n\\(" reg-expr "\\)")) - (pos 0) wal name expr) - (goto-char (point-min)) - (while (re-search-forward reg-all nil t) - (setq pos (+ 1 pos)) - (setq name (match-string-no-properties 2)) - (setq expr (match-string-no-properties 4)) - (if (not (eq (string-to-number name) 0)) ;;if number of any kind set the name to "" - (setq name "")) - (setq wal - (append wal (list (list pos name expr))))) - wal))) - -(defun ess-watch--parse-assoc (al) - "Return a string of the form 'assign(\".ess_watch_expressions\", list(a = parse(expr_a), b= parse(expr_b)), envir = .GlobalEnv)' -ready to be send to R process. AL is an association list as return by `ess-watch--make-alist'" - (concat ".ess_watch_assign_expressions(list(" - (mapconcat (lambda (el) - (if (> (length (cadr el) ) 0) - (concat "`" (cadr el) "` = parse(text = '" (caddr el) "')") - (concat "parse(text = '" (caddr el) "')"))) - al ", ") - "))\n")) - -(defun ess-watch--install-.ess_watch_expressions () - ;; used whenever watches are added/deleted/modified from the watch - ;; buffer. this is the only way to insert expressions into - ;; .ess_watch_expressions object in R. Assumes R watch being the current - ;; buffer, otherwise will most likely install empty list. - (interactive) - (process-send-string (ess-get-process ess-current-process-name) - (ess-watch--parse-assoc (ess-watch--make-alist))) - ;;TODO: delete the prompt at the end of proc buffer TODO: defun ess-send-string!! - (sleep-for 0.05) ;; need here, if ess-command is used immediately after, for some weird reason the process buffer will not be changed - ) - - -(defun ess-watch-quit () - "Quit (kill) the watch buffer. -If watch buffer exists, it is displayed during the debug -process. The only way to avoid the display, is to kill the -buffer." - (interactive) - (kill-buffer) ;; dedicated, window is deleted unless not the only one - ) - -;;;_ + MOTION -(defun ess-watch-next-block (&optional n) - "Move the overlay over the next block. -Optional N if supplied gives the number of steps forward `backward-char'." - (interactive "P") - (setq n (prefix-numeric-value n)) - (goto-char (overlay-end ess-watch-current-block-overlay)) - (unless (re-search-forward ess-watch-start-expression nil t n) - (goto-char (point-min)) ;;circular but always moves to start! - (re-search-forward ess-watch-start-expression nil t 1)) - (apply 'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) - -(defun ess-watch-previous-block (&optional n) - "Move the overlay over the previous block. -Optional N if supplied gives the number of backward steps." - (interactive "P") - (setq n (prefix-numeric-value n)) - (goto-char (overlay-start ess-watch-current-block-overlay)) - (unless (re-search-backward ess-watch-start-expression nil t n) - (goto-char (point-max)) ;;circular but always moves to last! - (re-search-backward ess-watch-start-expression nil t 1)) - (goto-char (match-end 0)) - (apply 'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) - -;;;_ + BLOCK MANIPULATION and EDITING -(defun ess-watch-rename () - "Rename the currently selected watch block." - (interactive) - (end-of-line) - (unless (re-search-backward ess-watch-start-block nil t) - (error "Can not find a watch block")) - (let ((reg-name (concat ess-watch-start-block " *\\(\\S-*\\).*$")) - name start end) - ;; (reg-expr (concat "^" ess-watch-start-expression "\\s-*\\(.*\\)$")) - ;; (reg-all (concat "\\(" reg-name "\\)\n\\(" reg-expr "\\)")) - ;; (pos 0) wal name expr) - (unless (re-search-forward reg-name (point-at-eol) t) - (error "Can not find the name substring in the current watch block ")) - (setq name (match-string-no-properties 1)) - (setq start (match-beginning 1)) - (setq end (match-end 1)) - (goto-char start) - ;; TODO: highlight the name in R-watch here - (setq name (read-string (concat "New name (" name "): ") nil nil name) ) - (setq buffer-read-only nil) - (delete-region start end) - (insert name) - (setq buffer-read-only t) - (ess-watch--install-.ess_watch_expressions) - (ess-watch-refresh-buffer-visibly (current-buffer)))) - -(defun ess-watch-edit-expression () - "Edit in the minibuffer the R expression from the current watch block." - (interactive) - (end-of-line) - (unless (re-search-backward ess-watch-start-block nil 1) - (error "Can not find a watch block")) - (let ((reg-expr (concat ess-watch-start-expression " *\\(.*\\)$")) - expr start end) - (unless (re-search-forward reg-expr nil t) - (error "Can not find an expression string in the watch block")) - (setq expr (match-string-no-properties 1)) - (setq start (match-beginning 1)) - (setq end (match-end 1)) - (goto-char start) - ;; TODO: highlight the name in R-watch here - (setq expr (read-string "New expression: " expr nil expr) ) - (setq buffer-read-only nil) - (delete-region start end) - (insert expr) - (setq buffer-read-only t) - (ess-watch--install-.ess_watch_expressions) - (ess-watch-refresh-buffer-visibly (current-buffer)))) - -(defun ess-watch-add () - "Ask for new R expression and name and append it to the end of the list of watch expressions." - (interactive) - (let (nr expr name) - (goto-char (point-max)) - (setq nr (number-to-string (1+ (ess-watch-block-at-point)))) - (setq name nr) - ;; (setq name (read-string (concat "Name (" nr "):") nil nil nr )) ;;this one is quite annoying and not really needed than for logging - (setq expr (read-string "New expression: " nil nil "\"Empty watch!\"")) - (setq buffer-read-only nil) - (insert (concat "\n" ess-watch-start-block " " name " -@\n" ess-watch-start-expression " " expr "\n")) - (setq buffer-read-only t) - (ess-watch--install-.ess_watch_expressions))) - -(defun ess-watch-insert () - "Ask for new R expression and name and insert it in front of current watch block." - (interactive) - (let (nr expr name) - (setq nr (number-to-string (ess-watch-block-at-point))) - (setq name nr) - ;; (setq name (read-string (concat "Name (" nr "):") nil nil nr )) - (setq expr (read-string "New expression: " nil nil "\"Empty watch!\"")) - (re-search-backward ess-watch-start-block nil 1) ;;point-min if not found - (setq buffer-read-only nil) - (insert (concat "\n" ess-watch-start-block " " name " -@\n" ess-watch-start-expression " " expr "\n")) - (setq buffer-read-only t) - (ess-watch--install-.ess_watch_expressions))) - -(defun ess-watch-move-up () - "Move the current block up." - (interactive) - (let ((nr (ess-watch-block-at-point)) - wbl) - (when (> nr 1) - (setq buffer-read-only nil) - (setq wbl (apply 'delete-and-extract-region (ess-watch-block-limits-at-point))) - (re-search-backward ess-watch-start-block nil t 1) ;; current block was deleted, point is at the end of previous block - (insert wbl) - (ess-watch--install-.ess_watch_expressions) - (setq buffer-read-only t)))) - - -(defun ess-watch-move-down () - "Move the current block down." - (interactive) - (let ((nr (ess-watch-block-at-point)) - (nr-all (save-excursion (goto-char (point-max)) - (ess-watch-block-at-point))) - wbl) - (when (< nr nr-all) - (setq buffer-read-only nil) - (setq wbl (apply 'delete-and-extract-region (ess-watch-block-limits-at-point))) - (end-of-line) - (when (re-search-forward ess-watch-start-block nil t 1) ;; current block was deleted, point is at the end of previous block or point-max - (goto-char (match-beginning 0))) - (insert wbl) - (ess-watch--install-.ess_watch_expressions) - (setq buffer-read-only t)))) - -(defun ess-watch-kill () - "Kill the current block." - (interactive) - (setq buffer-read-only nil) - (apply 'delete-region (ess-watch-block-limits-at-point)) - (ess-watch--install-.ess_watch_expressions)) - -;;;_ + Debug/Undebug at point -(defun ess--dbg-get-signatures (method) - "Get signatures for the method METHOD." - (let ((tbuffer (get-buffer-create " *ess-command-output*")); initial space: disable-undo - signatures) - (save-excursion - (ess-if-verbose-write (format "ess-get-signatures*(%s).. " method)) - (ess-command (concat "showMethods(\"" method "\")\n") tbuffer) - (message "%s" ess-local-process-name) - (message "%s" ess-current-process-name) - (ess-if-verbose-write " [ok] ..\n") - (set-buffer tbuffer) - (goto-char (point-min)) - (if (not (re-search-forward "Function:" nil t)) - (progn (ess-if-verbose-write "not seeing \"Function:\".. \n") - (error (buffer-string)) - ;; (error "Cannot trace method '%s' (Is it a primitive method which you have already traced?)" method) - ) - ;; (setq curr-point (point)) - ;; (while (re-search-forward ", " nil t) ;replace all ", " with ":" for better readability in completion buffers?? - ;; (replace-match ":")) - ;; (goto-char curr-point) - (while (re-search-forward "^.+$" nil t) - (setq signatures (cons (match-string-no-properties 0) signatures)))) - ; (kill-buffer tbuffer) - ) - signatures)) - - -(defun ess-debug-flag-for-debugging () - "Set the debugging flag on a function. -Ask the user for a function and if it turns to be generic, ask -for signature and trace it with browser tracer." - (interactive) - (ess-force-buffer-current "Process to use: ") - (let* ((tbuffer (get-buffer-create " *ess-command-output*")) ;; output buffer name is hard-coded in ess-inf.el - (pkg (ess-r-package-name)) - (all-functions (ess-get-words-from-vector - (if pkg - (format ".ess_all_functions(c('%s'))\n" pkg) - ".ess_all_functions()\n"))) - (obj-at-point (ess-helpobjs-at-point--read-obj)) - (default (and - obj-at-point - (let* ((reg (regexp-quote obj-at-point)) - (matches (cl-loop for el in all-functions - if (string-match reg el) collect el))) - (car (sort matches (lambda (a b) (< (length a) (length b)))))))) - (ufunc (ess-completing-read "Debug" all-functions - nil nil nil nil (or default obj-at-point))) - signature) - ;; FIXME: Most of the following logic should be in R - (if (ess-boolean-command (format "as.character(isGeneric('%s'))\n" ufunc)) - - ;; it's S4 generic: - (save-excursion - ;; ask for exact signature - (setq signature - (ess-completing-read (concat "Method for generic '" ufunc "'") - (ess--dbg-get-signatures ufunc) ;signal an error if not found - nil t nil nil "*default*")) - (if (equal signature "*default*") - ;;debug, the default ufunc - (ess-command (format "trace('%s', tracer = browser)\n" ufunc) tbuffer) - (ess-command (format "trace('%s', tracer = browser, signature = c('%s'))\n" ufunc signature) tbuffer)) - (with-current-buffer tbuffer - ;; give appropriate message or error - (message "%s" (buffer-substring-no-properties (point-min) (point-max))))) - - ;;else, not an S4 generic - (when (ess-boolean-command (format "as.character(.knownS3Generics['%s'])\n" ufunc)) - ;; it's S3 generic: - (setq all-functions - (ess-get-words-from-vector - (format "local({gens<-methods('%s');as.character(gens[attr(gens, 'info')$visible])})\n" ufunc))) - (setq all-functions - ;; cannot debug non-visible methods - (delq nil (mapcar (lambda (el) - (if (not (char-equal ?* (aref el (1- (length el))))) el)) - all-functions))) - (setq ufunc (ess-completing-read (format "Method for S3 generic '%s'" ufunc) - (cons ufunc all-functions) nil t))) - (ess-command (format ".ess_dbg_flag_for_debuging('%s')\n" ufunc))))) - - -(defun ess-debug-unflag-for-debugging () - "Prompt for the debugged/traced function or method and undebug/untrace it." - (interactive) - (let ((tbuffer (get-buffer-create " *ess-command-output*")); initial space: disable-undo\ - (debugged (ess-get-words-from-vector - (if nil ;; FIXME: was checking `ess-developer-packages` - (format ".ess_dbg_getTracedAndDebugged(c('%s'))\n" - (mapconcat 'identity ess-developer-packages "', '")) - ".ess_dbg_getTracedAndDebugged()\n"))) - out-message fun def-val) - ;; (prin1 debugged) - (if (eq (length debugged) 0) - (setq out-message "No debugged or traced functions/methods found") - (setq def-val (if (eq (length debugged) 1) - (car debugged) - "*ALL*")) - (setq fun (ess-completing-read "Undebug" debugged nil t nil nil def-val)) - (if (equal fun "*ALL*" ) - (ess-command (concat ".ess_dbg_UndebugALL(c(\"" (mapconcat 'identity debugged "\", \"") "\"))\n") tbuffer) - (ess-command (format ".ess_dbg_UntraceOrUndebug(\"%s\")\n" fun) tbuffer)) - (with-current-buffer tbuffer - (if (= (point-max) 1) ;; not reliable TODO: - (setq out-message (format "Undebugged '%s' " fun)) - (setq out-message (buffer-substring-no-properties (point-min) (point-max))) ;; untrace info or warning, or error occurred - ))) - (message "%s" out-message))) - -;;;_ * Kludges and Fixes -;;; delete-char and delete-backward-car do not delete whole intangible text -(defun ess--tracebug-delete-char (n &rest _) - "When deleting an intangible char, delete the whole intangible region. -Only do this when N is 1" - (when (and (ess-derived-mode-p) - (= n 1) - (get-text-property (point) 'cursor-intangible)) - (kill-region (point) (or (next-single-property-change (point) 'cursor-intangible) - (point-max))) - (indent-according-to-mode))) - -(advice-add 'delete-char :before-until #'ess--tracebug-delete-char) - -(defun ess--tracebug-delete-backward-char (n &rest _) - "When deleting an intangible char, delete the whole intangible region. -Only do this when called interactively and N is 1" - (when (and (ess-derived-mode-p) - (= n 1) - (> (point) (point-min)) - (get-text-property (1- (point)) 'cursor-intangible)) - (kill-region (or (previous-single-property-change (point) 'cursor-intangible) - (point-min)) - (point)))) - -(advice-add 'delete-backward-char :before-until #'ess--tracebug-delete-backward-char) - -(provide 'ess-tracebug) - -;;; ess-tracebug.el ends here diff --git a/elpa/ess-20191014.1343/ess-trns.el b/elpa/ess-20191014.1343/ess-trns.el deleted file mode 100644 index 19fa8059..00000000 --- a/elpa/ess-20191014.1343/ess-trns.el +++ /dev/null @@ -1,235 +0,0 @@ -;;; ess-trns.el --- Support for manipulating S transcript files -*- lexical-binding: t; -*- - -;; Copyright (C) 1989--1994 Bates, Kademan, Ritter and Smith -;; Copyright (C) 1997--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: David Smith -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - - -;;; Commentary: - -;; Code for dealing with ESS transcripts. - -;;; Code: - - ; Requires and autoloads - -(require 'ess-mode) -(require 'ess-inf) -(require 'comint) - -(declare-function ess-display-help-on-object "ess-help" (object &optional command)) - - ; ess-transcript-mode -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;; In this section: -;;;; -;;;; * The major mode ess-transcript-mode -;;;; * Commands for ess-transcript-mode -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defcustom ess-transcript-mode-hook nil - "Hook for customizing ESS transcript mode." - :group 'ess-hooks - :type 'hook) - -;;*;; Major mode definition -(defvar ess-transcript-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-s" #'ess-switch-process) - (define-key map "\C-c\C-r" #'ess-eval-region) - (define-key map "\C-c\M-r" #'ess-eval-region-and-go) - (define-key map "\C-c\C-k" #'ess-force-buffer-current) - (define-key map "\C-c\C-q" #'ess-quit) - (define-key map "\C-c\C-j" #'ess-transcript-send-command) - (define-key map "\C-c\M-j" #'ess-transcript-send-command-and-move) - (define-key map "\M-\C-a" #'ess-goto-end-of-function-or-para) - (define-key map "\M-\C-e" #'ess-goto-end-of-function-or-para) - (define-key map "\C-c\C-y" #'ess-switch-to-ESS) - (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) - (define-key map "\C-c\C-v" #'ess-display-help-on-object) - (define-key map "\C-c\C-d" #'ess-dump-object-into-edit-buffer) - (define-key map "\C-a" #'comint-bol) - (define-key map "\M-\t" #'comint-replace-by-expanded-filename) - (define-key map "\M-?" #'comint-dynamic-list-completions) - (define-key map "\C-c\C-k" #'ess-request-a-process) - (define-key map "{" #'skeleton-pair-insert-maybe) - (define-key map "}" #'skeleton-pair-insert-maybe) - (define-key map "\e\C-h" #'ess-mark-function-or-para) - (define-key map "\e\C-q" #'ess-indent-exp) - (define-key map "\t" #'ess-indent-command) - (define-key map "\C-c\C-p" #'comint-previous-prompt) - (define-key map "\C-c\C-n" #'comint-next-prompt) - (define-key map "\r" #'ess-transcript-send-command-and-move) - (define-key map "\M-\r" #'ess-transcript-send-command) - (define-key map "\C-c\r" #'ess-transcript-copy-command) - (define-key map "\C-c\C-w" #'ess-transcript-DO-clean-region) - (define-key map "\C-c\M-c" #'ess-transcript-clean-buffer) - map) - "Keymap for `ess-transcript-mode'.") - -(easy-menu-define - ess-transcript-mode-menu ess-transcript-mode-map - "Menu for use in S transcript mode." - '("ESS-trans" - ["Describe" describe-mode t] - ["About" (ess-goto-info "Transcript Mode") t] - ["Send bug report" ess-submit-bug-report t] - "------" - ["Mark cmd group" mark-paragraph t] - ["Previous prompt" comint-previous-prompt t] - ["Next prompt" comint-next-prompt t] - "------" - ["Send and move" ess-transcript-send-command-and-move t] - ["Copy command" ess-transcript-copy-command t] - ["Send command" ess-transcript-send-command t] - ["Clean Region" ess-transcript-DO-clean-region t] - ["Clean Whole Buffer" ess-transcript-clean-buffer t] - ["Switch S process" ess-switch-process t] - )) - -;;;###autoload -(define-derived-mode ess-transcript-mode ess-mode "ESS Transcript" - "Major mode for transcript files. - -Type \\[ess-transcript-send-command] to send a command in the -transcript to the current inferior process. \\[ess-transcript-copy-command] -copies the command but does not execute it, allowing you to edit it in -the process buffer first. - -Type \\[ess-transcript-clean-region] to delete all outputs and prompts -in the region, leaving only the commands." - :group 'ess - (setq buffer-read-only t - ess-local-process-name nil - mode-line-process '(" [" ess-local-process-name "]")) - ;; TODO: Set this more normally in various major modes - (unless inferior-ess-prompt ;; For S languages it is set in custom-alist - (setq inferior-ess-prompt - ;; Do not anchor to bol with `^' - (concat "\\(" - inferior-ess-primary-prompt - "\\|" - inferior-ess-secondary-prompt - "\\)"))) - (setq-local paragraph-start (concat "^" inferior-ess-prompt "\\|^\^L")) - (setq-local paragraph-separate "^\^L") - (setq-local comint-use-prompt-regexp t) - (setq-local comint-prompt-regexp (concat "^" inferior-ess-prompt)) - (setq font-lock-defaults '(ess-build-font-lock-keywords - nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))) - -;;*;; Commands used in S transcript mode - -(defun ess-transcript-send-command () - "Send the command at point in the transcript to the ESS process. -The line should begin with a prompt. The ESS process buffer is displayed if it -is not already." - (interactive) - (let* ((proc (or ess-local-process-name - (ess-request-a-process "Evaluate into which process? " t))) - (ess-buf (ess-get-process-buffer proc))) - (setq ess-local-process-name proc) - (if (get-buffer-window ess-buf) nil - (display-buffer ess-buf t)) - (let ((input (inferior-ess-get-old-input))) - (with-current-buffer ess-buf - (goto-char (point-max)) - (ess-eval-linewise input))))) - -(defun ess-transcript-send-command-and-move () - "Send the command on this line, and move point to the next command." - (interactive) - (let* ((proc (or ess-local-process-name - (ess-request-a-process "Evaluate into which process? " t))) - (ess-buf (ess-get-process-buffer proc))) - (setq ess-local-process-name proc) - (if (get-buffer-window ess-buf) nil - (display-buffer ess-buf t)) - (let ((input (inferior-ess-get-old-input))) - (with-current-buffer ess-buf - (goto-char (point-max)) - (ess-eval-linewise input nil nil nil 1)))) - (comint-next-prompt 1)) - -(defun ess-transcript-copy-command () - "Copy the command at point to the command line of the ESS process." - (interactive) - (let* ((proc (or ess-local-process-name - (ess-request-a-process "Evaluate into which process? " t))) - (ess-buf (process-buffer (get-process proc))) - (input (inferior-ess-get-old-input))) - (setq ess-local-process-name proc) - (if (get-buffer-window ess-buf) nil - (display-buffer ess-buf t)) - (with-current-buffer ess-buf - (goto-char (point-max)) - (insert input))) - (ess-switch-to-end-of-ESS)) - -(defun ess-transcript-clean-region (beg end even-if-read-only) - "Strip the transcript in the region, leaving only (R/S/Lsp/..) commands. -Deletes any lines not beginning with a prompt, and then removes the -prompt from those lines that remain. Prefix argument means to -clean even if the buffer is \\[read-only]." - (interactive "r\nP") - (unless inferior-ess-prompt - (error "Cannot clean ESS transcript region in this mode! - That only works in ess-transcript-mode or inferior-ess-mode ('*R*' etc)." - ;; Maybe call ess-clean-region-in-new-transcript ?")) - )) - (let ((do-toggle (and buffer-read-only even-if-read-only)) - (ess-prompt-rx (if inferior-ess-secondary-prompt - (concat "^\\(\\(" - inferior-ess-prompt - "\\)\\|\\(" - inferior-ess-secondary-prompt - "\\)\\)") - (concat "^" inferior-ess-prompt)))) - (save-excursion - (if do-toggle (setq buffer-read-only nil)) - (save-restriction - (deactivate-mark) - (narrow-to-region beg end) - (goto-char (point-min)) - (delete-non-matching-lines ess-prompt-rx) - (goto-char (point-min)) - ;; (replace-regexp * * ) : - (while (re-search-forward ess-prompt-rx nil t) - (replace-match "" nil nil))) - - (if do-toggle (setq buffer-read-only t))))) - -(defun ess-transcript-DO-clean-region (beg end) - "Clean the current via \\[ess-transcript-clean-region] even if the buffer is read-only." - (interactive "r") - (ess-transcript-clean-region beg end 'In-ANY-case)) - -(defun ess-transcript-clean-buffer () - "Cleanup the whole buffer. -Use point-min/max to obey `narrow-to-region'." - (interactive) - (ess-transcript-clean-region (point-min) (point-max) 'In-ANY-case)) - -(provide 'ess-trns) - -;;; ess-trns.el ends here diff --git a/elpa/ess-20191014.1343/ess-utils.el b/elpa/ess-20191014.1343/ess-utils.el deleted file mode 100644 index 6c49e11c..00000000 --- a/elpa/ess-20191014.1343/ess-utils.el +++ /dev/null @@ -1,1057 +0,0 @@ -;;; ess-utils.el --- General Emacs utility functions used by ESS -*- lexical-binding: t; -*- - -;; Copyright (C) 1998--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2017 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; Author: Martin Maechler -;; Created: 9 Sept 1998 -;; Maintainer: ESS-core - -;; This file is part of ESS (Emacs Speaks Statistics). - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - - -;;; Commentary: -;; Various utilities for ESS. - -;;; Code: -(require 'cl-lib) -(require 'comint) -(eval-when-compile - (require 'tramp)) -;; The only ESS file this file should depend on is ess-custom.el -(require 'ess-custom) - -(defvar ac-modes) -(declare-function ess-eval-linewise "ess-inf" (text &optional invisibly eob even-empty wait-last-prompt sleep-sec wait-sec)) -(declare-function color-lighten-name "color" (name percent)) -(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) -;; The following declares can be removed once we drop Emacs 25 -(declare-function tramp-file-name-method "tramp") -(declare-function tramp-file-name-user "tramp") -(declare-function tramp-file-name-host "tramp") -(declare-function tramp-file-name-localname "tramp") -(declare-function tramp-file-name-hop "tramp") - - -;;*;; elisp tools - -(defun ess-next-code-line (&optional arg skip-to-eob) - "Move ARG lines of code forward (backward if ARG is negative). -If `ess-eval-empty' is non-nil, skip past all empty and comment -lines. ARG is 1 by default. If ARG is 0 only comments are skipped -forward. Don't skip the last empty and comment lines in the -buffer unless SKIP-TO-EOB is non-nil. On success, return 0. -Otherwise go as far as possible and return -1." - (interactive "p") - (if (or ess-eval-empty - (and (fboundp 'ess-roxy-entry-p) - (ess-roxy-entry-p))) - (forward-line arg) - (setq arg (or arg 1)) - (beginning-of-line) - (let ((pos (point)) - (inc (if (>= arg 0) 1 -1)) - (cnt (if (= arg 0) 1 arg)) - (out 0)) - ;; when orig-arg == 0, we skip only comments - (while (and (/= cnt 0) (= out 0)) - (unless (= arg 0) - (setq out (forward-line inc))) ; out==0 means success - (comment-beginning) - (beginning-of-line) - (forward-comment (* inc (buffer-size))) ;; as suggested in info file - (if (or skip-to-eob - (not (looking-at ess-no-skip-regexp))) ;; don't go to eob or whatever - (setq cnt (- cnt inc)) - (goto-char pos) - (setq cnt 0) - (forward-line inc)) ;; stop at next empty line - (setq pos (point))) - (goto-char pos) - out))) - -(defun ess-goto-line (line) - "Go to LINE in the widened buffer." - (save-restriction - (widen) - (goto-char (point-min)) - (forward-line (1- line)))) - -(defun ess-skip-thing (thing) - "Leave point at the end of THING. -THING can be 'function, 'paragraph, or 'line." - (cond - ((eql thing 'line) (goto-char (line-end-position))) - ((eql thing 'paragraph) (forward-paragraph)) - ((eql thing 'function) (end-of-defun) (skip-chars-backward " \t\n")))) - -(defun ess-search-except (regexp &optional except backward) - "Search for a REGEXP and store as match 1. -Optionally ignore strings that match EXCEPT. If BACKWARD is -non-nil, search backward." - (let ((continue t) (exit nil)) - (while continue - (if (or (and backward (search-backward-regexp regexp nil t)) - (and (not backward) (search-forward-regexp regexp nil t))) - (progn - (setq exit (match-string 1)) - (setq continue (and except (string-match except exit))) - (if continue (setq exit nil))) - ;;else - (setq continue nil))) - exit)) - -(defun ess-save-and-set-local-variables () - "If buffer was modified, save file and set Local Variables if defined. -Return t if buffer was modified, nil otherwise." - (let ((ess-temp-return-value (buffer-modified-p))) - (save-buffer) - (hack-local-variables) - ess-temp-return-value)) - -(defun ess-get-file-or-buffer (file-or-buffer) - "Return FILE-OR-BUFFER if it is a buffer. -Otherwise return the buffer associated with the file which must -be qualified by it's path; if the buffer does not exist, return -nil." - (declare (side-effect-free t) - (obsolete nil "ESS 19.04")) - (if (bufferp file-or-buffer) - file-or-buffer - (find-buffer-visiting file-or-buffer))) - -(defun ess-file-content (file) - "Return the content of FILE as string." - (if (file-exists-p file) - (with-temp-buffer - (insert-file-contents-literally file) - (buffer-string)) - (error "File '%s' does not exist" file))) - -(defun ess-uniq (list predicate) - "Uniquify LIST, stably, deleting elements using PREDICATE. -Return the list with subsequent duplicate items removed by side effects. -PREDICATE is called with an element of LIST and a list of elements from LIST, -and should return the list of elements with occurrences of the element removed. -This function will work even if LIST is unsorted. See also `delete-dups'." - (declare (obsolete 'delete-dups "ESS 19.04")) - (let ((list list)) - (while list - (setq list (setcdr list (funcall predicate (car list) (cdr list)))))) - list) - -(define-obsolete-function-alias 'ess-uniq-list 'delete-dups "ESS 19.04") - -(defalias 'ess-flatten-list - ;; `flatten-tree' is a function in Emacs 27 - (if (fboundp 'flatten-tree) - 'flatten-tree - (lambda (list) - "Take the arguments and flatten them into one long LIST. -Drops 'nil' entries." - ;; Taken from lpr.el - ;; `lpr-flatten-list' is defined here (copied from "message.el" and - ;; enhanced to handle dotted pairs as well) until we can get some - ;; sensible autoloads, or `flatten-list' gets put somewhere decent. - (ess-flatten-list-1 list)))) - -(defun ess-flatten-list-1 (list) - "Internal helper for `ess-flatten-list', which see for LIST." - (cond - ((null list) (list)) - ((consp list) - (append (ess-flatten-list-1 (car list)) - (ess-flatten-list-1 (cdr list)))) - (t (list list)))) - -(define-obsolete-function-alias 'ess-delete-blank-lines - 'delete-blank-lines "ESS 19.04") - -(define-obsolete-function-alias 'ess-line-to-list-of-words #'split-string "ESS 19.04") - - -;;*;; System - -(defun ess-revert-wisely () - "Revert from disk if file and buffer last modification times are different." - (interactive) - ;; whether or not a revert is needed, force load local variables - ;; for example, suppose that you change the local variables and then - ;; save the file, a revert is unneeded, but a force load is - (hack-local-variables) - (unless (verify-visited-file-modtime (current-buffer)) - (progn - (let ((ess-temp-store-point (point))) - (revert-buffer t t) - (goto-char ess-temp-store-point)) - t))) - -(define-obsolete-function-alias 'ess-find-exec 'ess-find-exec-completions "ESS 19.04") -(defun ess-find-exec-completions (root) - "Given the ROOT of an executable file name, find all possible completions. -Search for the executables in the variable `exec-path'." - (let (executables) - (dolist (dir exec-path) - (when (and (> (length dir) 0) - (file-accessible-directory-p dir)) - ;; the first test above excludes "" from exec-path, which can be - ;; problematic with Tramp. - (dolist (f (file-name-all-completions root dir)) - (setq f (expand-file-name f dir)) - (when (and (file-executable-p f) - (not (backup-file-name-p f)) - (not (file-directory-p f))) - (push f executables))))) - executables)) - -(defun ess-drop-non-directories (file-strings) - "Drop all entries in FILE-STRINGS that do not \"look like\" directories." - (ess-flatten-list (mapcar 'file-name-directory file-strings))) - -(defun ess--parent-dir (path n) - "Return Nth parent of PATH." - (let ((opath path)) - (while (and path (> n 0)) - (setq path (file-name-directory (directory-file-name opath))) - (if (equal path opath) - (setq path nil) - (setq opath path - n (1- n)))) - path)) - - -;;*;; Interaction with inferiors - -(defmacro ess-when-new-input (time-var &rest body) - "BODY is evaluate only if the value of process variable TIME-VAR -is bigger than the time of the last user input (stored in -`last-eval' process variable). TIME-VAR is the name of the -process variable which holds the access time. See the code for -`ess-synchronize-dirs' and `ess-cache-search-list'. - -Returns nil when no current process, or process is busy, or -time-var > last-eval. Otherwise, execute BODY and return the last -value. - -If BODY is executed, set process variable TIME-VAR -to (current-time). - -Variable *proc* is bound to the current process during the -evaluation of BODY. - -Should be used in `ess-idle-timer-functions' which call the -process to avoid excessive requests." - (declare (indent 1) (debug t)) - `(with-ess-process-buffer 'no-error - (let ((le (process-get *proc* 'last-eval)) - (tv (process-get *proc* ',time-var))) - (when (and (or (null tv) (null le) (time-less-p tv le)) - (not (process-get *proc* 'busy))) - (let ((out (progn ,@body))) - (process-put *proc* ',time-var (current-time)) - out))))) - - -;;; Emacs Integration - -(defun ess-derived-mode-p () - "Non-nil if the current major mode is an ESS major mode." - (or (derived-mode-p 'ess-mode) - (derived-mode-p 'ess-julia-mode))) - -(defun ess--generate-eval-visibly-submenu (_menu) - '(["yes" (lambda () (interactive) (setq ess-eval-visibly t)) - :style radio :enable t :selected (eq ess-eval-visibly t)] - ["nowait" (lambda () (interactive) (setq ess-eval-visibly 'nowait)) - :style radio :enable t :selected (eq ess-eval-visibly 'nowait) ] - ["no" (lambda () (interactive) (setq ess-eval-visibly nil)) - :style radio :enable t :selected (eq ess-eval-visibly nil) ])) - -;; Font Lock - -(defun ess--fl-keywords-values () - "Return a cons (STANDARD-VALUE . CUSTOM-VALUE) of `ess-font-lock-keywords'." - (let ((sym ess-font-lock-keywords)) - (if (and (symbolp sym) - (custom-variable-p sym)) - (cons - (eval (car (get sym 'standard-value))) - (symbol-value sym)) - (error "`ess-font-lock-keywords' must be a symbol of a custom variable")))) - -(defun ess--extract-fl-keywords () - (let ((values (ess--fl-keywords-values))) - (mapcar (lambda (kv) - (let ((cust-kv (assoc (car kv) (cdr values)))) - (when cust-kv - (setcdr kv (cdr cust-kv)))) - kv) - (copy-alist (car values))))) - -(defun ess-build-font-lock-keywords () - "Retrieve `font-lock-keywords' from ess-[dialect]-font-lock-keywords. -Merge the customized values of that variable on top of the -standard values and return the new list. For this to work, -`ess-font-lock-keywords' should be a name of the -ess-[dialect]-font-lock-keywords variable." - (delq nil - (mapcar (lambda (c) - (when (cdr c) - (symbol-value (car c)))) - (ess--extract-fl-keywords)))) - -(defun ess-font-lock-toggle-keyword (keyword) - "Toggle KEYWORD font-lock." - (interactive - (list (intern (ess-completing-read - "Keyword to toggle" - (mapcar (lambda (el) (symbol-name (car el))) - (car (ess--fl-keywords-values))) - nil t)))) - (let* ((values (ess--fl-keywords-values)) - (kwd (cond - ;; already in custom values - ((assoc keyword (cdr values))) - ;; if keyword is not already in custom values (can happen if - ;; we add new keywords but the user has the old value saved in - ;; .emacs-custom.el) - ((let ((kwd (assoc keyword (car values))) - (sym ess-font-lock-keywords)) - (when kwd - (set sym (cons kwd (symbol-value sym))) - kwd))) - (t (error "Invalid keyword %s" keyword))))) - (setcdr kwd (not (cdr kwd))) - (let ((mode major-mode) - (dialect ess-dialect)) - ;; refresh font-lock defaults in all relevant buffers - (mapc (lambda (b) - (with-current-buffer b - (when (and (eq major-mode mode) - (eq ess-dialect dialect)) - (font-lock-refresh-defaults)))) - (buffer-list))))) - -(defun ess--generate-font-lock-submenu (_menu) - "Generate ESS font-lock submenu." - (append (mapcar (lambda (el) - `[,(symbol-name (car el)) - (lambda () (interactive) - (ess-font-lock-toggle-keyword ',(car el))) - :style toggle - :enable t - :selected ,(cdr el)]) - (ess--extract-fl-keywords)) - (list "-----" - ["Save to custom" - (lambda () (interactive) - (customize-save-variable ess-font-lock-keywords - (ess--extract-fl-keywords))) - t]))) - - -;;; External modes - -;; Define these here for the byte compiler since ido dynamically -;; let-binds them: -(defvar ido-choice-list) -(defvar ido-context-switch-command) -(defvar ido-directory-too-big) -(defvar ido-directory-nonreadable) -(defvar ido-current-directory) -(defvar ido-enable-flex-matching) -(declare-function ido-read-internal "ido" (item prompt hist &optional default require-match initial)) - -(defun ess-completing-read (prompt collection &optional predicate - require-match initial-input hist def) - "Read a string in the minibuffer, with completion. -Use `ido-completing-read' if IDO interface is present, or fall -back on classical `completing-read' otherwise. Meaning of PROMPT, -COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, HIST, and -DEF is as in `completing-read'. PROMPT is automatically suffixed -with ': ' and (default %s) when needed. If HIST is nil use -`ess--completing-hist' as history. See also `ess-use-ido'." - (let ((use-ido (and ess-use-ido (require 'ido nil t)))) - (setq hist (or hist 'ess--completing-hist)) - (when (and def (not use-ido)) ;; ido places in front and highlights the default - (setq prompt (format "%s(default %s)" prompt def))) - (setq prompt (concat prompt ": ")) - (if use-ido - (let ((reset-ido (and use-ido (not ido-mode))) ;people not using ido but having it) - (ido-current-directory nil) - (ido-directory-nonreadable nil) - (ido-directory-too-big nil) - (ido-context-switch-command 'ignore) - (ido-enable-flex-matching ess-ido-flex-matching) ;it's fast and useful, may be get into options - (ido-choice-list (copy-sequence collection)) ;ido removes the match (reported) - sel) - (unwind-protect - (progn - (add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup) - (add-hook 'choose-completion-string-functions 'ido-choose-completion-string) - (setq sel (ido-read-internal 'list prompt hist def require-match initial-input)) - (when hist ;; ido does not push into hist the whole match if C-SPC or RET is used (reported) - (unless (string= sel (car (symbol-value hist))) - (set hist (cons sel (symbol-value hist)))))) - (when reset-ido - (remove-hook 'minibuffer-setup-hook 'ido-minibuffer-setup) - (remove-hook 'choose-completion-string-functions 'ido-choose-completion-string))) - sel) - ;; else usual completion - (completing-read prompt collection predicate require-match initial-input hist def)))) - -(defun ess--setup-auto-complete (sources &optional inferior) - "Setup auto-complete depending on user settings. -SOURCES gets added to `ac-sources', INFERIOR should be t for -inferior buffers." - ;; auto-complete - (when (and (boundp 'ac-sources) - (if inferior - (eq ess-use-auto-complete t) - ess-use-auto-complete)) - (add-to-list 'ac-modes major-mode) - ;; files should be in front; ugly, but needed - (setq ac-sources - (delq 'ac-source-filename ac-sources)) - (mapc (lambda (el) (add-to-list 'ac-sources el)) - sources) - (add-to-list 'ac-sources 'ac-source-filename))) - -(defun ess--setup-company (sources &optional inferior) - "Setup company depending on user settings. -SOURCES gets added to `company-backends', and when t, INFERIOR -specifies inferior buffers." - ;; company - (when (and (boundp 'company-backends) - (if inferior - (eq ess-use-company t) - ess-use-company)) - (setq-local company-backends - (cl-copy-list (append sources company-backends))) - (delq 'company-capf company-backends))) - -(defmacro ess--execute-electric-command (map &optional prompt wait exit-form &rest args) - "Execute single-key commands defined in MAP till a key is pressed which is not part of map. -Single-key input commands are those that once executed do not -require the prefix command for subsequent invocation. Return the -value of the lastly executed command. PROMPT is passed to -`read-event'. - -If WAIT is t, wait for next input and ignore the keystroke which -triggered the command. - -Each command in map should accept one at least one argument, the -most recent event (as read by `read-event'). ARGS are the -supplementary arguments passed to the commands. - -EXIT-FORM should be supplied for a more refined control of the -read-even loop. The loop is exited when EXIT-FORM evaluates to -t. See examples in the tracebug code." - ;;VS[09-06-2013]: check: it seems that set-temporary-overlay-map is designed - ;;for this type of things; see also repeat.el package. - `(let* ((ev last-command-event) - (command (lookup-key ,map (vector ev))) - out exit ) - (if (not (or ,wait command)) - (message "%s is undefined" (key-description (this-command-keys))) - (unless ,wait - (setq out (and command (funcall command ev ,@args)))) - (while (and (not exit) - (setq command - (lookup-key ,map - (vector (setq ev (read-event ,prompt)))))) - (setq out (funcall command ev ,@args)) - (sleep-for .01) - (setq exit ,exit-form)) - (unless exit ;; push only if an event triggered the exit - (push ev unread-command-events)) - out))) - -(cl-defgeneric ess-build-tags-command () - "Command passed to generate tags. -If nil, `ess-build-tags-for-directory' uses the mode's imenu -expression. Otherwise, it should be a string with two %s -formats: one for directory and another for the output file." - nil) - - -;;; Emacs itself - -(defun ess-yank-cleaned-commands () - "Yank and strip the code, leaving only (R/S/Lsp/..) commands. -Deletes any lines not beginning with a prompt, and then removes -the prompt from those lines that remain. Invoke this command with -\\[universal-argument] \\[universal-argument] \\\\[yank]." - (setq yank-window-start (window-start)) - (let ((beg (point))) - (push-mark beg) - (setq this-command t) - (insert-for-yank (current-kill 0)) - (when (and (require 'ess-trns) (fboundp 'ess-transcript-clean-region)) - (ess-transcript-clean-region beg (point) nil)) - (if (eq (point) beg) - (message "No commands found")) - (if (eq this-command t) - (setq this-command 'yank)))) - -(defun ess-yank (&optional arg) - "Call `ess-yank-cleaned-commands' if ARG is 16. -With double prefix ARG (\\[universal-argument] -\\[universal-argument]) call `ess-yank-cleaned-commands'." - (interactive "*P") - (if (equal '(16) arg) - (ess-yank-cleaned-commands) - (let* ((remapped (command-remapping 'yank (point))) - (command (cond ((eq remapped 'ess-yank) 'yank) - ((null remapped) 'yank) - (t remapped)))) - (funcall command arg)))) - -(put 'ess-yank 'delete-selection 'yank) - -(defun ess-build-tags-for-directory (dir tagfile) - "Ask for directory and tag file and build tags for current dialect. -If the current language defines `ess-build-tags-command' use it -and ask the subprocess to build the tags. Otherwise use imenu -regexp and call find .. | etags .. in a shell command. You must -have 'find' and 'etags' programs installed. - -Use M-. to navigate to a tag. \\[visit-tags-table] to -append/replace the currently used tag table. - -If prefix is given, force tag generation based on imenu. Might be -useful when different language files are also present in the -directory (.cpp, .c etc)." - (interactive "DDirectory to tag: -GTags file (default TAGS): ") - (when (or (eq (length (file-name-nondirectory tagfile)) 0) - (file-directory-p tagfile)) - (setq tagfile (concat (file-name-as-directory tagfile) "TAGS"))) - ;; Emacs find-tags doesn't play well with remote TAG files :( - (when (file-remote-p tagfile) - (require 'tramp) - (setq tagfile (with-parsed-tramp-file-name tagfile foo foo-localname))) - (when (file-remote-p dir) - (require 'tramp) - (setq dir (with-parsed-tramp-file-name dir foo foo-localname))) - (if (and (ess-build-tags-command) (null current-prefix-arg)) - (ess-eval-linewise (format (ess-build-tags-command) dir tagfile)) - ;; else generate from imenu - (unless imenu-generic-expression - (error "No ess-tag-command found, and no imenu-generic-expression defined")) - (let* ((find-cmd - (format "find %s -type f -size 1M \\( -regex \".*\\.\\(cpp\\|jl\\|[RsrSch]\\(nw\\)?\\)$\" \\)" dir)) - (regs (delq nil (mapcar (lambda (l) - (if (string-match "'" (cadr l)) - nil ;; remove for time being - (format "/%s/\\%d/" - (replace-regexp-in-string "/" "\\/" (nth 1 l) t) - (nth 2 l)))) - imenu-generic-expression))) - (tags-cmd (format "etags -o %s --regex='%s' -" tagfile - (mapconcat 'identity regs "' --regex='")))) - (message "Building tags: %s" tagfile) - (when (= 0 (shell-command (format "%s | %s" find-cmd tags-cmd))) - (message "Building tags .. ok!"))))) - - -;;; UI - -(defvar ess-current-region-overlay - (let ((overlay (make-overlay (point) (point)))) - (overlay-put overlay 'face 'highlight) - overlay) - "The overlay for highlighting currently evaluated region or line.") - -(defun ess-blink-region (start end) - "Blink from START to END depending on option `ess-blink-region'." - (when ess-blink-region - (move-overlay ess-current-region-overlay start end) - (run-with-timer ess-blink-delay nil - (lambda () - (delete-overlay ess-current-region-overlay))))) - -(defun ess-deactivate-mark () - "Deactivate the mark, if active. -If `evil-mode' is on, switch to `evil-normal-state'." - (if (and (bound-and-true-p evil-mode) - (fboundp 'evil-visual-state-p) - (evil-visual-state-p)) - (when (fboundp 'evil-normal-state) - (evil-normal-state)) - (when mark-active - (deactivate-mark)))) - -;; SJE: 2009-01-30 -- this contribution from -;; Erik Iverson - -(defun ess-tooltip-show-at-point (text xo yo) - "Show a tooltip displaying TEXT at (around) point. -XO and YO are x- and y-offsets for the toolbar from point." - (let ( - (fx (frame-parameter nil 'left)) - (fy (frame-parameter nil 'top)) - (fw (frame-pixel-width)) - (fh (frame-pixel-height)) - frame-left frame-top my-x-offset my-y-offset) - ;; The following comment was found before code looking much like that - ;; of frame-left and frame-top below in the file - ;; tooltip-help.el. I include it here for acknowledgment, and I did observe - ;; the same behavior with the Emacs window maximized under Windows XP. - - ;; -----original comment-------- - ;; handles the case where (frame-parameter nil 'top) or - ;; (frame-parameter nil 'left) return something like (+ -4). - ;; This was the case where e.g. Emacs window is maximized, at - ;; least on Windows XP. The handling code is "shamelessly - ;; stolen" from cedet/speedbar/dframe.el - ;; (contributed by Andrey Grigoriev) - (setq frame-left (if (not (consp fx)) - fx - (if (eq (car fx) '-) - (- (display-pixel-width) (car (cdr fx)) fw) - (car (cdr fx))))) - (setq frame-top (if (not (consp fy)) - fy - (if (eq (car fy) '-) - (- (display-pixel-height) (car (cdr fy)) fh) - (car (cdr fy))))) - ;; calculate the offset from point, use xo and yo to adjust to preference - (setq my-x-offset (+ (car(window-inside-pixel-edges)) - (car(posn-x-y (posn-at-point))) - frame-left xo)) - (setq my-y-offset (+ (cadr(window-inside-pixel-edges)) - (cdr(posn-x-y (posn-at-point))) - frame-top yo)) - (let ((tooltip-frame-parameters - (cons (cons 'top my-y-offset) - (cons (cons 'left my-x-offset) - tooltip-frame-parameters)))) - (tooltip-show text)))) - -(defun ess-select-frame-set-input-focus (frame) - "Select FRAME, raise it, and set input focus, if possible. -Copied almost verbatim from gnus-utils.el (but with test for mac added)." - ;; The function `select-frame-set-input-focus' won't set - ;; the input focus under Emacs 21.2 and X window system. - ;;((fboundp 'select-frame-set-input-focus) - ;; (defalias 'gnus-select-frame-set-input-focus - ;; 'select-frame-set-input-focus) - ;; (select-frame-set-input-focus frame)) - (raise-frame frame) - (select-frame frame) - (cond ((and - (memq window-system '(x mac)) - (fboundp 'x-focus-frame)) - (x-focus-frame frame)) - ((and (eq window-system 'w32) - ;; silence byte compiler warnings about w32-fns - (fboundp 'w32-focus-frame)) - (w32-focus-frame frame))) - (when focus-follows-mouse - (set-mouse-position frame (1- (frame-width frame)) 0))) - -(define-obsolete-function-alias 'ess-do-auto-fill 'do-auto-fill "ESS 19.04") - - -;;; Syntax - -(defun ess-containing-sexp-position () - "Return the `cadr' of `syntax-ppss'." - (cadr (syntax-ppss))) - -(defun ess-code-end-position () - "Like (line-end-position) but stops at comments." - (save-excursion - (goto-char (1+ (line-end-position))) - (forward-comment -1) - (point))) - -;; FIXME: The following function pattern stuff is specific to R but is -;; used throughout ESS -(defvar ess-r-set-function-start - ;; [MGAR].. <=> {setMethod(), set[Group]Generic(), setAs(), setReplaceMethod()} - ;; see also set-S4-exp in ess-r-function-pattern below - "^set[MGAR][GMa-z]+\\s-?(") - -(defvar ess-function-pattern nil ; in R set to ess-r-function-pattern - "Regexp to match the beginning of a function in S buffers.") - -(defvar ess-r-symbol-pattern - "\\(\\sw\\|\\s_\\)" - "The regular expression for matching an R symbol.") - -(defvar ess-r-name-pattern - (concat "\\(" ess-r-symbol-pattern "+\\|\\(`\\).+`\\)") - "The regular expression for matching a R name.") - -(defvar ess--r-s-function-pattern - (let* ((Q "\\s\"") ; quote - (Sym-0 "\\(\\sw\\|\\s_\\)") ; symbol - (Symb (concat Sym-0 "+")) - (xSymb "[^ \t\n\"']+") ;; (concat "\\[?\\[?" Sym-0 "*")); symbol / [ / [[ / [symbol / [[symbol - ;; FIXME: allow '%foo%' but only when quoted; don't allow [_0-9] at beg. - (space "\\(\\s-\\|\n\\)*") ; white space - - (part-1 (concat - "\\(" ;;--------outer Either------- - "\\(\\(" ; EITHER - Q xSymb Q ; any function name between quotes - "\\)\\|\\(" - Symb ; (beginning of name) + ess-r-symbol-pattern - "\\)\\)")) ; END EITHER OR - - (set-S4-exp - (concat - "^set\\(As\\|Method\\|Generic\\|GroupGeneric\\|ReplaceMethod\\)(" ; S4 ... - Q xSymb Q "," space - ;; and now often `` signature(......), : '' - ".*" ;; <<< FIXME ??? - )) - - (part-2 (concat - "\\|" ;;--------outer Or --------- - set-S4-exp - "\\)" ;;--------end outer Either/Or------- - - "\\(" space "\\s<.*\\s>\\)*" ; whitespace, comment - ;; FIXME: in principle we should skip 'definition *= *' here - space "function\\s-*(" ; whitespace, function keyword, parenthesis - ))) - `(,part-1 ,part-2)) - "Placeholder for use in constructing `ess-r-function-pattern' and `ess-s-function-pattern'.") - -(defvar ess-r-function-pattern - (concat (car ess--r-s-function-pattern) - "\\s-*\\(<-\\|=\\)" ; whitespace, assign - (nth 1 ess--r-s-function-pattern)) - "The regular expression for matching the beginning of an R function.") - -(defvar ess-s-function-pattern - (concat (car ess--r-s-function-pattern) - "\\s-*\\(<-\\|_\\|=\\)" ; whitespace, assign (incl. "_") - (nth 1 ess--r-s-function-pattern)) - "The regular expression for matching the beginning of an S function.") - -(defvar ess--fn-name-start-cache nil) - -(defun ess--fn-name-start () - "Return (FN-NAME . START-POS). -FN-NAME is a function name located before the pointer. START-POS -is the position where FN-NAME starts. Store this cons in variable -`ess--fn-name-start-cache'." - (save-excursion - (save-restriction - (let* ((proc (get-buffer-process (current-buffer))) - (mark (and proc (process-mark proc)))) - (if (and mark (>= (point) mark)) - (narrow-to-region mark (point))) - (and (fboundp 'ess-noweb-narrow-to-chunk) - (bound-and-true-p ess-noweb-mode) - (ess-noweb-narrow-to-chunk)) - (unless (ess-inside-string-p) - (setq ess--fn-name-start-cache - (condition-case nil ;; check if it is inside a function - (progn - ;; for the sake of big buffers, look only 1000 chars back - (narrow-to-region (max (point-min) (- (point) 1000)) (point)) - (up-list -1) - (while (not (looking-at "(")) - (up-list -1)) - (let ((funname (symbol-name (ess-symbol-at-point)))) - (when (and funname - (not (member funname ess-S-non-functions))) - (cons funname (- (point) (length funname)))))) - (error nil)))))))) - -(defun ess-symbol-at-point () - "Like `symbol-at-point' but consider fully qualified names. -Fully qualified names include accessor symbols (like aaa$bbb and -aaa@bbb in R)." - (with-syntax-table (or ess-mode-completion-syntax-table - (syntax-table)) - (symbol-at-point))) - -(defun ess-bounds-of-symbol () - "Get bounds of symbol at point. -Intended for completion." - (let ((bounds (with-syntax-table (or ess-mode-completion-syntax-table - (syntax-table)) - (bounds-of-thing-at-point 'symbol)))) - (and bounds - (not (save-excursion - (goto-char (car bounds)) - (looking-at "/\\|.[0-9]"))) - bounds))) - -(defun ess-symbol-start () - "Get initial position for objects completion. -Symbols are fully qualified names that include accessor -symbols (like aaa$bbb and aaa@bbb in R)." - (car (ess-bounds-of-symbol))) - -(defun ess-arg-start () - "Get initial position for args completion." - (when (not (ess-inside-string-p)) - (when (ess--fn-name-start) - (if (looking-back "[(,]+[ \t\n]*" nil) - (point) - (ess-symbol-start))))) - -(defun ess-inside-string-p (&optional pos) - "Return non-nil if POS is inside string. -POS defaults to `point'." - (let ((pos (or pos (point)))) - (nth 3 (syntax-ppss pos)))) - -(defun ess-inside-comment-p (&optional pos) - "Return non-nil if POS is inside string. -POS defaults to `point'." - (let ((pos (or pos (point)))) - (nth 4 (syntax-ppss pos)))) - -(defun ess-inside-string-or-comment-p (&optional pos) - "Return non-nil if POS is inside a string or comment. -POS defaults to `point'." - (or (ess-inside-string-p pos) - (ess-inside-comment-p pos))) - -(defun ess-inside-brackets-p (&optional pos curly?) - "Return t if position POS is inside brackets. -POS defaults to point if no value is given. If CURLY?? is non nil -also return t if inside curly brackets." - (save-excursion - (let ((ppss (syntax-ppss pos)) - (r nil)) - (while (and (> (nth 0 ppss) 0) - (not r)) - (goto-char (nth 1 ppss)) - (when (or (char-equal ?\[ (char-after)) - (and curly? - (char-equal ?\{ (char-after)))) - (setq r t)) - (setq ppss (syntax-ppss))) - r))) - - -;;; String manipulation - -(defun ess-quote-special-chars (string) - "Quote special characters in STRING." - (replace-regexp-in-string - "\"" "\\\\\\&" - (replace-regexp-in-string ;; replace backslashes - "\\\\" "\\\\" string nil t))) - -(defun ess-rep-regexp (regexp to-string &optional fixedcase literal verbose) - "Instead of (replace-regexp..) -- do NOT replace in strings or comments. -If FIXEDCASE is non-nil, do *not* alter case of replacement text. -If LITERAL is non-nil, do *not* treat `\\' as special. -If VERBOSE is non-nil, (message ..) about replacements." - (let ((case-fold-search (and case-fold-search - (not fixedcase))); t <==> ignore case in search - (ppt (point)); previous point - (p)) - (while (and (setq p (re-search-forward regexp nil t)) - (< ppt p)) - (setq ppt p) - (cond ((not (ess-inside-string-or-comment-p (1- p))) - (if verbose - (let ((beg (match-beginning 0))) - (message "buffer in (match-beg.,p)=(%d,%d) is '%s'" - beg p (buffer-substring beg p)))) - (replace-match to-string fixedcase literal)))))) - -(defun ess-replace-regexp-dump-to-src (regexp to-string &optional dont-query verbose) - "Replace REGEXP matches from beginning of buffer with TO-STRING. -If DONT-QUERY is non-nil, call `ess-rep-regexp' else call -`query-replace-regexp'. VERBOSE can be passed to `ess-rep-regexp'." - (save-excursion - (goto-char (point-min)) - (if dont-query - (ess-rep-regexp regexp to-string nil nil verbose) - (query-replace-regexp regexp to-string nil)))) - -(defun ess-space-around (word &optional from verbose) - "Replace-regexp .. ensuring space around all occurrences of WORD. -Start at from FROM, which defaults to point." - (interactive "d\nP"); Defaults: point and prefix (C-u) - (save-excursion - (goto-char from) - (ess-rep-regexp (concat "\\([^ \t\n]\\)\\(\\<" word "\\>\\)") - "\\1 \\2" nil nil verbose) - (goto-char from) - (ess-rep-regexp (concat "\\(\\<" word "\\>\\)\\([^ \t\n]\\)") - "\\1 \\2" nil nil verbose))) - -(defun ess-time-string (&optional clock) - "Return a string for use as a timestamp, like \"13 Mar 1992\". -Include hr:min if CLOCK is non-nil. Redefine to taste." - (declare (obsolete format-time-string "ESS 19.04")) - (format-time-string (concat "%e %b %Y" (if clock ", %H:%M")))) - -(defun ess-replace-in-string (str regexp newtext &optional literal) - "Replace all matches in STR for REGEXP with NEWTEXT string. -Optional LITERAL non-nil means do a literal replacement. -Otherwise treat \\ in NEWTEXT string as special: - \\& means substitute original matched text, - \\N means substitute match for \(...\) number N, - \\\\ means insert one \\." - (if (not (stringp str)) - (error "(replace-in-string): First argument must be a string: %s" str)) - (if (stringp newtext) - nil - (error "(replace-in-string): 3rd arg must be a string: %s" - newtext)) - (let ((rtn-str "") - (start 0) - (special) - match prev-start) - (while (setq match (string-match regexp str start)) - (setq prev-start start - start (match-end 0) - rtn-str - (concat - rtn-str - (substring str prev-start match) - (cond (literal newtext) - (t (mapconcat - (function - (lambda (c) - (if special - (progn - (setq special nil) - (cond ((eq c ?\\) "\\") - ((eq c ?&) - (substring str - (match-beginning 0) - (match-end 0))) - ((and (>= c ?0) (<= c ?9)) - (if (> c (+ ?0 (length - (match-data)))) - ;; Invalid match num - (error "(replace-in-string) Invalid match num: %c" c) - (setq c (- c ?0)) - (substring str - (match-beginning c) - (match-end c)))) - (t (char-to-string c)))) - (if (eq c ?\\) (progn (setq special t) nil) - (char-to-string c))))) - newtext "")))))) - (concat rtn-str (substring str start)))) - -;;- From: friedman@gnu.ai.mit.edu (Noah Friedman) -;;- Date: 12 Feb 1995 21:30:56 -0500 -;;- Newsgroups: gnu.emacs.sources -;;- Subject: nuke-trailing-whitespace -;;- -;;- This is too trivial to make into a big todo with comments and copyright -;;- notices whose length exceed the size of the actual code, so consider it -;;- public domain. Its purpose is along similar lines to that of -;;- `require-final-newline', which is built in. I hope the names make it -;;- obvious. - -;; (add-hook 'write-file-hooks 'nuke-trailing-whitespace) -;;or at least -;; (add-hook 'ess-mode-hook -;; (lambda () -;; (add-hook 'local-write-file-hooks 'nuke-trailing-whitespace))) - -(defvar ess-nuke-trailing-whitespace-p nil;disabled by default 'ask - "[Dis]activates (ess-nuke-trailing-whitespace). -Disabled if nil; if t, it works unconditionally, otherwise, -the user is queried. -Note that setting the default to t may not be a good idea when you edit -binary files!") - -;;; MM: Newer Emacsen now have delete-trailing-whitespace -;;; -- but no customization like nuke-trailing-whitespace-p .. -(defun ess-nuke-trailing-whitespace () - "Nuke all trailing whitespace in the buffer. -Whitespace in this case is just spaces or tabs. This is a useful -function to put on `write-file-hooks'. If the variable -`ess-nuke-trailing-whitespace-p' is nil, this function is -disabled. If t, unreservedly strip trailing whitespace. If not -nil and not t, query for each instance." - (interactive) - (let ((bname (buffer-name))) - (cond ((or - (string= major-mode "rmail-mode") - (string= bname "RMAIL") - nil)); do nothing.. - (t - (and (not buffer-read-only) - ess-nuke-trailing-whitespace-p - (save-match-data - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (cond ((eq ess-nuke-trailing-whitespace-p t) - (while (re-search-forward "[ \t]+$" (point-max) t) - (delete-region (match-beginning 0) - (match-end 0)))) - (t - (query-replace-regexp "[ \t]+$" ""))))))))) - ;; always return nil, in case this is on write-file-hooks. - nil)) - - -;;; Debugging tools - -(defun ess-write-to-dribble-buffer (text) - "Write TEXT to `ess-dribble-buffer'." - (when (or ess-verbose ess-write-to-dribble) - (with-current-buffer (get-buffer-create ess-dribble-buffer) - (goto-char (point-max)) - (insert-before-markers text)))) - -(defun ess-if-verbose-write (text) - "Write TEXT to `ess-dribble-buffer' only if `ess-verbose' is non-nil." - (when ess-verbose (ess-write-to-dribble-buffer text))) - -(defun ess-kill-last-line () - (save-excursion - (goto-char (point-max)) - (forward-line -1) - (delete-region (point-at-eol) (point-max)))) - -(defun ess-sleep () - "Put Emacs to sleep for `ess-sleep-for-shell' seconds (floats work)." - (sleep-for ess-sleep-for-shell)) - -(defun ess-setq-vars-local (alist &optional buf) - "Set language variables from ALIST, in buffer BUF, if desired." - (when buf (set-buffer buf)) - (mapc (lambda (pair) - (make-local-variable (car pair)) - (set (car pair) (eval (cdr pair))) - (when (bound-and-true-p ess--make-local-vars-permanent) - (put (car pair) 'permanent-local t))) ;; hack for Rnw - alist)) - -(defvar ess-error-regexp "^\\(Syntax error: .*\\) at line \\([0-9]*\\), file \\(.*\\)$" - "Regexp to search for errors.") - -(define-obsolete-function-alias 'ess-beginning-of-function 'beginning-of-defun "ESS 19.04") -(define-obsolete-function-alias 'ess-end-of-function 'end-of-defun "ESS 19.04") - -(provide 'ess-utils) - -;;; ess-utils.el ends here diff --git a/elpa/ess-20191014.1343/ess.el b/elpa/ess-20191014.1343/ess.el deleted file mode 100644 index 8ad45957..00000000 --- a/elpa/ess-20191014.1343/ess.el +++ /dev/null @@ -1,221 +0,0 @@ -;;; ess.el --- Emacs Speaks Statistics -*- lexical-binding: t; -*- -;; -;; Author: David Smith -;; A.J. Rossini -;; Richard M. Heiberger -;; Kurt Hornik -;; Martin Maechler -;; Rodney A. Sparapani -;; Stephen Eglen -;; Sebastian P. Luque -;; Henning Redestig -;; Vitalie Spinu -;; Lionel Henry -;; J. Alexander Branham -;; -;; Maintainer: ESS Core Team -;; Copyright (C) 1997-2018 ESS Core Team -;; Created: 7 Jan 1994 -;; Version: 18.10.3snapshot -;; URL: https://ess.r-project.org/ -;; Package-Requires: ((emacs "25.1") (julia-mode "0.3")) -;; ESSR-Version: 1.5 -;; -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ -;; -;;; Commentary: -;; -;; Emacs Speaks Statistics (ESS) is a package designed to support editing of -;; scripts and interaction with various statistical analysis programs such as R, -;; S-Plus, SAS, Stata and OpenBUGS/JAGS. For more details please visit ESS home -;; page at https://ess.r-project.org/ -;; -;;; Code: - -(require 'ess-utils) -(require 'cl-generic) - -(defvar reporter-prompt-for-summary-p) - - -;; Versions - -(defconst ess-version (eval-when-compile - (require 'lisp-mnt) - (lm-version (or load-file-name buffer-file-name))) - "Version of ESS currently loaded.") - -(defconst essr-version (eval-when-compile - (require 'lisp-mnt) - (save-excursion (lm-header "ESSR-Version"))) - "Version of ESSR package.") - -(defvar ess-revision nil - "The revision and date of ESS. -Is set by \\[ess-version-string].") - -;;;###autoload -(defun ess-version () - "Return a string with ESS version information." - (interactive) - (message (format "ess-version: %s (loaded from %s)" - (ess-version-string) - (file-name-directory ess-lisp-directory)))) - -(defun ess-version-string () - (let* ((ess-dir (file-name-directory ess-lisp-directory)) ; if() the top-level 'ess/' - (is-release (file-exists-p (concat ess-etc-directory ".IS.RELEASE"))) - (rel-string (if is-release "Released ")) - (git-ref-fn (concat ess-dir ".git/HEAD")) - (git-ref (when (file-exists-p git-ref-fn) - (with-current-buffer (find-file-noselect git-ref-fn) - (goto-char (point-min)) - (when (re-search-forward "ref: \\(.*\\)\n" nil t) - (match-string 1))))) - (git-fname (if git-ref - (concat ess-dir ".git/" git-ref) - ;; For release - (concat ess-etc-directory "git-ref"))) - (git-rev (when (file-exists-p git-fname) - (with-current-buffer (find-file-noselect git-fname) - (goto-char (point-min)) - (concat "git: "(buffer-substring 1 (point-at-eol)))))) - (elpa-fname (concat ess-dir "ess-pkg.el")) - (elpa-rev (when (file-exists-p elpa-fname) - ;; Get it from ELPA dir name, (probably won't work if installed manually) - (concat "elpa: " - (replace-regexp-in-string "ess-" "" - (file-name-nondirectory - (substring ess-dir 1 -1))))))) - ;; Set the "global" ess-revision: - (setq ess-revision (format "%s%s%s" - (or rel-string "") - (or git-rev "") - (or elpa-rev ""))) - (when (string= ess-revision "") - (setq ess-revision "")) - (concat ess-version " [" ess-revision "]"))) - - -;;; Bug Reporting - -;;;###autoload -(defun ess-submit-bug-report () - "Submit a bug report to the ESS maintainers." - (interactive) - (let ((reporter-prompt-for-summary-p 't)) - (reporter-submit-bug-report - "ess-bugs@r-project.org" - (concat "ess-mode " (ess-version-string)) - (list 'ess-language - 'ess-dialect - 'ess-ask-for-ess-directory - 'ess-ask-about-transfile - 'default-directory - 'ess-keep-dump-files - 'ess-source-directory - 'ess-use-ido - 'ess-use-eldoc - 'ess-use-tracebug - 'ess-use-auto-complete - 'ess-use-company - 'ess-eval-visibly-p - 'ess-can-eval-in-background - 'ess-local-process-name) - nil - (lambda () - ;;(goto-char (point-max)) - (rfc822-goto-eoh) - (forward-line 1) - (insert "\n\n-------------------------------------------------------\n") - (insert "This bug report will be sent to the ESS bugs email list\n") - (insert "Press C-c C-c when you are ready to send your message.\n") - (insert "-------------------------------------------------------\n\n") - (insert (with-current-buffer ess-dribble-buffer - (goto-char (point-max)) - (forward-line -100) - (buffer-substring-no-properties (point) (point-max)))))))) - - - -;;; Timer - -(defcustom ess-idle-timer-interval 1 - "Number of idle seconds to wait before running function in `ess-idle-timer-functions'." - :type '(integer) - :group 'ess) - -(defvar ess-idle-timer-functions nil - "A list of functions to run each `ess-idle-timer-interval' idle seconds. -If your function calls the process, you better use -`ess-when-new-input' to wrap your call. If you call the -subprocess please respect `ess-can-eval-in-background' variable. - -These functions are run with `run-hooks'. Use `add-hook' to add -symbols to this variable. - -Most likely you will need a local hook. Then you should specify -the LOCAL argument to `add-hook' and initialize it in -`ess-mode-hook' or `ess-post-run-hook', or one of the more -specialized hooks `ess-r-post-run-hook',`ess-stata-post-run-hook' -etc.") - -(defun ess--idle-timer-function nil - "Internal function executed by `ess--idle-timer'." - (run-hooks 'ess-idle-timer-functions)) - -(require 'timer) -(defvar ess--idle-timer - (run-with-idle-timer ess-idle-timer-interval 'repeat 'ess--idle-timer-function) - "Timer used to run `ess-idle-timer-functions'.") - - -;;; Dispatch on ess-dialect -;; Inspired by major-mode specializer in cl-generic.el - -;; FIXME: Implement a notion of derived dialects. major-mode specializer cannot -;; be used here as we need same dialect in different major-modes. - -;; Two parts: -;; 1) first define a specializer (ess-dialect= DIALECT) to match symbols -;; representing ess dialects. -;; 2) then define a context-rewriter so you can write -;; `&context (ess-dialect "R")` rather than -;; `&context (ess-dialect (ess-dialect= "R"))`. - -(cl-generic-define-generalizer ess--generic-dialect-generalizer - 95 - (lambda (name &rest _) `(if (stringp ,name) (intern ,name) - (if (symbolp ,name) ,name))) - (lambda (tag &rest _) `((ess-dialect= ,tag)))) - -(cl-defmethod cl-generic-generalizers ((_specializer (head ess-dialect=))) - "Support for (ess-dialect DIALECT) context specializer." - (list ess--generic-dialect-generalizer)) - -(cl-generic-define-context-rewriter ess-dialect (dialect) - `(ess-dialect (ess-dialect= ,(if (stringp dialect) - (intern dialect) - dialect)))) - -;; (cl-defgeneric ess-print-dialect () -;; (error "unknown dialect %s" ess-dialect)) -;; (cl-defmethod ess-print-dialect (&context (ess-dialect "R")) -;; (message "dialect: R")) -;; (cl-defmethod ess-print-dialect (&context (ess-dialect "julia")) -;; (message "dialect: julia")) - -(provide 'ess) - -;;; ess.el ends here diff --git a/elpa/ess-20191014.1343/ess.info b/elpa/ess-20191014.1343/ess.info deleted file mode 100644 index 0ab70e35..00000000 --- a/elpa/ess-20191014.1343/ess.info +++ /dev/null @@ -1,4997 +0,0 @@ -This is ess.info, produced by makeinfo version 6.5 from ess.texi. - -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, BUGS/JAGS and Stata). -END-INFO-DIR-ENTRY - -ESS -- Emacs Speaks Statistics -****************************** - - -File: ess.info, Node: Top, Next: Introduction, Up: (dir) - -ESS: Emacs Speaks Statistics -**************************** - -ESS version 18.10.3snapshot - - by A.J. Rossini, - R.M. Heiberger, - K. Hornik, - M. Maechler, - R.A. Sparapani, - S.J. Eglen, - S.P. Luque, - H. Redestig, - V. Spinu, - L. Henry, - and J.A. Branham. - - Emacs Speaks Statistics (ESS) provides an intelligent, consistent - interface between the user and the software. ESS interfaces with - R, SAS, S-PLUS, BUGS/JAGS and other statistical analysis packages - on GNU/Linux, other Unix-like systems such as macOS, and Microsoft - Windows. ESS is itself a package within the Emacs text editor and - uses Emacs features to streamline the creation and use of - statistical software. ESS knows the syntax and grammar of - statistical analysis packages and provides consistent display and - editing features based on that knowledge. ESS assists in - interactive and batch execution of statements written in these - statistical analysis languages. - - The source and documentation of ESS is free software. You can -redistribute it and/or modify it under the terms of the GNU General -Public License as published by the Free Software Foundation; either -version 2, or (at your option) any later version. - - ESS is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License in -the file COPYING in the same directory as this file for more details. - -* Menu: - -* Introduction:: Overview of features provided by this package -* Installation:: Installing ESS on your system -* Interactive ESS:: Interacting with statistical programs -* Entering commands:: Interacting with the ESS process -* Evaluating code:: Sending code to the ESS process -* Transcript Mode:: Manipulating saved transcript files -* Editing objects:: How to create/edit objects and functions -* Help:: Reading help files -* Completion:: Various completion mechanisms -* Developing with ESS:: Tools for package development and debugging -* Extras:: Other ESS features for the S family -* ESS for R:: Overview of ESS features for the S family -* ESS for SAS:: -* ESS for BUGS:: -* ESS for JAGS:: -* Mailing lists/bug reports:: How to get assistance with ESS -* Customization:: Customizing ESS -* Indices:: - - -File: ess.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top - -1 Introduction to ESS -********************* - -ESS provides a generic interface, through Emacs, to statistical -packages. It currently supports R (and the rest of the S family), SAS, -BUGS/JAGS, Stata, and Julia with the level of support roughly in that -order. - - Throughout this manual, _Emacs_ refers to _GNU Emacs_ by the Free -Software Foundation. Although previous versions of ESS supported other -Emacsen, current versions only support GNU Emacs. - - There are two main ways of interacting with ESS: through "regular" -modes or "inferior" modes. Regular modes act like normal Emacs major -modes. ESS major modes are displayed in the mode-line in the format -'ESS[dialect]', where 'dialect' can take values such as 'R', 'SAS', or -'S'. - - ESS also provides easy access to an "inferior process," which is an -Emacs buffer associated with a running process. This can be an R -session, for example. These inferior processes are referred to as -inferior ESS ('iESS'), and are shown in the modeline by 'iESS -[dialect]'. - - Currently, the documentation contains many references to ''R'' where -actually any supported (statistics) language is meant, i.e., 'R' could -also mean 'S' or 'SAS.' - - For exclusively interactive users of R, ESS provides a number of -features to make life easier. There is an easy to use command history -mechanism, including a quick prefix-search history. To reduce typing, -command-line completion is provided for all R objects and "hot keys" are -provided for common R function calls. Help files are easily accessible, -and a paging mechanism is provided to view them. Finally, an incidental -(but very useful) side-effect of ESS is that a transcript of your -session is kept for later saving or editing. - - No special knowledge of Emacs is necessary when using R interactively -under ESS. - - For those that use R in the typical edit-test-revise cycle when -writing R functions, ESS provides for editing of R functions in Emacs -buffers. Unlike the typical use of R where the editor is restarted -every time an object is edited, ESS uses the current Emacs session for -editing. In practical terms, this means that you can edit more than one -function at once, and that the ESS process is still available for use -while editing. Error checking is performed on functions loaded back -into R, and a mechanism to jump directly to the error is provided. ESS -also provides for maintaining text versions of your R functions in -specified source directories. - -* Menu: - -* Features:: Why should I use ESS? -* New features:: -* Credits:: Authors of and contributors to ESS -* Manual:: How to read this manual - - -File: ess.info, Node: Features, Next: New features, Up: Introduction - -1.1 Why should I use ESS? -========================= - -Statistical packages are powerful software systems for manipulating and -analyzing data, but their user interfaces often leave something to be -desired: they offer weak editor functionality and they differ among -themselves so markedly that you have to re-learn how to do those things -for each package. ESS is a package which is designed to make editing -and interacting with statistical packages more uniform, user-friendly -and give you the power of Emacs as well. - - Additionally, both Emacs and ESS (and R) are free software designed -to give users full control over their computer. For more on what this -means, visit . - -* Menu: - -* Current Features:: - - -File: ess.info, Node: Current Features, Up: Features - -1.1.1 Features Overview ------------------------ - - * Languages Supported: - * S family (R, S, and S+ AKA S-PLUS) - * SAS - * BUGS/JAGS - * Stata - * Julia - * Editing source code (S family, SAS, BUGS/JAGS, Stata, Julia) - * Syntactic indentation and highlighting of source code - * Partial evaluation of code - * Loading and error-checking of code - * Source code revision maintenance - * Batch execution (SAS, BUGS/JAGS) - * Use of imenu to provide links to appropriate functions - * Interacting with the process (S family, SAS, Stata, Julia) - * Command-line editing - * Searchable Command history - * Command-line completion of S family object names and file - names - * Quick access to object lists and search lists - * Transcript recording - * Interface to the help system - * Transcript manipulation (S family, Stata) - * Recording and saving transcript files - * Manipulating and editing saved transcripts - * Re-evaluating commands from transcript files - * Interaction with Help Pages and other Documentation (R) - * Fast Navigation - * Sending Examples to running ESS process. - * Fast Transfer to Further Help Pages - * Help File Editing (R) - * Syntactic indentation and highlighting of source code. - * Sending Examples to running ESS process. - * Previewing - - For source code buffers, ESS offers several features: - - * Support for multiple indentation styles R code *Note Indenting::. - - * Facilities for loading and error-checking source files, including a - keystroke to jump straight to the position of an error in a source - file. *Note Error Checking::. - - * Source code revision maintenance, which allows you to keep historic - versions of R source files. *Note Source Files::. - - * Facilities for evaluating R code such as portions of source files, - or line-by-line evaluation of files (useful for debugging). *Note - Evaluating code::. - - ESS also provides features that make it easier to interact with -inferior ESS (iESS) process (a connection between your buffer and the -statistical package which is waiting for you to input commands). These -include: - - * Command-line editing for fixing mistakes in commands before they - are entered. *Note Command-line editing::. - - * Searchable command history for recalling previously-submitted - commands. *Note Command History::. - - * Command-line completion of both object and file names for quick - entry. *Note Completion::. - - * Hot-keys for quick entry of commonly-used commands in 'R' such as - 'objects()', and 'search()'. *Note Hot keys::. - - * Transcript recording for a complete record of all the actions in an - R session. *Note Transcript::. - - * Interface to the help system, with a specialized mode for viewing R - help files. *Note Help::. - - * Object editing. ESS allows you to edit more than one function - simultaneously in dedicated Emacs buffers. The ESS process may - continue to be used while functions are being edited. *Note Edit - buffer::. - - Finally, ESS provides features for re-submitting commands from saved -transcript files, including: - - * Evaluation of previously entered commands, stripping away - unnecessary prompts. *Note Transcript resubmit::. - - -File: ess.info, Node: New features, Next: Credits, Prev: Features, Up: Introduction - -1.2 New features in ESS -======================= - -Changes and New Features in 19.04 (unreleased): - - * ESS[R]: There is a new menu entry for reloading the R process. It - is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same - process name and start arguments that were used to start the - process. - - * iESS: Process runners now return the inferior buffer. Note that - callers of inferior runners should not assume that the current - buffer has been set to the inferior buffer. Instead, use - 'with-current-buffer' with the return value of the inferior. - - * iESS[SAS]: The SAS keymap was only set in iESS buffers called - '*SAS*'. This is now fixed. - - * ESS[R]: Fixed longstanding indentation issues involving '::' and - ':::' operators. - - * Implement a more reliable check for the process busy state. - Background actions such as completion and directory synchronization - should not block the process and should not cause printing of the - extraneous output to the interpreter. - - * Activate 'goto-address-mode' for url and email highlighting in - inferior buffers. - - * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. - Users who liked the previous behavior (i.e. underscore inserting - "<-") should bind 'ess-insert-assign' to the underscore in their - Emacs initialization file. For example, '(define-key - ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key - inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it - in all ESS R buffers. - - * ESS major modes are now defined using 'define-derived-mode'. This - makes ESS major modes respect modern conventions such as having - -mode-hook and -mode-map. Users are encouraged - to place customizations under the appropriate mode. - - * New option ess-auto-width controls setting the width option on - window changes. Users can change it to 'frame, 'window, or an - integer. See the documentation for details. - 'ess-auto-width-visible' controls visibility. - - * ESS now respects 'display-buffer-alist'. Users can now use - 'display-buffer-alist' to manage how and where windows appear. See - *Note (ess)Controlling buffer display:: for more information and - examples. - - * 'ess-roxy-mode' can now be enabled in non-R buffers. This is - primarily intended to support roxygen documentation for cpp - buffers. Preview functionality is not supported outside R buffers. - - * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. - - * 'ess-style' now has effects when set as a file or directory local - variable. - - * 'ess-default-style' is now obsolete, use 'ess-style' instead. - - * Options for 'ess-gen-proc-buffer-name-function' have been renamed. - ess-gen-proc-buffer-name:projectile-or-simple was renamed to - ess-gen-proc-buffer-name:project-or-simple and - ess-gen-proc-buffer-name:projectile-or-directory was renamed to - ess-gen-proc-buffer-name:project-or-directory. As the name - suggests, these now rely on project.el (included with Emacs) rather - than projectile.el, which is a third-party package. - - * ESS[R]: devtools commands ask about saving modified buffers before - running. Users can disable the questioning with - 'ess-save-silently'. - - * ESS[R] help pages now provide links to other help topics. This is - similar with what you would see with, for example - 'options(help_type = ``html'')' but works with the plain-text - version as well. This only works with 'options(useFancyQuotes = - TRUE)' (the default). - - * 'ess-rdired' buffers now derive from tabulated-list-mode. They - should look better and be a bit faster overall. The size column - now displays object sizes in bytes. - - * 'ess-rdired' buffers now auto-update. The frequency is governed by - the new option 'ess-rdired-auto-update-interval'. - - * ESS[R]: 'electric-layout-mode' is now supported. This - automatically inserts a newline after an opening curly brace in R - buffers. To enable it, customize 'ess-r-mode-hook'. - - * ESS[R]: imenu now supports assignment with the equals sign. - - * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. - - * ESS removed support for many unused languages. This includes old - versions of S+, ARC, OMG, VST, and XLS. - - The following have been made obsolete or removed, see their -documentation for more detail: - - * Libraries for literate data analysis are obsolete and not loaded by - default. This includes 'ess-noweb', 'ess-swv', and related - functionality like 'Rnw-mode'. Users are encouraged to switch to - one of several other packages that deal with these modes. For - example, polymode , - , or markdown-mode with edit-indirect - . - - * Support for 'auto-complete' is obsolete. The 'auto-complete' - package is unmaintained and so ESS support is now obsolete. Users - are encouraged to switch to 'company-mode' instead. - - * User options for controlling display of buffers. This includes - 'ess-show-buffer-action', 'inferior-ess-same-window', - 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See - above about ESS respecting 'display-buffer-alist'. - - * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. - Use the Emacs-wide setting of 'tab-always-indent' instead. - - * 'inferior-ess-*-start-file' variables. All modes except Stata did - not respect customization of this variable. In order to load a - file on startup, you should put a function on - 'ess-*-post-run-hook'. - - Bug Fixes in 18.10.3: - * More 'Makefile' fixes, notably installing '*.el's. - - Bug Fixes in 18.10.2: - * ESS[R] Fix namespace evaluation in non-installed packages. - Evaluation is directed into GlobalEnv as originally intended. - * 'Makefile' fixes, notably for 'make install' and including full - docs in the tarballs. - - Bug Fixes in 18.10-1: - * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and - 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave - as the old versions of 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step'. - - Changes and New Features in 18.10: - - * This is the last release to support Emacs older than 25.1. Going - forward, only GNU Emacs 25.1 and newer will be supported. Soon - after this release, support for older Emacs versions will be - dropped from the git master branch. Note that MELPA uses the git - master branch to produce ESS snapshots, so if you are using Emacs < - 25.1 from MELPA and are unable to upgrade, you should switch to - MELPA-stable. - - * ESS now displays the language dialect in the mode-line. So, for - example, R buffers will now show ESS[R] rather than ESS[S]. - - * The ESS manual has been updated and revised. - - * The ESS initialization process has been further streamlined. If - you update the autoloads (which installation from 'package-install' - does), you should not need to '(require 'ess-site)' at all, as - autoloads should automatically load ESS when it is needed (e.g. - the first time an R buffer is opened). In order to defer loading - your ESS config, you may want to do something like - '(with-require-after-load "ess" )' in your Emacs - init file. Users of the popular 'use-package' Emacs package can - now do '(use-package ess :defer t)' to take advantage of this - behavior. *Note (ess)Activating and Loading ESS:: for more - information on this feature. - - * ESS now respects Emacs conventions for keybindings. This means - that The 'C-c [letter]' bindings have been removed. This affects - 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in - 'sas-mode-local-map'; 'C-c f', which was bound to - 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', - which was bound to 'ess-handy-commands' in 'Rd-mode-map', - 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' - - * Functions 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step' now behave consistently with - other evaluation function inside a package. - - * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets - the working directory to the root of the current package including - for example C or C++ files within '/src'). - - * ESS[R]: Long + + prompts in the inferior no longer offset output. - - * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This - strips the entire + + sequence. - - * ESS modes now inherit from 'prog-mode'. In the next release, ESS - modes will use 'define-derived-mode' so that each mode will have - (for example) its own hooks and keymaps. - - * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. - Users need to install the 'lintr' package to use it. Customizable - options include 'ess-use-flymake', 'ess-r-flymake-linters', and - 'ess-r-flymake-lintr-cache'. - - * ESS[R]: Gained support for xref in Emacs 25+. *Note (emacs)Xref:: - - * ESS[R]: The startup screen is cleaner. It also displays the - startup directory with an explicit 'setwd()'. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[R]: 'Makevars' files open with 'makefile-mode'. - - * New variable 'ess-write-to-dribble'. This allows users to disable - the dribble ('*ESS*') buffer if they wish. - - * All of the '*-program-name' variables have been renamed to - '*-program'. Users who previously customized e.g. - 'inferior-ess-R-program-name' will need to update their - customization to 'inferior-ess-R-program'. These variables are - treated as risky variables. - - * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It - provides similar functionality but for any keybinding, not just - '_'. For instance if you bind it to ';', repeated invocations - cycle through between assignment and inserting ';'. - - * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the - documentation for details. New user customization option - 'ess-assign-list' controls which assignment operators are cycled. - - * ESS[R] In remote sessions, the ESSR package is now fetched from - GitHub. - - * Commands that send the region to the inferior process now deal with - rectangular regions. See the documentation of 'ess-eval-region' - for details. This only works on Emacs 25.1 and newer. - - * ESS[R]: Improvements to interacting with iESS in non-R files. - Interaction with inferior process in non-R files within packages - (for instance C or C++ files) has been improved. This is a work in - progress. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in - JAGS mode. - - Many improvements to fontification: - - * Improved customization for faces. ESS now provides custom faces - for (nearly) all faces used and places face customization options - into their own group. Users can customize these options using 'M-x - customize-group RET ess-faces'. - - * Many new keywords were added to 'ess-R-keywords' and - 'ess-R-modifiers'. See the documentation for details. - - * ESS[R]: 'in' is now only fontified when inside a 'for' construct. - This avoids spurious fontification, especially in the output buffer - where 'in' is a common English word. - - * ESS: Font-lock keywords are now generated lazily. That means you - can now add or remove keywords from variables like 'ess-R-keywords' - in your Emacs configuration file after loading ESS (i.e. in the - ':config' section for 'use-package' users). - - * ESS[R]: Fontification of roxygen '@param' keywords now supports - comma-separated parameters. - - * ESS[R]: Certain keywords are only fontified if followed by a - parenthesis. Function-like keywords such as 'if ()' or 'stop()' - are no longer fontified as keyword if not followed by an opening - parenthesis. The same holds for search path modifiers like - 'library()' or 'require()'. - - * ESS[R]: Fixed fontification toggling. Especially certain syntactic - elements such as '%op%' operators and backquoted function - definitions. - - * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. - This command asks with completion for a font-lock group to toggle. - This functionality is equivalent to the font-lock menu. - - Notable bug fixes: - - * 'prettify-symbols-mode' no longer breaks indentation. This is - accomplished by having the pretty symbols occupy the same number of - characters as their non-pretty cousins. You may customize the new - variable 'ess-r-prettify-symbols' to control this behavior. - - * ESS: Inferior process buffers are now always displayed on startup. - Additionally, they don't hang Emacs on failures. - - Obsolete libraries, functions, and variables: - - * The 'ess-r-args.el' library has been obsoleted and will be removed - in the next release. Use 'eldoc-mode' instead, which is on by - default. - - * Functions and options dealing with the smart assign key are - obsolete. The following functions have been made obsolete and will - be removed in the next release of ESS: 'ess-smart-S-assign', - 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', - 'ess-disable-smart-S-assign'. - - The variable 'ess-smart-S-assign-key' is now deprecated and will be - removed in the next release. If you would like to continue using - '_' for inserting assign in future releases, please bind - 'ess-insert-assign' in 'ess-mode-map' the normal way. - - * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. - Use 'ess-s-versions' instead. You may pass arguments by starting - the inferior process with the universal argument. - - Changes and New Features in 17.11: - - * The ESS initialization process has been streamlined. You can now - load the R and Stata modes independently from the rest of ESS. Just - put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your - init file. This is for experienced Emacs users as this requires - setting up autoloads for '.R' files manually. We will keep - maintaining 'ess-site' for easy loading of all ESS features. - - * Reloading and quitting the process is now more robust. If no - process is attached, ESS now switches automatically to one - (prompting you for selection if there are several running). - Reloading and quitting will now work during a debug session or when - R is prompting for input (for instance after a crash). Finally, - the window configuration is saved and restored after reloading to - prevent the buffer of the new process from capturing the cursor. - - * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working - directory of the current process to the current package directory. - - * ESS[R] Lookup for references in inferior buffers has been improved. - New variable 'ess-r-package-source-roots' contains package - sub-directories which are searched recursively during the file - lookup point. Directories in 'ess-tracebug-search-path' are now - also searched recursively. - - * ESS[R] Namespaced evaluation is now automatically enabled only in - the 'R/' directory. This way ESS will not attempt to update - function definitions from a package if you are working from e.g. a - test file. - - Changes and New Features in 16.10: - - * ESS[R]: Syntax highlighting is now more consistent. Backquoted - names are not fontified as strings (since they really are - identifiers). Furthermore they are now correctly recognized when - they are function definitions or function calls. - * ESS[R]: Backquoted names and '%op%' operators are recognized as - sexp. This is useful for code navigation, e.g. with 'C-M-f' and - 'C-M-b'. - * ESS[R]: Integration of outline mode with roxygen examples fields. - You can use outline mode's code folding commands to fold the - examples field. This is especially nice to use with well - documented packages with long examples set. Set - 'ess-roxy-fold-examples' to non-nil to automatically fold the - examples field when you open a buffer. - * ESS[R]: New experimental feature: syntax highlighting in roxygen - examples fields. This is turned off by default. Set - 'ess-roxy-fontify-examples' to non-nil to try it out. - * ESS[R]: New package development command 'ess-r-devtools-ask' bound - to 'C-c C-w C-a'. It asks with completion for any devtools command - that takes 'pkg' as argument. - * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. - Currently only implemented for R. The R method runs - 'inferior-ess-r-reload-hook' on reloading. - * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers - as well. - - Bug fixes in 16.10: - * ESS[R]: Fix broken (un)flagging for debugging inside packages - * ESS[R]: Fixes (and improvements) in Package development - * ESS[R]: Completion no longer produces '...=' inside 'list( )'. - * ESS[R]: Better debugging and tracing in packages. - * ESS[R]: Better detection of symbols at point. - * ESS[R]: No more spurious warnings on deletion of temporary files. - * ESS[julia]: help and completion work (better) - * ESS[julia]: available via 'ess-remote' - - Changes and New Features in 16.04: - - * ESS[R]: 'developer' functionality has been refactored. The new - user interface consists of a single command - 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once - an evaluation environment has been set with, all subsequent ESS - evaluation will source the code into that environment. By default, - for file within R packages the evaluation environment is set to the - package environment. Set 'ess-r-package-auto-set-evaluation-env' - to 'nil' to disable this. - * ESS[R]: New 'ess-r-package-mode' This development mode provides - features to make package development easier. Currently, most of - the commands are based on the 'devtools' packages and are - accessible with 'C-c C-w' prefix. See the documentation of - 'ess-r-package-mode' function for all available commands. With - 'C-u' prefix each command asks for extra arguments to the - underlying devtools function. This mode is automatically enabled - in all files within R packages and is indicated with '[pkg:NAME]' - in the mode-line. - * ESS[R]: Help lookup has been improved. It is now possible to get - help for namespaced objects such as pkg::foobar. Furthermore, ESS - recognizes more reliably when you change 'options('html_type')'. - * ESS[R]: New specialized breakpoints for debugging magrittr pipes - * ESS: ESS now implements a simple message passing interface to - communicate between ESS and inferior process. - - Bug fixes in 16.04: - * ESS[R]: Roxygen blocks with backtics are now correctly filled - * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' - * ESS[R]: Error highlighting now understands 'testthat' type errors - * ESS[Julia]: Added getwd and setwd generic commands - - -File: ess.info, Node: Credits, Next: Manual, Prev: New features, Up: Introduction - -1.3 Authors of and contributors to ESS -====================================== - -The ESS environment is built on the open-source projects of many -contributors, dating back to 1989 where Doug Bates and Ed Kademan wrote -S-mode to edit S and Splus files in GNU Emacs. Frank Ritter and Mike -Meyer added features, creating version 2. Meyer and David Smith made -further contributions, creating version 3. For version 4, David Smith -provided significant enhancements to allow for powerful process -interaction. - - John Sall wrote GNU Emacs macros for SAS source code around 1990. -Tom Cook added functions to submit jobs, review listing and log files, -and produce basic views of a dataset, thus creating a SAS-mode which was -distributed in 1994. - - In 1994, A.J. Rossini extended S-mode to support XEmacs. Together -with extensions written by Martin Maechler, this became version 4.7 and -supported S, Splus, and R. In 1995, Rossini extended SAS-mode to work -with XEmacs. - - In 1997, Rossini merged S-mode and SAS-mode into a single Emacs -package for statistical programming; the product of this marriage was -called ESS version 5. Richard M. Heiberger designed the inferior mode -for interactive SAS and SAS-mode was further integrated into ESS. Thomas -Lumley's Stata mode, written around 1996, was also folded into ESS. More -changes were made to support additional statistical languages, -particularly XLispStat. - - ESS initially worked only with Unix statistics packages that used -standard-input and standard-output for both the command-line interface -and batch processing. ESS could not communicate with statistical -packages that did not use this protocol. This changed in 1998 when -Brian Ripley demonstrated use of the Windows Dynamic Data Exchange (DDE) -protocol with ESS. Heiberger then used DDE to provide interactive -interfaces for Windows versions of Splus. In 1999, Rodney A. Sparapani -and Heiberger implemented SAS batch for ESS relying on files, rather -than standard-input/standard-output, for Unix, Windows and Mac. In -2001, Sparapani added BUGS batch file processing to ESS for Unix and -Windows. - - * The multiple process code, and the idea for - 'ess-eval-line-and-next-line' are by Rod Ball. - - * Thanks to Doug Bates for many useful suggestions. - - * Thanks to Martin Maechler for reporting and fixing bugs, providing - many useful comments and suggestions, and for maintaining the ESS - mailing lists. - - * Thanks to Frank Ritter for updates, particularly the menu code, and - invaluable comments on the manual. - - * Thanks to Ken'ichi Shibayama for his excellent indenting code, and - many comments and suggestions. - - * Thanks to Aki Vehtari for adding interactive BUGS support. - - * Thanks to Brendan Halpin for bug-fixes and updates to Stata-mode. - - * Last, but definitely not least, thanks to the many ESS users and - contributors to the ESS mailing lists. - - _ESS_ is being developed and currently maintained by - - * A.J. Rossini (mailto:blindglobe@gmail.com) - * Richard M. Heiberger (mailto:rmh@temple.edu) - * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) - * Martin Maechler (mailto:maechler@stat.math.ethz.ch) - * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) - * Stephen Eglen (mailto:stephen@gnu.org) - * Sebastian P. Luque (mailto:spluque@gmail.com) - * Henning Redestig (mailto:henning.red@googlemail.com) - * Vitalie Spinu (mailto:spinuvit@gmail.com) - * Lionel Henry (mailto:lionel.hry@gmail.com) - * J. Alexander Branham (mailto:alex.branham@gmail.com) - - -File: ess.info, Node: Manual, Prev: Credits, Up: Introduction - -1.4 How to read this manual -=========================== - -If you need to install ESS, read *note Installation:: for details on -what needs to be done before proceeding to the next chapter. This -section describes some of the basics of using Emacs. If you are already -familiar with basic Emacs functionality, skip this section. You may -also want to use the Emacs tutorial, accessible via 'C-h t'. - - In this manual we use the standard notation used by Emacs for -describing the keystrokes used to invoke certain commands. 'C-' -means hold the CONTROL key while typing the character . 'M-' -means hold the META key (usually ALT) down while typing . If there -is no META, EDIT or ALT key, instead press and release the ESC key and -then type . - - All ESS commands can be invoked by typing 'M-x command'. Most of the -useful commands are bound to keystrokes for ease of use. Also, the most -popular commands are also available through the Emacs menubar, and a -small subset are provided on the toolbar. Where possible, keybindings -are similar to other modes in Emacs to strive for a consistent user -interface within Emacs, regardless of the details of which programming -language is being edited, or process being run. - - Some commands, such as 'M-x R' can accept an optional 'prefix' -argument. To specify the prefix argument, you would type 'C-u' before -giving the command. For example, if you type 'C-u M-x R', you will be -asked for command line options that you wish to invoke the R process -with. - - Emacs is a 'self-documenting' text editor. This applies to ESS in -two ways. First, some documentation about each ESS command can be -obtained by typing 'C-h f'. For example, if you type 'C-h f -ess-eval-region', documentation for that command will appear in a -separate *Help* buffer. Second, 'C-h m' pops up a complete list of -keybindings available in each ESS mode and brief description of that -mode. - - Emacs is a versatile editor written in both C and a dialect of lisp -known as elisp. ESS is written in elisp and benefits from the flexible -nature of lisp. In particular, many aspects of ESS behaviour can be -changed by suitable customization of lisp variables. This manual -mentions some of the most frequent variables. A full list of them -however is available by using the Custom facility within Emacs. Type -'M-x customize-group RET ess RET' to get started. *note Customization:: -provides details of common user variables you can change to customize -ESS to your taste, but it is recommended that you defer this section -until you are more familiar with ESS. - - -File: ess.info, Node: Installation, Next: Interactive ESS, Prev: Introduction, Up: Top - -2 Installing ESS on your system -******************************* - -ESS supports GNU Emacs versions 25.1 and newer. - - ESS is most likely to work with current/recent versions of the -following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. - - To build the PDF documentation, you will need a version of TeX Live -or texinfo that includes texi2dvi. - - There are two main methods used for installing ESS. You may install -from a third-party repository or from source code. Once you install it, -you must also activate or load ESS in each Emacs session, though -installation from a third-party repository likely takes care of that for -you. See *note Activating and Loading ESS:: for more details. - -* Menu: - -* Installing from a third-party repository:: -* Installing from source:: -* Activating and Loading ESS:: -* Check Installation:: - - -File: ess.info, Node: Installing from a third-party repository, Next: Installing from source - -2.1 Installing from a third-party repository -============================================ - -ESS is packaged by many third party repositories. Many GNU/Linux -distributions package it, usually with the name "emacs-ess" or similar. - - ESS is also available through Milkypostman’s Emacs Lisp Package -Archive (MELPA), a popular repository for Emacs packages. Instructions -on how to do so are found on MELPA's website (https://melpa.org/). -MELPA also hosts MELPA-stable with stable ESS builds. You may choose -between MELPA with the latest and greatest features (and bugs) or -MELPA-stable, which may lag a bit behind but should be more stable. - - After installing, users should make sure ESS is activated or loaded -in each Emacs session. See *note Activating and Loading ESS::. -Depending on install method, this may be taken care of automatically. - - -File: ess.info, Node: Installing from source, Next: Activating and Loading ESS, Prev: Installing from a third-party repository - -2.2 Installing from source -========================== - -Stable versions of ESS are available at the ESS web page -(https://ess.r-project.org) as a .tgz file or .zip file. ESS releases -are GPG-signed, you should check the signature by downloading the -accompanying '.sig' file and doing: - - gpg --verify ess-18.10.tgz.sig - - Alternatively, you may download the git repository. ESS is currently -hosted on GitHub: . 'git clone -https://github.com/emacs-ess/ESS.git' will download it to a new -directory 'ESS' in the current working directory. - - We will refer to the location of the ESS source files as -'/path/to/ESS/' hereafter. - - After installing, users should make sure they activate or load ESS in -each Emacs session, see *note Activating and Loading ESS:: - - Optionally, compile elisp files, build the documentation, and the -autoloads: - cd /path/to/ESS/ - make - Without this step the documentation, reference card, and autoloads -will not be available. Uncompiled ESS will also run slower. - - Optionally, you may make ESS available to all users of a machine by -installing it site-wide. To do so, run 'make install'. You might need -administrative privileges: - - make install - - The files are installed into '/usr/share/emacs' directory. For this -step to run correctly on macOS, you will need to adjust the 'PREFIX' -path in 'Makeconf'. The necessary code and instructions are commented -in that file. - - -File: ess.info, Node: Activating and Loading ESS, Next: Check Installation, Prev: Installing from source - -2.3 Activating and Loading ESS -============================== - -After installing ESS, you must activate or load it each Emacs session. -ESS can be autoloaded, and if you used a third-party repository (such as -your Linux distribution or MELPA) to install, you can likely skip this -section and proceed directly to *note Check Installation:: - - Otherwise, you may need to add the path to ESS to 'load-path' with: - - (add-to-list 'load-path "/path/to/ESS/lisp") - - You then need to decide whether to take advantage of deferred loading -(which will result in a faster Emacs startup time) or require ESS when -Emacs is loaded. To autoload ESS when needed (note that if installed -from source, you must have run 'make'): - - (load "ess-autoloads") - - To require ESS on startup, you can either put - - (require 'ess-site) - - or - - (require 'ess-r-mode) - - In your configuration file, depending on whether you want all ESS -features or only R related features. - - -File: ess.info, Node: Check Installation, Prev: Activating and Loading ESS - -2.4 Check Installation -====================== - -Restart Emacs and check that ESS was loaded from a correct location with -'M-x ess-version'. - - -File: ess.info, Node: Interactive ESS, Next: Entering commands, Prev: Installation, Up: Top - -3 Interacting with statistical programs -*************************************** - -As well as using ESS to edit your source files for statistical programs, -you can use ESS to run these statistical programs. In this chapter, we -mostly will refer by example to running R from within Emacs. The Emacs -convention is to name such processes running under its control as -'inferior processes'. Some users find this terminology confusing; you -may prefer to think of these as 'interactive processes.' Either way, we -use the term 'iESS' to refer to the Emacs mode used to interact with -statistical programs. - -* Menu: - -* Starting up:: -* Multiple ESS processes:: -* ESS processes on Remote Computers:: -* Customizing startup:: -* Controlling buffer display:: - - -File: ess.info, Node: Starting up, Next: Multiple ESS processes, Up: Interactive ESS - -3.1 Starting an ESS process -=========================== - -To start an inferior R session on GNU/Linux, macOS, or Windows using the -Cygwin bash shell, simply type 'M-x R RET'. To start an R session on -Windows when you use the MSDOS/powershell shell, simply type 'M-x -S+6-msdos RET'. R will then (by default) ask the question - - R starting data directory? - -Enter the name of the directory you wish to have as the working -directory (that is, the directory you wish to have 'getwd()' return if -using R). - - You will then be popped into a buffer named '*R*' which will be used -for interacting with the ESS process, and you can start entering -commands. - - -File: ess.info, Node: Multiple ESS processes, Next: ESS processes on Remote Computers, Prev: Starting up, Up: Interactive ESS - -3.2 Running more than one ESS process -===================================== - -ESS allows you to run more than one iESS process simultaneously in the -same session. Each process has a name and a number; the initial process -(process 1) is simply named 'R'. If you call 'M-x R' again without -killing the first R process, ESS will start a second R process with the -name 'R:2'. To have the first buffer named 'R:1', customize the option -'ess-plain-first-buffername'. With a prefix argument, 'C-u M-x R' -allows for the specification of command line options. - - -- User Option: ess-plain-first-buffername - If non-'nil', name the first iESS process [R]. Otherwise, name it - [R:1]. - - You can switch to any active ESS process with the command 'M-x -ess-request-a-process'. Just enter the name of the process you require; -completion is provided over the names of all running processes. This is -a good command to consider binding to a global key. - - -File: ess.info, Node: ESS processes on Remote Computers, Next: Customizing startup, Prev: Multiple ESS processes, Up: Interactive ESS - -3.3 ESS processes on Remote Computers -===================================== - -3.3.1 ESS and TRAMP -------------------- - -ESS works with processes on remote computers as easily as with processes -on the local machine. The recommended way to access a statistical -program on remote computer is to start it with *Note (tramp)Top::. - - Start an ssh session using TRAMP with 'C-x C-f /ssh:user@host: RET'. -Tramp should open a dired buffer in your remote home directory. Now -call your favorite ESS process ('R', 'Julia', 'stata' etc) as you would -usually do on local machine: 'M-x R'. - - Alternatively you can start your process normally ('M-x R'). When -asked for starting directory, simply type '/ssh:user@host: RET'. The R -process will be started on the remote machine. - - To simplify the process even further create a "config" file in your -'.ssh/' folder and add an account. For example if you use amazon EC2, -it might look like following: - - Host amazon - Hostname ec2-54-215-203-181.us-west-1.compute.amazonaws.com - User ubuntu - IdentityFile ~/.ssh/my_amazon_key.pem - ForwardX11 yes - - With this configuration '/ssh:amazon:' is enough to start a -connection. The ForwardX11 is needed if you want to see the R graphic -device showing on the current machine - -3.3.2 ESS-remote ----------------- - -TRAMP is the recommended way of starting a remote session. The other -way to start a remote ESS connection is through 'ess-remote'. - - 1. Start a new shell, telnet or ssh buffer and connect to the remote - computer (e.g. use, 'M-x shell', 'M-x telnet' or 'M-x ssh'; ssh.el - is available at - ). - - 2. Start the ESS process on the remote machine, for example with one - of the commands 'R', 'Splus', or 'sas -stdio'. - - 3. Start 'M-x ess-remote'. You will be prompted for a program name - with completion. Choose one. Your process is now known to ESS. - All the usual ESS commands ('C-c C-n' and its relatives) now work - with the R language processes. For SAS you need to use a different - command 'C-c i' (that is a regular 'i', not a 'C-i') to send lines - from your 'myfile.sas' to the remote SAS process. 'C-c i' sends - lines over invisibly. With ess-remote you get teletype - behavior--the data input, the log, and the listing all appear in - the same buffer. To make this work, you need to end every PROC and - DATA step with a "RUN;" statement. The "RUN;" statement is what - tells SAS that it should process the preceding input statements. - - 4. Graphics (interactive) on the remote machine. If you run X11 - (*Note X11::, X Windows) on both the local and remote machines then - you should be able to display the graphs locally by setting the - 'DISPLAY' environment variable appropriately. Windows users can - download 'xfree86' from cygwin. - - 5. Graphics (static) on the remote machine. If you don't run the X - window system on the local machine, then you can write graphics to - a file on the remote machine, and display the file in a graphics - viewer on the local machine. Most statistical software can write - one or more of postscript, GIF, or JPEG files. Depending on the - versions of Emacs and the operating system that you are running, - Emacs itself may display '.gif' and '.jpg' files. Otherwise, a - graphics file viewer will be needed. Ghostscript/ghostview may be - downloaded to display '.ps' and '.eps' files. Viewers for GIF and - JPEG are usually included with operating systems. *Note - ESS(SAS)--Function keys for batch processing::, for more - information on using the F12 key for displaying graphics files with - SAS. - - Should you or a colleague inadvertently start a statistical process -in an ordinary '*shell*' buffer, the 'ess-remote' command can be used to -convert it to an ESS buffer and allow you to use the ESS commands with -it. - - -File: ess.info, Node: Customizing startup, Next: Controlling buffer display, Prev: ESS processes on Remote Computers, Up: Interactive ESS - -3.4 Changing the startup actions -================================ - -If you do not wish ESS to prompt for a starting directory when starting -a new process, set the variable 'ess-ask-for-ess-directory' to 'nil'. -In this case, the starting directory will be set using one of the -following methods: - - 1. If the variable 'ess-directory-function' stores the name of a - function, the value returned by this function is used. The default - for this variable is nil. - - 2. Otherwise, if the variable 'ess-directory' stores the name of a - directory (ending in a slash), this value is used. The default for - this variable is nil. - - 3. Otherwise, the working directory of the current buffer is used. - - If 'ess-ask-for-ess-directory' has a non-'nil' value (as it does by -default) then the value determined by the above rules provides the -default when prompting for the starting directory. Incidentally, -'ess-directory' is an ideal variable to set in 'ess-pre-run-hook'. - - You may also customize 'ess-post-run-hook' and the dialect-specific -'ess-*-post-run-hook' variables. For example, you may want to use -'ess-load-file' to load a file when ESS starts R: - - (add-hook 'ess-r-post-run-hook (lambda () (ess-load-file "foo.R"))) - - If you like to keep a record of your R actions, set the variable -'ess-ask-about-transfile' to 't', and you will be asked for a filename -for the transcript before the ESS process starts. - - -- User Option: ess-ask-about-transfile - If non-'nil', ask for a file name in which to save the session - transcript. - - Enter the name of a file in which to save the transcript at the -prompt. If the file doesn't exist it will be created (for R, you likely -want it to end in '.Rout'). If the file already exists the transcript -will be appended to the file. (Note: if you don't set this variable but -you still want to save the transcript, you can still do it later -- -*note Saving transcripts::.) - - Once these questions are answered (if they are asked at all) the -inferior process itself is started. If you need to pass any arguments -to this program, they may be specified in the variable -'inferior-S_PROGRAM_NAME-args'. For example, if 'inferior-ess-program' -is '"R"' then the variable to set is 'inferior-R-args'. It is not -normally necessary to pass arguments to the iESS program; in particular -do not pass the '-e' option to 'Splus', since ESS provides its own -command history mechanism. - - ESS can set the width option of inferior processes automatically when -the window configuration changes. To do so, set 'ess-auto-width' to a -non-nil value. By default, the change will not be shown in the inferior -buffer. If you want it to be shown, set 'ess-auto-width-visible' to a -non-nil value. - - -File: ess.info, Node: Controlling buffer display, Prev: Customizing startup, Up: Interactive ESS - -3.5 Controlling buffer display -============================== - -Users can control how buffers are displayed by customizing -'display-buffer-alist', *Note (emacs)Window Choice::. This section -provides examples of how to achieve certain setups. - - Users coming from RStudio may want the R process to appear at the -bottom left of the frame, help buffers to appear at the bottom right, -and ess-rdired buffers at the top right. To achieve that, you could -this. Note that the order matters; '*R Dired*' would match '*R' if it -came before in the alist. - - (setq display-buffer-alist - `(("*R Dired" - (display-buffer-reuse-window display-buffer-in-side-window) - (side . right) - (slot . -1) - (window-width . 0.33) - (reusable-frames . nil)) - ("*R" - (display-buffer-reuse-window display-buffer-at-bottom) - (window-width . 0.5) - (reusable-frames . nil)) - ("*Help" - (display-buffer-reuse-window display-buffer-in-side-window) - (side . right) - (slot . 1) - (window-width . 0.33) - (reusable-frames . nil)))) - - Some users prefer working with multiple frames where one frame has -the source code and the other frame has the inferior process. To -achieve this, use this example. *Note (elisp)Buffer Display Action -Alists:: for a detailed description of 'reusable-frames'. - - (setq display-buffer-alist - '(("*R" - (display-buffer-reuse-window display-buffer-pop-up-frame) - (reusable-frames . 0)))) - - Some users may want the process window to be dedicated to the process -so that other buffers are not shown on top of that window. *Note -(elisp)Dedicated Windows::. For example, this prevents help buffers -from being displayed in the window showing the inferior R process. - - (setq display-buffer-alist - '(("*R" - nil - (dedicated . t)))) - - By default, ESS usually prefers splitting the frame into multiple -windows so that you can work with both the R script and the R REPL -visible at once. If you want to override this behavior so that the -script buffer and the process buffer share the same window, you can do -so like this: - - (setq display-buffer-alist - '(("*R" . ((display-buffer-same-window) (inhibit-same-window . nil))) - ("\\.R$" . ((display-buffer-same-window) (inhibit-same-window . nil))))) - - -File: ess.info, Node: Entering commands, Next: Evaluating code, Prev: Interactive ESS, Up: Top - -4 Interacting with the ESS process -********************************** - -The primary function of the ESS package is to provide an easy-to-use -front end to the R interpreter. This is achieved by running the R -process from within an Emacs buffer, called hereafter _inferior_ buffer, -which has an active 'inferior-ess-mode'. The features of inferior R -mode are similar to those provided by the standard Emacs shell mode -(*note (emacs)Shell Mode::). Command-line completion of R objects and a -number of 'hot keys' for commonly-used R commands are also provided for -ease of typing. - -* Menu: - -* Command-line editing:: Entering commands and fixing mistakes -* Transcript:: Manipulating the transcript -* Command History:: Command History -* History expansion:: References to historical commands -* Hot keys:: Hot keys for common commands -* Statistical Process running in ESS?:: -* Emacsclient:: Using emacsclient -* Other:: Other commands provided by inferior-ESS - - -File: ess.info, Node: Command-line editing, Next: Transcript, Up: Entering commands - -4.1 Entering commands and fixing mistakes -========================================= - -Sending a command to the ESS process is as simple as typing it in and -pressing the key: - - -- Command: inferior-ess-send-input - 'RET' Send the command on the current line to the ESS process. - - If you make a typing error before pressing 'RET' all the usual Emacs -editing commands are available to correct it (*note Basic: -(emacs)Basic.). Once the command has been corrected you can press - (even if the cursor is not at the end of the line) to send the -corrected command to the ESS process. - - Emacs provides some other commands which are useful for fixing -mistakes: - -'C-c C-w' - 'backward-kill-word' Deletes the previous word (such as an object - name) on the command line. - -'C-c C-u' - 'comint-kill-input' Deletes everything from the prompt to point. - Use this to abandon a command you have not yet sent to the ESS - process. - -'C-a' - 'comint-bol' Move to the beginning of the line, and then skip - forwards past the prompt, if any. - - *Note (emacs)Shell Mode::, for other commands relevant to entering -input. - - -File: ess.info, Node: Transcript, Next: Command History, Prev: Command-line editing, Up: Entering commands - -4.2 Manipulating the transcript -=============================== - -Most of the time, the cursor spends its time at the bottom of the ESS -process buffer, entering commands. However all the input and output -from the current (and previous) ESS sessions is stored in the process -buffer (we call this the transcript) and often we want to move back up -through the buffer, to look at the output from previous commands for -example. - - Within the process buffer, a paragraph is defined as the prompt, the -command after the prompt, and the output from the command. Thus 'M-{' -and 'M-}' move you backwards and forwards, respectively, through -commands in the transcript. A particularly useful command is 'M-h' -('mark-paragraph') which will allow you to mark a command and its entire -output (for deletion, perhaps). For more information about paragraph -commands, *note Paragraphs: (emacs)Paragraphs. - - If an ESS process finishes and you restart it in the same process -buffer, the output from the new ESS process appears after the output -from the first ESS process separated by a form-feed ('^L') character. -Thus pages in the ESS process buffer correspond to ESS sessions. Thus, -for example, you may use 'C-x [' and 'C-x ]' to move backward and -forwards through ESS sessions in a single ESS process buffer. For more -information about page commands, *note Pages: (emacs)Pages. - -* Menu: - -* Last command:: Manipulating the output from the last command -* Process buffer motion:: Viewing older commands -* Transcript resubmit:: Re-submitting commands from the transcript -* Saving transcripts:: Keeping a record of your R session - - -File: ess.info, Node: Last command, Next: Process buffer motion, Up: Transcript - -4.2.1 Manipulating the output from the last command ---------------------------------------------------- - -Viewing the output of the command you have just entered is a common -occurrence and ESS provides a number of facilities for doing this. -Whenever a command produces output, it is possible that the window will -scroll, leaving the next prompt near the middle of the window. The -first part of the command output may have scrolled off the top of the -window, even though the entire output would fit in the window if the -prompt were near the bottom of the window. If this happens, you can use -the following comint commands: - - 'comint-show-maximum-output' to move to the end of the buffer, and -place cursor on bottom line of window to make more of the last output -visible. To make this happen automatically for all inputs, set the -variable 'comint-scroll-to-bottom-on-input' to 't' or ''this'. If the -first part of the output is still not visible, use 'C-c C-r' -('comint-show-output'), which moves cursor to the previous command line -and places it at the top of the window. - - Finally, if you want to discard the last command output altogether, -use 'C-c C-o' ('comint-delete-output'), which deletes everything from -the last command to the current prompt. Use this command judiciously to -keep your transcript to a more manageable size. - - -File: ess.info, Node: Process buffer motion, Next: Transcript resubmit, Prev: Last command, Up: Transcript - -4.2.2 Viewing older commands ----------------------------- - -If you want to view the output from more historic commands than the -previous command, commands are also provided to move backwards and -forwards through previously entered commands in the process buffer: - -'C-c C-p' - 'comint-previous-prompt' Moves point to the preceding prompt in the - process buffer. - -'C-c C-n' - 'comint-next-prompt' Moves point to the next prompt in the process - buffer. - -Note that these two commands are analogous to 'C-p' and 'C-n' but apply -to command lines rather than text lines. And just like 'C-p' and 'C-n', -passing a prefix argument to these commands means to move to the ARG'th -next (or previous) command. (These commands are also discussed in *note -Shell History Copying: (emacs)Shell History Copying.) - - There are also two similar commands (not bound to any keys by -default) which move to preceding or succeeding commands, but which first -prompt for a regular expression (*note Syntax of Regular Expression: -(emacs)Regexps.), and then moves to the next (previous) command matching -the pattern. - -'comint-backward-matching-input regexp arg' -'comint-forward-matching-input regexp arg' - Search backward (forward) through the transcript buffer for the - ARG'th previous (next) command matching REGEXP. ARG is the prefix - argument; REGEXP is prompted for in the minibuffer. - - -File: ess.info, Node: Transcript resubmit, Next: Saving transcripts, Prev: Process buffer motion, Up: Transcript - -4.2.3 Re-submitting commands from the transcript ------------------------------------------------- - -When moving through the transcript, you may wish to re-execute some of -the commands you find there. ESS provides commands to do this; these -commands may be used whenever the cursor is within a command line in the -transcript (if the cursor is within some command _output_, an error is -signaled). Note all commands involve the key. - -'RET' - 'inferior-ess-send-input' *Note Command-line editing::. - -'C-c RET' - 'comint-copy-old-input' Copy the command under the cursor to the - current command line, but don't execute it. Leaves the cursor on - the command line so that the copied command may be edited. - - When the cursor is not after the current prompt, the key has -a slightly different behavior than usual. Pressing 'RET' on any line -containing a command that you entered (i.e. a line beginning with a -prompt) sends that command to the ESS process once again. If you wish -to edit the command before executing it, use 'C-c RET' instead; it -copies the command to the current prompt but does not execute it, -allowing you to edit it before (re)submitting it. - - These commands work even if the current line is a continuation line -(i.e. the prompt is '+' instead of '>') -- in this case all the lines -that form the multi-line command are concatenated together and the -resulting command is sent to the ESS process (currently this is the only -way to resubmit a multi-line command to the ESS process in one go). If -the current line does not begin with a prompt, an error is signalled. -This feature, coupled with the command-based motion commands described -above, could be used as a primitive history mechanism. ESS provides a -more sophisticated mechanism, however, which is described in *note -Command History::. - - -File: ess.info, Node: Saving transcripts, Prev: Transcript resubmit, Up: Transcript - -4.2.4 Keeping a record of your R session ----------------------------------------- - -To keep a record of your R session in a disk file, use the Emacs command -'C-x C-w' ('write-file') to attach a file to the ESS process buffer. -The name of the process buffer will (probably) change to the name of the -file, but this is not a problem. You can still use R as usual; just -remember to save the file before you quit Emacs with 'C-x C-s'. You can -make ESS prompt you for a filename in which to save the transcript every -time you start R by setting the variable 'ess-ask-about-transfile' to -'t'; *Note Customizing startup::. For R files, naming transcript files -'*.Rout' puts them in a special mode (ESS transcript mode -- *note -Transcript Mode::) for editing transcript files which is automatically -selected for files with this suffix. - - R transcripts can get very large, so some judicious editing is -appropriate if you are saving it in a file. Use 'C-c C-o' whenever a -command produces excessively long output (printing large arrays, for -example). Delete erroneous commands (and the resulting error messages -or other output) by moving to the command (or its output) and typing -'M-h C-w'. Also, remember that 'C-c C-x' (and other hot keys) may be -used for commands whose output you do not wish to appear in the -transcript. These suggestions are appropriate even if you are not -saving your transcript to disk, since the larger the transcript, the -more memory your Emacs process will use on the host machine. - - You can use 'ess-transcript-clean-region' to strip output from a -transcript, leaving only source code suitable for inclusion in files -'source()'-able from R. *note Transcript Mode: Clean. - - -File: ess.info, Node: Command History, Next: History expansion, Prev: Transcript, Up: Entering commands - -4.3 Command History -=================== - -ESS provides easy-to-use facilities for re-executing or editing previous -commands. An input history of the last few commands is maintained (by -default the last 500 commands are stored, although this can be changed -by setting the variable 'comint-input-ring-size' in -'inferior-ess-mode-hook'.) The simplest history commands simply select -the next and previous commands in the input history: - -'M-p' - 'comint-previous-input' Select the previous command in the input - history. - -'M-n' - 'comint-next-input' Select the next command in the input history. - -For example, pressing 'M-p' once will re-enter the last command into the -process buffer after the prompt but does not send it to the ESS process, -thus allowing editing or correction of the command before the ESS -process sees it. Once corrections have been made, press 'RET' to send -the edited command to the ESS process. - - If you want to select a particular command from the history by -matching it against a regular expression (*note Syntax of Regular -Expression: (emacs)Regexps.), to search for a particular variable name -for example, these commands are also available: - -'M-r' - 'comint-history-isearch-backward-regexp' Prompt for a regular - expression, and search backwards through the input history for a - command matching the expression. - -A common type of search is to find the last command that began with a -particular sequence of characters; the following two commands provide an -easy way to do this: - -'C-c M-r' - 'comint-previous-matching-input-from-input' Select the previous - command in the history which matches the string typed so far. - -'C-c M-s' - 'comint-next-matching-input-from-input' Select the next command in - the history which matches the string typed so far. - -Instead of prompting for a regular expression to match against, as they -instead select commands starting with those characters already entered. -For instance, if you wanted to re-execute the last 'attach()' command, -you may only need to type 'att' and then 'C-c M-r' and 'RET'. - - *Note Shell History Ring: (emacs)Shell Ring, for a more detailed -discussion of the history mechanism, and do experiment with the 'In/Out' -menu to explore the possibilities. - - Many ESS users like to have even easier access to these, and -recommend to add something like - (eval-after-load "comint" - '(progn - (define-key comint-mode-map [up] - 'comint-previous-matching-input-from-input) - (define-key comint-mode-map [down] - 'comint-next-matching-input-from-input) - - ;; also recommended for ESS use -- - (setq comint-move-point-for-output 'others) - ;; somewhat extreme, almost disabling writing in *R*, *shell* buffers above prompt: - (setq comint-scroll-to-bottom-on-input 'this) - )) - to your Emacs configuration file, where the last two settings are -typically desirable for the situation where you work with a script (for -example, 'code.R') and send code chunks to the process buffer (e.g. -'*R*'). Note however that these settings influence all 'comint'-using -Emacs modes, not just the ESS ones, and for that reason, these -customization cannot be part of 'ESS' itself. - -* Menu: - -* Saving History:: - - -File: ess.info, Node: Saving History, Up: Command History - -4.3.1 Saving the command history --------------------------------- - -The 'ess-history-file' variable, which is 't' by default, together with -'ess-history-directory', governs if and where the command history is -saved and restored between sessions. By default, -'ess-history-directory' is 'nil', and the command history will be stored -(as a file) in the same directory as the iESS process. - - ESS users may work exclusively with script files rather than in a -iESS session, and may not want to save any history files. To do so: - - (setq ess-history-file nil) - -or if you prefer only one global command history file: - - (setq ess-history-directory "~/.R/") - -in your Emacs configuration file. - - -File: ess.info, Node: History expansion, Next: Hot keys, Prev: Command History, Up: Entering commands - -4.4 References to historical commands -===================================== - -Instead of searching through the command history using the command -described in the previous section, you can alternatively refer to a -historical command directly using a notation very similar to that used -in 'csh'. History references are introduced by a '!' or '^' character -and have meanings as follows: - -'!!' - The immediately previous command - -'!-N' - The Nth previous command - -'!text' - The last command beginning with the string 'text' - -'!?text' - The last command containing the string 'text' - - In addition, you may follow the reference with a "word designator" to -select particular "words" of the input. A word is defined as a sequence -of characters separated by whitespace. (You can modify this definition -by setting the value of 'comint-delimiter-argument-list' to a list of -characters that are allowed to separate words and themselves form -words.) Words are numbered beginning with zero. The word designator -usually begins with a ':' (colon) character; however it may be omitted -if the word reference begins with a '^', '$', '*' or '-'. If the word -is to be selected from the previous command, the second '!' character -can be omitted from the event specification. For instance, '!!:1' and -'!:1' both refer to the first word of the previous command, while '!!$' -and '!$' both refer to the last word in the previous command. The -format of word designators is as follows: - -'0' - The zeroth word (i.e. the first one on the command line) - -'N' - The Nth word, where N is a number - -'^' - The first word (i.e. the second one on the command line) - -'$' - The last word - -'X-Y' - A range of words; '-Y' abbreviates '0-Y' - -'*' - All the words except the zeroth word, or nothing if the command had - just one word (the zeroth) - -'X*' - Abbreviates X-$ - -'X-' - Like 'X*', but omitting the last word - - In addition, you may surround the entire reference except for the -first '!' by braces to allow it to be followed by other (non-whitespace) -characters (which will be appended to the expanded reference). - - Finally, ESS also provides quick substitution; a reference like -'^old^new^' means "the last command, but with the first occurrence of -the string 'old' replaced with the string 'new'" (the last '^' is -optional). Similarly, '^old^' means "the last command, with the first -occurrence of the string 'old' deleted" (again, the last '^' is -optional). - - To convert a history reference as described above to an input -suitable for R, you need to "expand" the history reference, using the - key. For this to work, the cursor must be preceded by a space -(otherwise it would try to complete an object name) and not be within a -string (otherwise it would try to complete a filename). So to expand -the history reference, type 'SPC TAB'. This will convert the history -reference into an R command from the history, which you can then edit or -press to execute. - - For example, to execute the last command that referenced the variable -'data', type '!?data SPC TAB RET'. - - -File: ess.info, Node: Hot keys, Next: Statistical Process running in ESS?, Prev: History expansion, Up: Entering commands - -4.5 Hot keys for common commands -================================ - -ESS provides a number of commands for executing the commonly used -functions. These commands below are basically information-gaining -commands (such as 'objects()' or 'search()') which tend to clutter up -your transcript and for this reason some of the hot keys display their -output in a temporary buffer instead of the process buffer by default. -This behavior is controlled by the following option: - - -- User Option: ess-execute-in-process-buffer - If non-'nil', means that these commands will produce their output - in the process buffer instead. - - In any case, passing a prefix argument to the commands (with 'C-u') -will reverse the meaning of 'ess-execute-in-process-buffer' for that -command. In other words, the output will be displayed in the process -buffer if it usually goes to a temporary buffer, and vice-versa. These -are the hot keys that behave in this way: - - -- Command: ess-execute-objects POSN - 'C-c C-x' Sends the 'objects()' command to the ESS process. A - prefix argument specifies the position on the search list (use a - negative argument to toggle 'ess-execute-in-process-buffer' as - well). This is a quick way to see what objects are in your working - directory. A prefix argument of 2 or more means get objects for - that position. A negative prefix argument POSN gets the objects - for that position, as well as toggling - 'ess-execute-in-process-buffer'. - - -- Command: ess-execute-search INVERT - 'C-c C-s' Sends the 'inferior-ess-search-list-command' command to - the 'ess-language' process; 'search()' in R. Prefix INVERT toggles - 'ess-execute-in-process-buffer'. - - 'ess-execute' may seem pointless when you could just type the command -in anyway, but it proves useful for 'spot' calculations which would -otherwise clutter your transcript, or for evaluating an expression while -partway through entering a command. You can also use this command to -generate new hot keys using the Emacs keyboard macro facilities; *note -Keyboard Macros: (emacs)Keyboard Macros. - - The following hot keys do not use 'ess-execute-in-process-buffer' to -decide where to display the output -- they either always display in the -process buffer or in a separate buffer, as indicated: - - -- Command: ess-load-file FILENAME - 'C-c M-l' Prompts for a file (FILENAME) to load into the ESS - process using 'source()'. If there is an error during loading, you - can jump to the error in the file with the following function. - - -- Command: ess-parse-errors ARG RESET - Visits next 'next-error' message and corresponding source code. If - all the error messages parsed so far have been processed already, - the message buffer is checked for new ones. A prefix ARG specifies - how many error messages to move; negative means move back to - previous error messages. Just 'C-u' as a prefix means reparse the - error message buffer and start at the first error. The RESET - argument specifies restarting from the beginning. - - *Note Error Checking::, for more details. - - -- Command: ess-display-help-on-object OBJECT COMMAND - 'C-c C-v' Pops up a help buffer for an R object or function. If - COMMAND is supplied, it is used instead of - 'inferior-ess-help-command'. See *note Help:: for more details. - - -- Command: ess-quit - 'C-c C-q' Issue an exiting command to the inferior process, - additionally also running 'ess-cleanup' for disposing of any - temporary buffers (such as help buffers and edit buffers) that may - have been created. Use this command when you have finished your R - session instead of simply quitting at the inferior process prompt, - otherwise you will need to issue the command 'ess-cleanup' - explicitly to make sure that all the files that need to be saved - have been saved, and that all the temporary buffers have been - killed. - - -File: ess.info, Node: Statistical Process running in ESS?, Next: Emacsclient, Prev: Hot keys, Up: Entering commands - -4.6 Is the Statistical Process running under ESS? -================================================= - -For the R languages (R, S, S-Plus) ESS sets an option in the current -process that programs in the language can check to determine the -environment in which they are currently running. - - ESS sets 'options(STERM="iESS")' for R language processes running in -an inferior 'iESS[S]' or 'iESS[R]' buffer. - - ESS sets 'options(STERM="ddeESS")' for independent S-Plus for Windows -processes running in the GUI and communicating with ESS via the DDE -(Microsoft Dynamic Data Exchange) protocol through a 'ddeESS[S]' buffer. - - Other values of 'options()$STERM' that we recommend are: - - * 'length': Fixed length xterm or telnet window. - * 'scrollable': Unlimited length xterm or telnet window. - * 'server': S-Plus Stat Server. - * 'BATCH': BATCH. - * 'Rgui': R GUI. - * 'Commands': S-Plus GUI without DDE interface to ESS. - - Additional values may be recommended in the future as new interaction -protocols are created. Unlike the values 'iESS' and 'ddeESS', ESS can't -set these other values since the R language program is not under the -control of ESS. - - -File: ess.info, Node: Emacsclient, Next: Other, Prev: Statistical Process running in ESS?, Up: Entering commands - -4.7 Using emacsclient -===================== - -When starting R or S under Unix, ESS sets -'options(editor="emacsclient")'. Under Microsoft Windows, it will use -gnuclient.exe rather than emacsclient, but the same principal applies. -Within your R session, if you have a function called 'iterator', typing -'fix(iterator)', will show that function in a temporary Emacs buffer. -You can then correct the function. When you kill the buffer, the -definition of the function is updated. Using 'edit()' rather than -'fix()' means that the function is not updated. Finally, the R function -'page(x)' will also show a text representation of the object 'x' in a -temporary Emacs buffer. - - -File: ess.info, Node: Other, Prev: Emacsclient, Up: Entering commands - -4.8 Other commands provided by inferior-ESS -=========================================== - -The following commands are also available in the process buffer: - - -- Command: comint-interrupt-subjob - 'C-c C-c' Sends a Control-C signal to the iESS process. This has - the effect of aborting the current command. - - -- Command: ess-switch-to-inferior-or-script-buffer TOGGLE-EOB - 'C-c C-z' When in process buffer, return to the most recent script - buffer. When in a script buffer pop to the associated process - buffer. Consecutive presses of 'C-z' switch between the script and - process buffers. - - If TOGGLE-EOB is given, the value of - 'ess-switch-to-end-of-proc-buffer' is toggled. - - -- User Option: ess-switch-to-end-of-proc-buffer - If non-'nil', 'ess-switch-to-inferior-or-script-buffer' goes to end - of process buffer. - - Other commands available in iESS modes are discussed in *note -(emacs)Shell Mode::. - - -File: ess.info, Node: Evaluating code, Next: Transcript Mode, Prev: Entering commands, Up: Top - -5 Sending code to the ESS process -********************************* - -Other commands are also available for evaluating portions of code in the -R process. These commands cause the selected code to be evaluated -directly by the ESS process as if you had typed them in at the command -line; the 'source()' function is not used. You may choose whether both -the commands and their output appear in the process buffer (as if you -had typed in the commands yourself) or if the output alone is echoed. -The behavior is controlled by the variable: - - -- User Option: ess-eval-visibly - Non-'nil' means 'ess-eval-*' commands display commands and output - in the process buffer. Default is 't'. - - Passing a prefix ('C-u') (in elisp terms, the argument VIS) to any of -the following commands, however, reverses the meaning of -'ess-eval-visibly' for that command only -- for example 'C-u C-c C-j' -evaluates the current line without showing the input in the iESS buffer. -The default value of 'ess-eval-visibly' ('t') means that ESS calls block -Emacs until they finish. This may be undesirable, especially if -commands take long to finish. Users who want input to be displayed and -Emacs not to be blocked can set 'ess-eval-visibly' to ''nowait'. This -sends the input to the iESS buffer but does not wait for the process to -finish, ensuring Emacs is not blocked. - - Primary commands for evaluating code are: - - -- Command: ess-eval-region-or-line-and-step VIS - 'C-' Sends the highlighted region or current line and step to - next line of code. - - -- Command: ess-eval-region-or-function-or-paragraph VIS - 'C-M-x' Sends the current selected region or function or paragraph. - - -- Command: ess-eval-region-or-function-or-paragraph-and-step VIS - 'C-c C-c' Like 'ess-eval-region-or-function-or-paragraph' but steps - to next line of code. - - Other, not so often used, evaluation commands are: - - -- Command: ess-eval-line VIS - 'C-c C-j' Sends the current line to the ESS process. - - -- Command: ess-eval-line-and-go VIS - 'C-c M-j' Like 'ess-eval-line' but additionally switches point to - the ESS process. - - -- Command: ess-eval-function VIS NO-ERROR - 'C-c C-f' Sends the function containing point to the ESS process. - - -- Command: ess-eval-function-and-go VIS - 'C-c M-f' Like 'ess-eval-function' but additionally switches point - to the ESS process. - - -- Command: ess-eval-region START END TOGGLE MESSAGE - 'C-c C-r' Sends the current region to the ESS process. - - -- Command: ess-eval-region-and-go START END VIS - 'C-c M-r' Like 'ess-eval-region' but additionally switches point to - the ESS process. - - -- Command: ess-eval-buffer VIS - 'C-c C-b' Sends the current buffer to the ESS process. - - -- Command: ess-eval-buffer-and-go VIS - 'C-c M-b' Like 'ess-eval-buffer' but additionally switches point to - the ESS process. - - All the above 'ess-eval-*' commands are useful for evaluating small -amounts of code and observing the results in the process buffer for -debugging purposes, or for generating transcripts from source files. -When editing R functions, it is generally preferable to use 'C-c C-l' to -update the function's value. In particular, 'ess-eval-buffer' is now -largely obsolete. - - A useful way to work is to divide the frame into two windows; one -containing the source code and the other containing the process buffer. -If you wish to make the process buffer scroll automatically when the -output reaches the bottom of the window, you will need to set the -variable 'comint-move-point-for-output' to ''others' or 't'. - - -File: ess.info, Node: Transcript Mode, Next: Editing objects, Prev: Evaluating code, Up: Top - -6 Manipulating saved transcript files -************************************* - -Inferior R mode records the transcript (the list of all commands -executed, and their output) in the process buffer, which can be saved as -a "transcript file", which should normally have the suffix '.Rout'. The -most obvious use for a transcript file is as a static record of the -actions you have performed in a particular R session. Sometimes, -however, you may wish to re-execute commands recorded in the transcript -file by submitting them to a running ESS process. This is what -Transcript Mode is for. - - If you load file a with the suffix '.Rout' into Emacs, it is placed -in R Transcript Mode. Transcript Mode is similar to inferior R mode -(*note Entering commands::): paragraphs are defined as a command and its -output, and you can move though commands either with the paragraph -commands or with 'C-c C-p' and 'C-c C-n'. - -* Menu: - -* Resubmit:: Resubmitting commands from the transcript file -* Clean:: Cleaning transcript files - - -File: ess.info, Node: Resubmit, Next: Clean, Up: Transcript Mode - -6.1 Resubmitting commands from the transcript file -================================================== - -Three commands are provided to re-submit command lines from the -transcript file to a running ESS process. They are: - - -- Command: ess-transcript-send-command - 'M-RET' Sends the current command line to the ESS process, and - execute it. - - -- Command: ess-transcript-copy-command - 'C-c RET' Copy the current command to the ESS process, and switch - to it (ready to edit the copied command). - - -- Command: ess-transcript-send-command-and-move - 'RET' Sends the current command to the ESS process, and move to the - next command line. This command is useful for submitting a series - of commands. - -Note that the first two commands are similar to those on the same keys -in inferior R Mode. In all three cases, the commands should be executed -when the cursor is on a command line in the transcript; the prompt is -automatically removed before the command is submitted. - - -File: ess.info, Node: Clean, Prev: Resubmit, Up: Transcript Mode - -6.2 Cleaning transcript files -============================= - -Yet another use for transcript files is to extract the command lines for -inclusion in an R source file or function. Transcript mode provides one -command which does just this: - - -- Command: ess-transcript-clean-region BEG END EVEN-IF-READ-ONLY - 'C-c C-w' Strip the transcript in the region (given by BEG and - END), leaving only commands. Deletes any lines not beginning with - a prompt, and then removes the prompt from those lines that remain. - Prefix argument EVEN-IF-READ-ONLY means to clean even if the buffer - is read-only. Don't forget to remove any erroneous commands first! - -The remaining command lines may then be copied to a source file or edit -buffer for inclusion in a function definition, or may be evaluated -directly (*note Evaluating code::) using the code evaluation commands -from R mode, also available in R Transcript Mode. - - -File: ess.info, Node: Editing objects, Next: Help, Prev: Transcript Mode, Up: Top - -7 Editing objects and functions -******************************* - -ESS provides facilities for editing R objects within your Emacs session. -Most editing is performed on R functions, although in theory you may -edit datasets as well. Edit buffers are always associated with files, -although you may choose to make these files temporary if you wish. -Alternatively, you may make use of a simple yet powerful mechanism for -maintaining backups of text representations of R functions. -Error-checking is performed when R code is loaded into the ESS process. - -* Menu: - -* Edit buffer:: Edit objects in a specialized buffer -* Loading:: Loading source files into the ESS process -* Error Checking:: Detecting errors in source files -* Indenting:: Indenting and formatting S code -* Other edit buffer commands:: Commands for motion, completion and more -* Source Files:: Maintaining R source files -* Source Directories:: Names and locations of dump files - - -File: ess.info, Node: Edit buffer, Next: Loading, Up: Editing objects - -7.1 Creating or modifying R objects -=================================== - -To edit an object, type - - -- Command: ess-dump-object-into-edit-buffer OBJECT - 'C-c C-e C-d' Edit an object in its own edit buffer. - - from within the iESS process buffer ('*R*'). You will then be -prompted for an object to edit: you may either type in the name of an -existing object (for which completion is available using the 'TAB' key), -or you may enter the name of a new object. A buffer will be created -containing the text representation of the requested object or, if you -entered the name of a non-existent object at the prompt and the variable -'ess-function-template' is non-'nil', you will be presented with a -template defined by that variable, which defaults to a skeleton function -construct. - - You may then edit the function as required. The edit buffer -generated by 'ess-dump-object-into-edit-buffer' is placed in the 'ESS' -major mode which provides a number of commands to facilitate editing R -source code. Commands are provided to intelligently indent R code, -evaluate portions of R code and to move around R code constructs. - - Note: when you dump a file with 'C-c C-e C-d', ESS first checks to -see whether there already exists an edit buffer containing that object -and, if so, pops you directly to that buffer. If not, ESS next checks -whether there is a file in the appropriate place with the appropriate -name (*note Source Files::) and if so, reads in that file. You can use -this facility to return to an object you were editing in a previous -session (and which possibly was never loaded to the R session). -Finally, if both these tests fail, the ESS process is consulted and a -'dump()' command issued. If you want to force ESS to ask the ESS -process for the object's definition (say, to reformat an unmodified -buffer or to revert back to R's idea of the object's definition) pass a -prefix argument to 'ess-dump-object-into-edit-buffer' by typing 'C-u C-c -C-e C-d'. - - -File: ess.info, Node: Loading, Next: Error Checking, Prev: Edit buffer, Up: Editing objects - -7.2 Loading source files into the ESS process -============================================= - -The best way to get information -- particularly function definitions -- -into R is to load them in as source file, using R's 'source' function. -You have already seen how to create source files using 'C-c C-e C-d'; -ESS provides a complementary command for loading source files (even -files not created with ESS!) into the ESS process, namely -'ess-load-file' ('C-c M-l'). *note Hot keys::. - -After typing 'C-c M-l' you will prompt for the name of the file to load -into R; usually this is the current buffer's file which is the default -value (selected by simply pressing 'RET' at the prompt). You will be -asked to save the buffer first if it has been modified (this happens -automatically if the buffer was generated with 'C-c C-e C-d'). The file -will then be loaded, and if it loads successfully you will be returned -to the ESS process. - - -File: ess.info, Node: Error Checking, Next: Indenting, Prev: Loading, Up: Editing objects - -7.3 Detecting errors in source files -==================================== - -If any errors occur when loading a file with 'C-c C-l', ESS will inform -you of this fact. In this case, you can jump directly to the line in -the source file which caused the error by typing 'C-c `' -('ess-parse-errors'). You will be returned to the offending file -(loading it into a buffer if necessary) with point at the line S -reported as containing the error. You may then correct the error, and -reload the file. Note that none of the commands in an R source file -will take effect if any part of the file contains errors. - - Sometimes the error is not caused by a syntax error (loading a -non-existent file for example). In this case typing 'C-c `' will simply -display a buffer containing S's error message. You can force this -behavior (and avoid jumping to the file when there _is_ a syntax error) -by passing a prefix argument to 'ess-parse-errors' with 'C-u C-c `'. - - -File: ess.info, Node: Indenting, Next: Other edit buffer commands, Prev: Error Checking, Up: Editing objects - -7.4 Indenting and formatting R code -=================================== - -ESS provides a sophisticated mechanism for indenting R source code. -Compound statements (delimited by '{' and '}') are indented relative to -their enclosing block. In addition, the braces have been electrified to -automatically indent to the correct position when inserted, and -optionally insert a newline at the appropriate place as well. Lines -which continue an incomplete expression are indented relative to the -first line of the expression. Function definitions, 'if' statements, -calls to 'expression()' and loop constructs are all recognized and -indented appropriately. User variables are provided to control the -amount of indentation in each case, and there are also a number of -predefined indentation styles to choose from. - - Comments are also handled specially by ESS, using an idea borrowed -from the Emacs-Lisp indentation style. By default, comments beginning -with '###' are aligned to the beginning of the line. Comments beginning -with '##' are aligned to the current level of indentation for the block -containing the comment. Finally, comments beginning with '#' are -aligned to a column on the right (the 40th column by default, but this -value is controlled by the variable 'comment-column',) or just after the -expression on the line containing the comment if it extends beyond the -indentation column. You turn off the default behavior by adding the -line '(setq ess-indent-with-fancy-comments nil)' to your '.emacs' file. - - ESS also supports Roxygen entries which is R documentation maintained -in the source code as comments *Note Roxygen::. - - The indentation commands provided by ESS are: - - -- Command: ess-indent-or-complete - 'TAB' Indents the current line as R code. - - Try to indent first, and if code is already properly indented, - complete instead. In ess-mode, only tries completion if - 'tab-always-indent' is ''complete'. See also - 'ess-first-tab-never-complete'. - - -- User Option: ess-first-tab-never-complete - If non-'nil', 'TAB' never tries to complete in ess-mode. The - default ''symbol' does not try to complete if the next char is a - valid symbol constituent. There are more options, see the help - ('C-h v'). - - -- Command: ess-indent-exp - 'TAB' Indents each line in the R (compound) expression which - follows point. Very useful for beautifying your R code. - - -- Command: ess-electric-brace - '{' '}' The braces automatically indent to the correct position - when typed. - - The following Emacs command are also helpful: - -'RET' -'LFD' - 'newline-and-indent' Insert a newline, and indent the next line. - (Note that most keyboards nowadays do not have a key, - but and 'C-j' are equivalent.) - -'M-;' - 'indent-dwim' Call the comment command you want (Do What I Mean). - -* Menu: - -* Styles:: Changing styles for indentation and alignment - - -File: ess.info, Node: Styles, Up: Indenting - -7.4.1 Changing styles for code indentation and alignment --------------------------------------------------------- - -The combined value of twelve variables (4 of three groups -'ess-indent-*', 'ess-offset-*' and 'ess-align-*') that control -indentation are collectively termed a style. ESS provides several -styles covering the common styles of indentation: 'DEFAULT', 'OWN', -'GNU', 'BSD', 'K&R', 'C++', 'RRR', 'RRR+', 'Rstudio', 'Rstudio-', and -'CLB'. The variable 'ess-style-alist' lists the value of each -indentation variable per style (and its documentation contains more). - - -- Command: ess-set-style - 'C-c C-e C-s' (or 'C-c C-e s') sets the formatting style in this - buffer to be one of the predefined styles, see above. The - 'DEFAULT' style uses the default values for the indenting - variables; The 'OWN' style allows you to use your own private - values of the indentation variable, see below. - - -- User Option: ess-style - The style to use. See the variable 'ess-style-alist' for how these - groups (DEFAULT, OWN, GNU, RRR, ...) map onto different settings - for variables. You can set this in your Emacs configuration file: - - (setq ess-style 'C++) - - -- User Option: ess-style-alist - Predefined formatting styles for ESS code. Values for all groups, - except OWN, are fixed. To change the value of variables in the OWN - group, customize the variable 'ess-own-style-list'. The default - style in use is controlled by 'ess-style'. - - The styles 'DEFAULT' and 'OWN' are initially identical. If you wish -to edit some of the default values, set 'ess-style' to ''OWN' and change -'ess-own-style-list'. *Note Customization::, for convenient ways to set -both these variables. - - If you prefer not to use the customization facility, you can change -individual indentation variables within a hook, for example: - - (defun myindent-ess-hook () - (setq ess-indent-level 4)) - (add-hook 'ess-mode-hook 'myindent-ess-hook) - - In the rare case that you'd like to add an entire new indentation -style of your own, copy the definition of 'ess-own-style-list' to a new -variable and ensure that the last line of the ':set' declaration calls -'ess-add-style' with a unique name for your style (e.g. ''MINE'). -Finally, add '(setq ess-style 'MINE)' to use your new style. - - -File: ess.info, Node: Other edit buffer commands, Next: Source Files, Prev: Indenting, Up: Editing objects - -7.5 Commands for motion, completion and more -============================================ - -A number of commands are provided to move across function definitions in -the edit buffer: - - -- Command: ess-goto-beginning-of-function-or-para - 'ESC C-a' aka 'C-M-a' If inside a function go to the beginning of - it, otherwise go to the beginning of paragraph. - - -- Command: ess-goto-end-of-function-or-para - 'ESC C-e' aka 'C-M-e' Move point to the end of the function - containing point. - - -- Command: ess-mark-function - 'ESC C-h' aka 'C-M-h' Place point at the beginning of the R - function containing point, and mark at the end. - -Don't forget the usual Emacs commands for moving over balanced -expressions and parentheses: *Note Lists and Sexps: (Emacs)Lists. - - Completion is provided in the edit buffer in a similar fashion to the -process buffer: first indents, and if there is nothing to indent, -completes the object or file name; 'M-?' lists file completions. See -*Note Completion::, for more. - - Finally, 'C-c C-z' ('ess-switch-to-inferior-or-script-buffer') -returns you to the 'iESS' process buffer, if done from a script buffer, -placing point at the end of the buffer. If this is done from the 'iESS' -process buffer, point is taken to the script buffer. - - In addition many commands available in the process buffer are also -available in the script buffer. You can still read help files with 'C-c -C-v', edit another function with 'C-c C-e C-d' and of course 'C-c C-l' -can be used to load a source file into R. - - -File: ess.info, Node: Source Files, Next: Source Directories, Prev: Other edit buffer commands, Up: Editing objects - -7.6 Maintaining R source files -============================== - -Every edit buffer in ESS is associated with a "dump file" on disk. Dump -files are created whenever you type 'C-c C-e C-d' -('ess-dump-object-into-edit-buffer'), and may either be deleted after -use, or kept as a backup file or as a means of keeping several versions -of an R function. - - -- User Option: ess-delete-dump-files - If non-'nil', dump files created with C-c C-e C-d are deleted - immediately after they are created by the ess-process. - - Since immediately after R dumps an object's definition to a disk file -the source code on disk corresponds exactly to R's idea of the object's -definition, the disk file isn't needed; deleting it now has the -advantage that if you _don't_ modify the file (say, because you just -wanted to look at the definition of one of the standard R functions) the -source dump file won't be left around when you kill the buffer. Note -that this variable only applies to files generated with R's 'dump' -function; it doesn't apply to source files which already exist. The -default value is 't'. - - -- User Option: ess-keep-dump-files - Variable controlling whether to delete dump files after a - successful load. If 'nil': always delete. If 'ask', confirm to - delete. If 'check', confirm to delete, except for files created - with 'ess-dump-object-into-edit-buffer'. Anything else, never - delete. This variable only affects the behaviour of - 'ess-load-file'. Dump files are never deleted if an error occurs - during the load. - - After an object has been successfully (without error) loaded back -into R with 'C-c C-l', the disk file again corresponds exactly (well, -almost -- see below) to R's record of the object's definition, and so -some people prefer to delete the disk file rather than unnecessarily use -up space. This option allows you to do just that. - - If the value of 'ess-keep-dump-files' is 't', dump files are never -deleted after they are loaded. Thus you can maintain a complete text -record of the functions you have edited within ESS. Backup files are -kept as usual, and so by using the Emacs numbered backup facility -- -*note Single or Numbered Backups: (emacs)Backup Names, you can keep a -historic record of function definitions. Another possibility is to -maintain the files with a version-control system such as git *Note -Version Control: (emacs)Version Control. As long as a dump file exists -in the appropriate place for a particular object, editing that object -with 'C-c C-e C-d' finds that file for editing (unless a prefix argument -is given) -- the ESS process is not consulted. Thus you can keep -comments _outside_ the function definition as a means of documentation -that does not clutter the R object itself. Another useful feature is -that you may format the code in any fashion you please without R -re-indenting the code every time you edit it. These features are -particularly useful for project-based work. - - If the value of 'ess-keep-dump-files' is nil, the dump file is always -silently deleted after a successful load with 'C-c C-l'. While this is -useful for files that were created with 'C-c C-e C-d' it also applies to -any other file you load (say, a source file of function definitions), -and so can be dangerous to use unless you are careful. Note that since -'ess-keep-dump-files' is buffer-local, you can make sure particular -files are not deleted by setting it to 't' in the Local Variables -section of the file *Note Local Variables in Files: (emacs)File -Variables. - - A safer option is to set 'ess-keep-dump-files' to 'ask'; this means -that ESS will always ask for confirmation before deleting the file. -Since this can get annoying if you always want to delete dump files -created with 'C-c C-e C-d', but not any other files, setting -'ess-keep-dump-files' to 'check' (the default value) will silently -delete dump files created with 'C-c C-e C-d' in the current Emacs -session, but query for any other file. Note that in any case you will -only be asked for confirmation once per file, and your answer is -remembered for the rest of the Emacs session. - - Note that in all cases, if an error (such as a syntax error) is -detected while loading the file with 'C-c C-l', the dump file is _never_ -deleted. This is so that you can edit the file in a new Emacs session -if you happen to quit Emacs before correcting the error. - - Dump buffers are always autosaved, regardless of the value of -'ess-keep-dump-files'. - - -File: ess.info, Node: Source Directories, Prev: Source Files, Up: Editing objects - -7.7 Names and locations of dump files -===================================== - -Every dump file should be given a unique file name, usually the dumped -object name with some additions. - - -- User Option: ess-dump-filename-template - Template for filenames of dumped objects. '%s' is replaced by the - object name. - -By default, dump file names are the user name, followed by '.' and the -object and ending with '.R'. Thus if user 'joe' dumps the object -'myfun' the dump file will have name 'joe.myfun.R'. The username part -is included to avoid clashes when dumping into a publicly-writable -directory, such as '/tmp'; you may wish to remove this part if you are -dumping into a directory owned by you. - - You may also specify the directory in which dump files are written: - - -- User Option: ess-source-directory - Directory name (ending in a slash) where R dump files are to be - written. - - By default, dump files are always written to '/tmp', which is fine -when 'ess-keep-dump-files' is 'nil'. If you are keeping dump files, -then you will probably want to keep them somewhere in your home -directory, say '~/R-source'. This could be achieved by including the -following line in your Emacs configuration file: - (setq ess-source-directory (expand-file-name "~/R-source/")) - - If you would prefer to keep your dump files in separate directories -depending on the value of some variable, ESS provides a facility for -this also. By setting 'ess-source-directory' to a lambda expression -which evaluates to a directory name, you have a great deal of -flexibility in selecting the directory for a particular source file to -appear in. The lambda expression is evaluated with the process buffer -as the current buffer and so you can use the variables local to that -buffer to make your choice. For example, the following expression -causes source files to be saved in the subdirectory 'Src' of the -directory the ESS process was run in. - - (setq ess-source-directory - (lambda () - (concat ess-directory "Src/"))) - -('ess-directory' is a buffer-local variable in process buffers which -records the directory the ESS process was run from.) This is useful if -you keep your dump files and you often edit objects with the same name -in different ESS processes. Alternatively, if you often change your R -working directory during an R session, you may like to keep dump files -in some subdirectory of the directory pointed to by the first element of -the current search list. This way you can edit objects of the same name -in different directories during the one R session: - (setq ess-source-directory - (lambda () - (file-name-as-directory - (expand-file-name (concat - (car ess-search-list) - "/.Src"))))) - - If the directory generated by the lambda function does not exist but -can be created, you will be asked whether you wish to create the -directory. If you choose not to, or the directory cannot be created, -you will not be able to edit functions. - - -File: ess.info, Node: Help, Next: Completion, Prev: Editing objects, Up: Top - -8 Reading help files -******************** - -ESS provides an easy-to-use facility for reading R help files from -within Emacs. From within the ESS process buffer or any ESS edit -buffer, typing 'C-c C-v' ('ess-display-help-on-object') will prompt you -for the name of an object for which you would like documentation. -Completion is provided over all objects which have help files. - - If the requested object has documentation, you will be popped into a -buffer (named '*help(OBJ-NAME)*') containing the help file. This buffer -is placed in a special ESS help mode which disables the usual editing -commands but which provides a number of keys for paging through the help -file. - - Help commands: - -'?' - 'ess-describe-help-mode' Pops up a help buffer with a list of the - commands available in R help mode. - -'h' - 'ess-display-help-on-object' Pop up a help buffer for a different - object. - - Paging commands: - -'DEL' - 'scroll-down-command' Move one screen backwards through the help - file. - -'SPC' - 'scroll-up-command' Move one screen forwards through the help file. - -'>' -'<' - 'end/beginning-of-buffer' Move to the end or beginning of the help - file, respectively. - - Section-based motion commands: - -'n' -'p' - 'ess-skip-to-previous-section' and 'ess-skip-to-next-section' Move - to the next and previous section header in the help file, - respectively. A section header consists of a number of capitalized - words, followed by a colon. - - In addition, the 's' key followed by one of the following letters -will jump to a particular section in the help file. Note that the exact -headings available and capitalization scheme may vary across languages. - - You may use 's ?' to get the current list of active key bindings. - -'a' - Arguments: - -'b' - Background: - -'B' - Bugs: - -'d' - Description: - -'D' - Details: - -'e' - Examples: - -'n' - Note: - -'O' - Optional Arguments: - -'R' - Required Arguments: - -'r' - References: - -'s' - See Also: - -'S' - Side Effects: - -'u' - Usage: - -'v' - Value: - -'?' - Pops up a help buffer with a list of the defined section motion - keys. - - Evaluation: - -'l' - 'ess-eval-line-and-step' Evaluates the current line in the ESS - process, and moves to the next line. Useful for running examples - in help files. - -'r' - 'ess-eval-region' Send the contents of the current region to the - ESS process. Useful for running examples in help files. - - Quit commands: - -'q' - 'ess-help-quit' Return to previously selected buffer, and bury the - help buffer. - -'k' - 'kill-buffer' Return to previously selected buffer, and kills the - help buffer. - -'x' - 'ess-kill-buffer-and-go' Return to the ESS process, killing this - help buffer. - - Miscellaneous: - -'i' - 'ess-display-index' Prompt for a package and display it's help - index. - -'v' - 'ess-display-vignettes' Display all available vignettes. - -'w' - 'ess-display-help-in-browser' Display current help page with the - web browser. - -'/' - 'isearch-forward' Same as 'C-s'. - - In addition, all of the ESS commands available in the edit buffers -are also available in R help mode (*note Edit buffer::). Of course, the -usual (non-editing) Emacs commands are available, and for convenience -the digits and <-> act as prefix arguments. - - If a help buffer already exists for an object for which help is -requested, that buffer is popped to immediately; the ESS process is not -consulted at all. If the contents of the help file have changed, you -either need to kill the help buffer first, or pass a prefix argument -(with 'C-u') to 'ess-display-help-on-object'. - - Help buffers are marked as temporary buffers in ESS, and are deleted -when 'ess-quit' or 'ess-cleanup' are called. - - Help buffers normally appear in another window within the current -frame. If you wish help buffers to appear in their own frame (either -one per help buffer, or one for all help buffers), you can customize the -variable 'ess-help-own-frame'. - - Help buffers are displayed by calling the function -'ess-display-help'. You can customize where these buffers are displayed -by adding an entry in 'display-buffer-alist' (see *Note (ess)Controlling -buffer display:: for examples) or by customizing the options -'ess-help-own-frame', 'ess-help-frame-alist', and -'ess-display-buffer-reuse-frame'. - - -File: ess.info, Node: Completion, Next: Developing with ESS, Prev: Help, Up: Top - -9 Completion -************ - -* Menu: - -* Object names:: -* Function arguments:: -* Minibuffer completion:: -* Company:: -* Icicles:: - - -File: ess.info, Node: Object names, Next: Function arguments, Up: Completion - -9.1 Completion of object names -============================== - -The key is for completion. The value of the variable -'ess-first-tab-never-complete' controls when completion is allowed to -occur. In 'ess-mode' first tries to indent, and if there is -nothing to indent, complete the object name instead. - -'TAB' - 'comint-dynamic-complete' Complete the R object name or filename - before point. - - When the cursor is just after a partially-completed object name, -pressing provides completion in a similar fashion to the rest of -Emacs. ESS maintains a list of all objects known to R at any given -time, which basically consists of all objects (functions and datasets) -in every attached directory listed by the 'search()' command along with -the component objects of attached data frames - - For example, consider three functions 'binomplot()', 'binom.test()' -and 'binomial()'. Typing 'bin TAB' will insert the characters 'om', -completing the longest prefix ('binom') which distinguishes these three -commands. Pressing 'TAB' once more provides a list of the three -commands which have this prefix, allowing you to add more characters -(say, '.') which specify the function you desire. After entering more -characters pressing 'TAB' yet again will complete the object name up to -uniqueness, etc. If you just wish to see what completions exist without -adding any extra characters, type 'M-?'. - - -- Command: ess-complete-object-name - 'M-?' List all possible completions of the object name at point. - - ESS also provides completion over the components of named lists and -environments (after '$'), S4 classes slots (after @), package and -namespace objects (after :: and :::). - - Completion is also provided over file names, which is particularly -useful when using R functions such as 'get()' or 'scan()' which require -fully expanded file names. - - In the iESS buffer, if the cursor is not in a string and does not -follow a (partial) object name, the key has a third use: it -expands history references. *Note History expansion::. - - Efficiency in completion is gained by maintaining a cache of objects -currently known to R; when a new object becomes available or is deleted, -only one component of the cache corresponding to the associated -directory needs to be refreshed. If ESS ever becomes confused about -what objects are available for completion (such as when if refuses to -complete an object you *know* is there), the command 'M-x ess-resynch' -forces the _entire_ cache to be refreshed, which should fix the problem. - - -File: ess.info, Node: Function arguments, Next: Minibuffer completion, Prev: Object names, Up: Completion - -9.2 Completion of function arguments -==================================== - -When inside a function call (i.e. following ''(''), 'TAB' completion -also provides function arguments. If function is a generic, completion -will provide all the arguments of 'S3' methods known to 'R'. - - In R versions newer than 2.14.1, ESS uses R's built-in completion -engine and will honor its settings. You may read about them by issuing -'?rc.options' at the prompt. For example, to have the equals sign for -function arguments contain spaces on both sides (e.g. 'lm(for)' -suggests 'formula = ' rather than 'formula='), you can adjust -'funarg.suffix': - - utils::rc.options(funarg.suffix = " = ") - - A related functionality is *Note ESS ElDoc::, which displays function -arguments in the echo area whenever the point is inside a function call. - - -File: ess.info, Node: Minibuffer completion, Next: Company, Prev: Function arguments, Up: Completion - -9.3 Minibuffer completion -========================= - -ESS uses 'IDO' mechanism (part of default Emacs) for minibuffer -completion if the 'ido' package is available and the value of -'ess-use-ido' it 't' (the default). The completion command -'ess-completing-read' falls back on classic 'completion-read' interface -if this feature is not available for whatever reason. - - -File: ess.info, Node: Company, Next: Icicles, Prev: Minibuffer completion, Up: Completion - -9.4 Company -=========== - -Another popular package for completion is company, short for complete -anything. ESS provides support for company out-of-the-box. To disable -company support, set 'ess-use-company' to 'nil'. You can set it to -''script-only' to only activate company in R scripts. - - -File: ess.info, Node: Icicles, Prev: Company, Up: Completion - -9.5 Icicles -=========== - -Another option for comprehensively handling completion in Emacs is via -Icicles (). It allows users to -have completions shown temporarily in the standard '*Completions*' -buffer, and interactively select completion candidates using several -methods. As of version 2013.04.04, Icicles provides support for -completion in ESS. Please consult Icicles documentation, which is easily -accessible via 'customize-group Icicles', for more details on -installation and customization options. - - Once installed, Icicles can be activated by evaluating): - - (require 'icicles) - (icy-mode 1) - - Icicles can be toggled by typing 'M-x icy'. - - When Icicles is on, 'TAB' offers completion, provided the conditions -determined by 'ess-first-tab-never-complete' allow it. Typing 'M-TAB' -will attempt completion regardless. Typing 'M-?' in 'ESS' or 'iESS' -modes brings up the relevant completion candidates from which to choose. -Minibuffer input filters the available candidates. Use 'TAB' for prefix -completion or 'S-TAB' for substring or regexp completion. Use 'S-SPC' -to match an additional pattern (repeatable). You can cycle among the -matching candidates, choosing with 'RET' or 'mouse-2'. - - -File: ess.info, Node: Developing with ESS, Next: Extras, Prev: Completion, Up: Top - -10 Developing with ESS -********************** - -ESS provides several tools to help you with the development of your R -packages: - -* Menu: - -* ESS tracebug:: Visual debugging, breakpoints, tracing, watch etc. -* Editing documentation:: Tools to edit R documentation -* Namespaced Evaluation:: Develop your packages on the fly - - -File: ess.info, Node: ESS tracebug, Next: Editing documentation, Up: Developing with ESS - -10.1 ESS tracebug -================= - -* Menu: - -* Getting started with tracebug:: Quick tutorial - -ESS 'tracebug' offers visual debugging, interactive error navigation, -interactive backtrace, breakpoint manipulation, control over R error -actions, watch window and interactive flagging/unflagging of functions -for debugging. - - 'ess-tracebug' is on by default. You can toggle it on and off with -'M-x' 'ess-tracebug'. To disable startup activation of 'ess-tracebug' -set 'ess-use-tracebug' to nil. - - Tracebug functionality can be found on 'ess-dev-map', bound to 'C-c -C-t'. Additionally, when subprocess is in a debugging state -'ess-debug-minor-mode' is active and the following additional shortcuts -are available: - -* Interactive Debugging (`ess-debug-minor-mode-map'): - - M-C . Continue . `ess-debug-command-continue' - M-C-C . Continue multi . `ess-debug-command-continue-multi' - M-N . Next step . `ess-debug-command-next' - M-C-N . Next step multi . `ess-debug-command-next-multi' - M-U . Up frame . `ess-debug-command-up' - M-Q . Quit debugging . `ess-debug-command-quit' - - - These are all the tracebug commands defined in 'ess-dev-map' ('C-c -C-t ?' to show this table): - - -* Breakpoints (`ess-dev-map'): - - b . Set BP (repeat to cycle BP type) . `ess-bp-set' - B . Set conditional BP . `ess-bp-set-conditional' - k . Kill BP . `ess-bp-kil' - K . Kill all BPs . `ess-bp-kill-all' - o . Toggle BP state . `ess-bp-toggle-state' - l . Set logger BP . `ess-bp-set-logger' - n . Goto next BP . `ess-bp-next' - p . Goto previous BP . `ess-bp-previous' - - (C- prefixed equivalents are also defined) - -* Debugging (`ess-dev-map'): - ` . Show traceback . `ess-show-traceback' (also on C-c `) - ~ . Show callstack . `ess-show-call-stack' (also on C-c ~) - e . Toggle error action (repeat to cycle). `ess-debug-toggle-error-action' - d . Flag for debugging . `ess-debug-flag-for-debugging' - u . Unflag for debugging . `ess-debug-unflag-for-debugging' - w . Watch window . `ess-watch' - - (C- prefixed equivalents are also defined) - -* Navigation to errors (general Emacs functionality): - - C-x `, M-g n . `next-error' - M-g p . `previous-error' - -* Misc: - -? . Show this help . `ess-tracebug-show-help' - - - To configure how electric watch window splits the display see -'ess-watch-width-threshold' and 'ess-watch-height-threshold' variables. - - _Note:_ Currently, ess-tracebug does not detect some of R's debug -related messages in non-English locales. To set your R messages to -English add the following line to your .Rprofile init file: - - Sys.setlocale("LC_MESSAGES", "C") - - -File: ess.info, Node: Getting started with tracebug, Up: ESS tracebug - -10.1.1 Getting started with tracebug ------------------------------------- - -Consider a buffer with the following function: - -test <- function(x){ - mean(x), -} - - Evaluating the function (e.g. 'C-c C-c') results in an error about -an unexpected comma. You can use 'next-error' (bound by default to 'C-x -`', 'M-g n', and 'M-g M-n') to jump to the place where the error -occurred. Alternatively, use the mouse to click on the error to jump to -where it occurred. - - Correct the error by deleting the comma. Now put point on 'mean' and -set the breakpoint using 'C-c C-t b' ('ess-bp-set') and reevaluate the -function. Jump to the inferior buffer (possibly using 'C-c C-z') and -evaluate 'test(1:10)'. An interactive debug process starts, stopping at -the breakpoint we just specified. Here you can debug your function -(what is 'x' at this point?). Use 'M-N' to continue. - - Let's replace our test function with one slightly more complicated: - -test <- function(x){ - x <- x + 1 - y <- mean(x) - x <- ifelse(x > 5, x, x - 100) - list(x, y) -} - - Try setting multiple breakpoints. You can unset a breakpoint by -killing it with 'C-c C-t k'. You can set conditional breakpoints too. -Try setting one by placing point on the line 'x <- x + 1' and doing 'C-c -C-t B'. ESS will ask for the condition. Let's set it to -'!is.numeric(x)'. After re-evaluating 'test', try calling 'test(1:100)' -and 'test('foo')'. - - You can remove all breakpoints with 'C-c C-t K'. - - You can flag a function for debugging (similar to calling -'debug(test)' at R's prompt) by doing 'C-c C-t d'. Try this yourself by -putting point over 'test' and doing 'C-c C-t d'. - - If an error occurs, you can get the complete call stack by doing 'C-c -`' or 'C-c C-t `' ('ess-show-traceback'). - - Tracebug also offers a watch window where you can watch values of -objects. Open it with 'C-c C-t w' ('ess-watch'). Initially you aren't -watching anything. Add something with 'a' (e.g. 'a test'). The watch -window displays what the object is at any given time and automatically -updates. Quit the watch window with 'q'. - - -File: ess.info, Node: Editing documentation, Next: Namespaced Evaluation, Prev: ESS tracebug, Up: Developing with ESS - -10.2 Editing documentation -========================== - -ESS provides two ways of writing documentation for R objects. Either -using the standard R documentation system or using in-source -documentation written as structured comment fields for use with the -Roxygen package. - -* Menu: - -* R documentation files:: Edit objects in a specialized buffer -* Roxygen:: Loading source files into the ESS process - - -File: ess.info, Node: R documentation files, Next: Roxygen, Up: Editing documentation - -10.2.1 Editing R documentation (Rd) files ------------------------------------------ - -R objects are documented in files written in the "R documentation" -("Rd"), a simple markup language closely resembling (La)TeX, which can -be processed into a variety of formats, including LaTeX, HTML, and plain -text. Rd format is described in section "Rd format" of the "Writing R -Extensions" manual in the R distribution. ESS has several features that -facilitate editing Rd files. - - Visiting an Rd file as characterized by its extension 'Rd' will -activate Rd Mode, which provides several facilities for making editing R -documentation files more convenient, by helping with indentation, -insertions, even doing some of the typing for you (with Abbrev Mode), -and by showing Rd keywords, strings, etc. in different faces (with Font -Lock Mode). - - In Rd mode, the following special Emacs commands can be used in -addition to the standard Emacs commands. - -'C-h m' - Describe the features of Rd mode. - -'LFD' -'RET' - Reindent the current line, insert a newline and indent the new line - ('reindent-then-newline-and-indent'). An abbrev before point is - expanded if 'abbrev-mode' is non-'nil'. - -'TAB' - Indent current line based on its contents and on previous lines. - ('indent-according-to-mode'). - -'C-c C-e' - Insert a "skeleton" with Rd markup for at least all mandatory - entries in Rd files ('Rd-mode-insert-skeleton'). Note that many - users might prefer to use the R function 'prompt' on an existing R - object to generate a non-empty Rd "shell" documenting the object - (which already has all information filled in which can be obtained - from the object). - -'C-c C-f' - Insert "font" specifiers for some of the Rd markup commands markup - available for emphasizing or quoting text, including markup for - URLs and email addresses ('Rd-font'). 'C-c C-f' is only a prefix; - see e.g. 'C-c C-f TAB' for the available bindings. Note that - currently, not all of the Rd text markup as described in section - "Marking text" of "Writing R Extensions" can be accessed via 'C-c - C-f'. - -'C-c C-j' - Insert a suitably indented '\item{' on the next line - ('Rd-mode-insert-item'). - -'C-c C-p' - Preview a plain text version ("help file", *note Help::) generated - from the Rd file ('Rd-preview-help'). - - In addition, when editing Rd files one can interact with a running R -process in a similar way as when editing R language files. For example, -'C-c C-v' provides access to on-line help, and 'C-c C-n' sends the -current line to the R process for evaluation. This interaction is -particularly useful when editing the examples in the Rd file. See 'C-h -m' for all available commands. - - Rd mode also provides access to abbreviations for most of the Rd -markup commands. Type 'M-x list-abbrevs' with Abbrev mode turned on to -list all available abbrevs. Note that all Rd abbrevs start with a grave -accent. - - Rd mode can be customized via the following variables. - - -- User Option: Rd-mode-hook - Hook to be run when Rd mode is entered. - - -- User Option: Rd-indent-level - The indentation of Rd code with respect to containing blocks. - Default is 2. - - -- User Option: Rd-to-help-command - The shell command used for converting Rd source to help text. - Default is 'R CMD Rd2txt'. - - To automatically turn on the abbrev and font-lock features of Rd -mode, add the following lines to one of your Emacs startup files: - - (add-hook 'Rd-mode-hook - (lambda () - (abbrev-mode 1) - (font-lock-mode 1))) - - -File: ess.info, Node: Roxygen, Prev: R documentation files, Up: Editing documentation - -10.2.2 Editing Roxygen documentation ------------------------------------- - -The Roxygen R package makes it possible to keep the intended contents -for Rd files as structured comments in the R source files. Roxygen can -then parse R files and generate appropriate Rd files from these -comments, fill the usage fields as well as updating 'NAMESPACE' files. -See the Roxygen documentation found via for more -information on its usage. An example of an Roxygen entry for a simple R -function can look like this: - - ##' Description of the function - ##' - ##' Further details about this function - ##' @title A title - ##' @param me all parameters must be listed and documented - ##' @return Description of the return value - ##' @author The author - myfun <- function(me) - cat("Hello", me, "\n") - The entry is immediately preceding the object to document and all -lines start with the Roxygen prefix string, in this case '##''. ESS -provides support to edit these documentation entries by providing line -filling, navigation, template generation etc. Syntax highlighting is -provided. - - Roxygen is customized by the variables in the customization group -"Ess Roxy". Customizables include the Roxygen prefix, use of folding to -toggle visibility of Roxygen entries and the Roxygen template. - - All ESS Roxygen support is defined in 'ess-roxy.el' which is loaded -by default in ESS. The following special Emacs commands are provided. - - -- Command: ess-roxy-update-entry - 'C-c C-o C-o' Generate a Roxygen template or update the parameter - list in Roxygen entry at point (or above the function at the - point). Documented parameters that are not in the function are - placed last in the list, parameters that are not documented and not - in the definition are dropped. Parameter descriptions are filled - if 'ess-roxy-fill-param-p' is non-nil. - - -- Command: ess-roxy-toggle-roxy-region BEG END - 'C-c C-o C-c' Toggle the presence of the leading Roxygen string on - all lines in the marked region (between BEG and END. Convenient - for transferring text to Roxygen entries and to evaluate example - fields. - - -- Command: ess-roxy-preview-Rd NAME-FILE - 'C-c C-o C-r' Use the attached R process to parse the entry at - point to obtain the Rd code. Convenient for previewing and - checking syntax. When used with the prefix argument NAME-FILE, - i.e. 'C-u C-c C-e C-r', place the content in a buffer associated - with a Rd file with the same name as the documentation. Requires - the Roxygen package to be installed. - - -- Command: ess-roxy-preview-HTML VISIT-INSTEAD-OF-OPEN - 'C-c C-o C-t' Use the attached R process to parse the entry at to - generate HTML for the entry and open it in a browser. When used - with the prefix argument VISIT-INSTEAD-OF-OPEN, i.e. 'C-u C-c C-e - C-t', visit the generated HTML file instead. Requires the Roxygen - and tools packages to be installed. - - -- Command: ess-roxy-previous-entry - 'C-c C-o p' Go to start of the Roxygen entry above point. - - -- Command: ess-roxy-next-entry - 'C-c C-o n' Go to end of the Roxygen entry above point. - - -- Command: ess-roxy-hide-all - 'C-c C-o C-h' Use the hideshow mode to fold away the visibility of - all Roxygen entries. Hide-show support must be enabled for this - binding to get defined. - - ESS also advises the following standard editing functions in order to -make Roxygen editing more intuitive: - -'TAB' - 'ess-R-complete-object-name' Complete Roxygen tag at point. E.g. - doing 'TAB' when the point is at the end of '@par' completes to - '@param'. - -'M-h' - 'mark-paragraph' If the transient mark mode is active, place mark - and point at start end end of the field at point and activate the - mark. - -'TAB' - 'ess-indent-command' If hide-show support is enabled, fold away the - visibility of the Roxygen entry at point. - -'M-q' - 'fill-paragraph' Fill the Roxygen field at point. - -'C-a' - 'ess-roxy-move-beginning-of-line' Move to the point directly to the - right of the Roxygen start string. If already there, move to the - beginning of the line. - -'RET' - 'newline-and-indent' Insert a new line and the Roxygen prefix - string. - - -File: ess.info, Node: Namespaced Evaluation, Prev: Editing documentation, Up: Developing with ESS - -10.3 Namespaced Evaluation -========================== - -In non package files evaluation commands, *Note Evaluating code::, send -portions of the current buffer environment ('R_GlobalEnv'. When -developing packages, ESS sends code to the corresponding package -namespace and (for visible objects) into package environment (visible on -search path). All objects that are assigned are displayed in the -minibuffer alongside the environment in which they are assigned. - - Here is a short overview of how namespace and package environments -work in R. All objects defined in a package 'foo' are stored in an -environment called 'namespace:foo'. Parent environment of -'namespace:foo' is an environment 'imports:foo' which contains copies of -all objects from other packages which 'foo' imports. Parent environment -of 'imports:foo' is the 'namespace:base'. Parent environment of -'namespace:base' is .GlobalEnv. Thus functions and methods stored in -'namespace:foo' see all the objects in .GlobalEnv unless shadowed by -objects in 'imports:foo', 'namespace:base', or 'namespace:foo' itself. -There is another environment associated with 'foo' - 'package:foo'. -This environment stores *copies* of exported objects from -'namespace:foo' and is placed on the search() path, i.e. if 'foo' is -loaded and if you start with .GlobalEnv and iteratively call -parent.env() you will get eventually to 'package:foo'. Thus all methods -and functions defined in .GlobalEnv can "see" objects in 'package:foo' -environment. See also -. - - Occasionally you want to evaluate into a package from a non-package -file, or the other way around, evaluate into 'GlobalEnv' from inside a -package. In such cases 'C-c C-t C-s' is your friend. - - -- Command: ess-r-set-evaluation-env ARG - 'C-c C-t C-s' Set or unset the current evaluation environment (a - package). - - -File: ess.info, Node: Extras, Next: ESS for R, Prev: Developing with ESS, Up: Top - -11 Other ESS features and tools -******************************* - -ESS has a few extra features, which didn't fit anywhere else. -* Menu: - -* ESS ElDoc:: Display function arguments in minibuffer -* ESS Flymake:: On-the-fly syntax checking -* Handy commands:: Usefully commands at your fingertips -* Highlighting:: Syntactic highlighting of buffers -* Parens:: Parenthesis matching -* Graphics:: Using graphics with ESS -* Imenu:: Support for Imenu in ESS -* Toolbar:: Support for toolbar in ESS -* Xref:: Xref -* Rdired:: Directory editor for R objects -* Package listing:: R object/package management and help utilities -* Org:: Interaction with Org mode -* Sweave and AUCTeX:: Support for Sweave in ESS and AUCTeX - - -File: ess.info, Node: ESS ElDoc, Next: ESS Flymake, Up: Extras - -11.1 ElDoc -========== - -In 'ElDoc' mode, the echo area displays function's arguments at point. -ElDoc is active by default in 'ess-mode' and 'inferior-ess-mode' -buffers. To activate it only in 'ess-mode' buffers, place the following -into your init file: - - (setq ess-use-eldoc 'script-only) - - -- User Option: ess-use-eldoc - If 't', activate eldoc in ess-mode and inferior-ess-mode buffers. - If ''script-only' activate in ess-mode buffers only. Set - 'ess-use-eldoc' to 'nil' to stop using 'ElDoc' altogether. - - -- User Option: ess-eldoc-show-on-symbol - This variable controls whether the help is shown only inside - function calls. If set to 't', 'ElDoc' shows help string whenever - the point is on a symbol, otherwise (the default), shows only when - the point is in a function call, i.e. after ''(''. - - -- User Option: ess-eldoc-abbreviation-style - The variable determines how the doc string should be abbreviated to - fit into minibuffer. Posible values are 'nil', 'mild', 'normal', - 'strong' and 'aggressive'. Please see the documentation of the - variable for more details. The default filter is 'normal'. - - Ess-eldoc also honors the value of 'eldoc-echo-area-use-multiline-p', -which if set to 'nil', will cause the truncation of doc string -indifferent of the value of 'ess-eldoc-abbreviation-style'. This way -you can combine different filter levels with the truncation. - - -File: ess.info, Node: ESS Flymake, Next: Handy commands, Prev: ESS ElDoc, Up: Extras - -11.2 Flymake -============ - -The minor mode 'flymake-mode' provides on-the-fly syntax checking. ESS -provides support for flymake in R-mode in Emacs versions 26 and newer. -It is enabled by default, to disable it you may set 'ess-use-flymake' to -'nil'. In order to use it, you may need to install the 'lintr' R -package, available from CRAN. - - -- User Option: ess-use-flymake - When non-nil, use flymake. If ''process', only use flymake when - the buffer has an inferior process running. - - -- User Option: ess-r-flymake-linters - This variable describes the linters to use. It can either be a - string with an R expression to be used as-is or a list of strings - where each element is passed to 'lintr::with_defaults'. See the - help page for 'lintr::default_linters' for information on available - linters and their defaults. - - -- User Option: ess-r-flymake-lintr-cache - When 't' (the default), lintr uses a cache. Change to 'nil' to - disable lintr's caching mechanism. - - -File: ess.info, Node: Handy commands, Next: Highlighting, Prev: ESS Flymake, Up: Extras - -11.3 Handy commands -=================== - - -- Command: ess-handy-commands - Request and execute a command from 'ess-handy-commands' list. - - -- User Option: ess-handy-commands - An alist of custom ESS commands available for call by - 'ess-handy-commands' and 'ess-smart-comma' function. - - Currently contains: - - change-directory - 'ess-change-directory' - help-index - 'ess-display-index' - help-object - 'ess-display-help-on-object' - vignettes - 'ess-display-vignettes' - objects[ls] - 'ess-execute-objects' - search - 'ess-execute-search' - set-width - 'ess-execute-screen-options' - install.packages - 'ess-install.packages' - library - 'ess-library' - setRepos - 'ess-setRepositories' - sos - 'ess-sos' - - Handy commands: 'ess-library', 'ess-install.packages', etc - ask for -item with completion and execute the correspond command. 'ess-sos' is a -interface to 'findFn' function in package 'sos'. If package 'sos' is -not found, ask user for interactive install. - - -File: ess.info, Node: Highlighting, Next: Parens, Prev: Handy commands, Up: Extras - -11.4 Syntactic highlighting of buffers -====================================== - -ESS provides Font-Lock (*note Using Multiple Typefaces: (emacs)Faces.) -patterns for inferior R Mode, S Mode, and R Transcript Mode buffers. - - The font-lock patterns are defined by the following variables, which -you may modify if desired: - - -- User Option: inferior-R-font-lock-keywords - Font-lock patterns for inferior *R* processes. (There is a - corresponding 'inferior-S-font-lock-keywords' for *S* processes.) - The default value highlights prompts, inputs, assignments, output - messages, vector and matrix labels, and literals such as 'NA' and - 'TRUE'. - - -- User Option: ess-R-font-lock-keywords - Font-lock patterns for ESS R programming mode. (There is a - corresponding 'ess-S-font-lock-keywords' for S buffers.) The - default value highlights function names, literals, assignments, - source functions and reserved words. - - -File: ess.info, Node: Parens, Next: Graphics, Prev: Highlighting, Up: Extras - -11.5 Parenthesis matching -========================= - -Emacs has facilities for highlighting the parenthesis matching the -parenthesis at point. This feature is very useful when trying to -examine which parentheses match each other. This highlighting also -indicates when parentheses are not matching. You may activate it -putting this in your Emacs configuration file: - - (show-paren-mode) - - -File: ess.info, Node: Graphics, Next: Imenu, Prev: Parens, Up: Extras - -11.6 Using graphics with ESS -============================ - -One of the main features of R is its ability to generate high-resolution -graphics plots. When using R in a windowing environment, no additional -configuration is necessary; plots will be shown in a new (non-Emacs) -window. - - If not using a windowing environment or S, ESS provides a number of -features for dealing with such plots. - -* Menu: - -* printer:: The printer() graphics driver -* X11:: The X11() (and other X Windows based) driver -* winjava:: Java Graphics Device - - -File: ess.info, Node: printer, Next: X11, Up: Graphics - -11.6.1 Using ESS with the 'printer()' driver --------------------------------------------- - -This is the simplest (and least desirable) method of using graphics -within ESS. S's 'printer()' device driver produces crude character based -plots which can be contained within the ESS process buffer itself. To -start using character graphics, issue the S command - printer(width=79) - (the 'width=79' argument prevents Emacs line-wrapping at column 80 on -an 80-column terminal. Use a different value for a terminal with a -different number of columns.) Plotting commands do not generate -graphics immediately, but are stored until the 'show()' command is -issued, which displays the current figure. - - -File: ess.info, Node: X11, Next: winjava, Prev: printer, Up: Graphics - -11.6.2 Using ESS with windowing devices ---------------------------------------- - -Of course, the ideal way to use graphics with ESS is to use a windowing -system. Under X Windows, or X11, this requires that the DISPLAY -environment variable be appropriately set. - - -File: ess.info, Node: winjava, Prev: X11, Up: Graphics - -11.6.3 Java Graphics Device ---------------------------- - -S+6.1 and newer on Windows contains a java library that supports -graphics. Send the commands: - - library(winjava) - java.graph() - -to start the graphics driver. This allows you to use ESS for both -interaction and graphics within S-PLUS. (Thanks to Tim Hesterberg for -this information.) - - -File: ess.info, Node: Imenu, Next: Toolbar, Prev: Graphics, Up: Extras - -11.7 Imenu -========== - -Imenu is an Emacs tool for providing mode-specific buffer indexes. In -some of the ESS editing modes (currently SAS and R), support for Imenu -is provided. For example, in R mode buffers, the menubar should display -an item called "Imenu-R". Within this menubar you will then be offered -bookmarks to particular parts of your source file (such as the starting -point of each function definition). - - Imenu works by searching your buffer for lines that match what ESS -thinks is the beginning of a suitable entry, for example the beginning -of a function definition. To examine the regular expression that ESS -uses, check the value of 'imenu-generic-expression'. This value is set -by various ESS variables such as 'ess-imenu-S-generic-expression'. - - -File: ess.info, Node: Toolbar, Next: Xref, Prev: Imenu, Up: Extras - -11.8 Toolbar -============ - -The R and S editing modes have support for a toolbar. This toolbar -provides icons to act as shortcuts for starting new S/R processes, or -for evaluating regions of your source buffers. The toolbar should be -present if your Emacs can display images. *Note Customization::, for -ways to change the toolbar. - - -File: ess.info, Node: Xref, Next: Rdired, Prev: Toolbar, Up: Extras - -11.9 Xref -========= - -Xref is an Emacs interface that supports finding "identifiers," usually -function definitions in ESS's view. ESS ships with support for Xref in -Emacs versions 25.1 and higher. *Note (emacs)Xref:: for how to use this -feature. - - -File: ess.info, Node: Rdired, Next: Package listing, Prev: Xref, Up: Extras - -11.10 Rdired -============ - -Ess-rdired provides a dired-like buffer for viewing, editing and -plotting objects in your current R session. If you are used to using -the dired (directory editor) facility in Emacs, this mode gives you -similar functionality for R objects. - - Start an R session with 'M-x R' and then store a few variables, such -as: - - s <- sin(seq(from=0, to=8*pi, length=100)) - x <- c(1, 4, 9) - y <- rnorm(20) - z <- TRUE - - Then use 'M-x ess-rdired' to create a buffer listing the objects in -your current environment and display it in a new window: - mode length - s numeric 100 - x numeric 3 - y numeric 20 - z logical 1 - - Type 'C-h m' or '?' to get a list of the keybindings for this mode. -For example, with your point on the line of a variable, 'p' will plot -the object, 'v' will view it, and 'd' will mark the object for deletion -('x' will actually perform the deletion). - - -File: ess.info, Node: Package listing, Next: Org, Prev: Rdired, Up: Extras - -11.11 Package listing -===================== - -ESS[R] provides several commands to list and manage packages and objects -under the 'C-c C-.' keymap: - - -- Command: ess-r-package-list-local-packages - 'C-c C-. l' List all packages in all available libraries. - - -- Command: ess-r-package-list-available-packages - 'C-c C-. r' List available packages from repositories listed by - 'getOptions(``repos'')' in the current R session. - - -- Command: ess-r-package-update-packages LIB REPOS - 'C-c C-. u' Update packages in a particular library LIB and - repository REPOS. - - -- Command: ess-rutils-rm-all - 'C-c C-. m' Remove all R objects. - - -- Command: ess-rutils-load-wkspc - 'C-c C-. w' Load a workspace file into R. - - -- Command: ess-rutils-save-wkspc - 'C-c C-. s' Save a workspace file. - - -- Command: ess-change-directory - 'C-c C-. d' Change the working directory for the current R session. - - -- Command: ess-rutils-html-docs - 'C-c C-. H' Use 'browse-url' to navigate R html documentation. - - Functions for listing objects and packages ('ess-rutils-local-pkgs', -'ess-rutils-repos-pkgs', and 'ess-rutils-objs') show results in a -separate buffer and window, in 'ess-rutils-mode', providing useful key -bindings in this mode (type '?' in this buffer for a description). - - -File: ess.info, Node: Org, Next: Sweave and AUCTeX, Prev: Package listing, Up: Extras - -11.12 Interaction with Org mode -=============================== - -Org-mode () now supports reproducible research and -literate programming in many languages (including R) - see chapter 14 of -the Org manual -(). For ESS -users, this offers a document-based work environment within which to -embed ESS usage. R code lives in code blocks of an Org document, from -which it can be edited in ess-mode, evaluated, extracted ("tangled") to -pure code files. The code can also be exported ("woven") with the -surrounding text to several formats including HTML and LaTeX. Results of -evaluation including figures can be captured in the Org document, and -data can be passed from the Org document (e.g. from a table) to the ESS -R process. (This section contributed by Dan Davison and Eric Schulte.) - - -File: ess.info, Node: Sweave and AUCTeX, Prev: Org, Up: Extras - -11.13 Support for Sweave in ESS and AUCTeX -========================================== - -Libraries for literate data analysis are obsolete and not loaded by -default. This includes 'ess-noweb', 'ess-swv', and related -functionality like 'Rnw-mode'. Users are encouraged to switch to one of -several other packages that deal with these modes. For example, -polymode , -, or markdown-mode with edit-indirect -. - - ESS provides support for writing and processing Sweave -(), building up on Emacs' -ess-noweb-mode for literate programming. When working on an Sweave -document, the following key bindings are available: - - -- Command: ess-swv-weave CHOOSE - 'M-n s' Run Sweave on the current .Rnw file. If CHOOSE is - non-'nil', offer a menu of available weavers. - - -- Command: ess-swv-latex - 'M-n l' Run LaTeX after Sweave'ing. - - -- Command: ess-swv-PS - 'M-n p' Generate and display a postscript file after LaTeX'ing. - - -- Command: ess-swv-PDF PDFLATEX-CMD - 'M-n P' Generate and display a PDF file after LaTeX'ing. Optional - argument PDFLATEX-CMD is the command to use, which by default, is - the command used to generate the PDF file is the first element of - 'ess-swv-pdflatex-commands'. - - -- User Option: ess-swv-pdflatex-commands - Commands used by 'ess-swv-PDF' to run a version of pdflatex; the - first entry is the default command. - - Sweave'ing with 'ess-swv-weave' starts an inferior-ESS process, if -one is not available. Other commands are available from the 'Sweaving, -Tangling, ...' submenu of the Noweb menu. - - AUCTeX () users may prefer to -set the variable 'ess-swv-plug-into-AUCTeX-p' (available from the "ESS -Sweave" customization group) to t. Alternatively, the same can be -achieved by activating the entry "AUCTeX Interface" from the 'Sweaving, -Tangling, ...' submenu, which toggles this variable on or off. When the -interface is activated, new entries for Sweave'ing and LaTeX'ing -thereafter are available from AUCTeX's "Command" menu. Sweave'ing can, -thus, be done by 'C-c C-c Sweave RET' without an inferior-ESS process. -Similarly, LaTeX'ing can be done by 'C-c C-c LaTeXSweave RET'. In both -cases, the process can be monitored with 'C-c C-l' -('TeX-recenter-output-buffer'). Open the viewer with 'C-c C-v' -('TeX-view'), as usual in AUCTeX. - - -File: ess.info, Node: ESS for R, Next: ESS for SAS, Prev: Extras, Up: Top - -12 Overview of ESS features for the S family -******************************************** - -* Menu: - -* ESS(R)--Editing files:: -* iESS(R)--Inferior ESS processes:: -* Philosophies for using ESS(R):: -* Example ESS usage:: - - -File: ess.info, Node: ESS(R)--Editing files, Next: iESS(R)--Inferior ESS processes, Up: ESS for R - -12.1 ESS[R]-Editing files -========================= - -ESS[R] mode should be automatically turned on when visiting a file -ending with an R or S suffix (*.R, *.S, *.s, etc), which enables the -features discussed previously. Alternatively, type 'M-x R-mode' to put -the current buffer into R mode. However, one will have to start up an -inferior process to take advantage of the interactive features. - - -File: ess.info, Node: iESS(R)--Inferior ESS processes, Next: Philosophies for using ESS(R), Prev: ESS(R)--Editing files, Up: ESS for R - -12.2 iESS[R]-Inferior ESS processes -=================================== - -To start up iESS mode for R, use: - M-x R - M-x S+3 - M-x S4 - M-x S+5 - M-x S+6 - -(for R, S-PLUS 3.x, S4, S+5, S+6 or S+7, respectively. This assumes -that you have access to each). - - In the case that you wish to pass command line arguments to the -starting R process, call it with the universal prefix. To set command -line arguments that apply to all future iESS sessions, set the variable -'inferior-R-args'. - - Note that R has some extremely useful command line arguments. For -example, '--vanilla' will ensure R starts up without loading in any init -files. - - If you have other versions of R or S available on the system, ESS is -also able to start those versions. How this exactly works depend on -which OS you are using (details below). The general principle, -regardless of OS, is that ESS searches the paths listed in the variable -'exec-path' for R binaries. If ESS cannot find your R binaries, on Unix -you can change the Unix environment variable 'PATH', as this variable is -used to set 'exec-path'. - - R on GNU/Linux systems and other Unix-like systems (macOS): If you -have "R-1.8.1" on your 'exec-path', it can be started using 'M-x -R-1.8.1'. By default, ESS will find versions of R beginning "R-1", -"R-2", "R-3", "R-devel", or "R-patched". If your versions of R are -called other names, consider renaming them with a symbolic link or -change the variable 'ess-r-runners-prefixes'. To see which functions -have been created for starting different versions of R, type 'M-x R-' -and then hit [Tab]. These other versions of R can also be started from -the "ESS->Start Process->Other" menu. - - R on Windows systems: If you have "rw1081" on your 'exec-path', it -can be started using 'M-x rw1081'. By default, ESS will find versions -of R located in directories parallel to the version of R in your 'PATH'. -If your versions of R are called other names, you will need to change -the variable 'ess-rterm-versions'. To see which functions have been -created for starting different versions of R, type 'M-x rw' and then hit -[Tab]. These other versions of R can also be started from the -"ESS->Start Process->Other" menu. - - Once ESS has found these extra versions of R, it will then create a -new function, called 'M-x run-ess-r-newest', which will call the newest -version of R that it found. (ESS examines the date in the first line of -information from 'R --version' to determine which is newest.) - - -File: ess.info, Node: Philosophies for using ESS(R), Next: Example ESS usage, Prev: iESS(R)--Inferior ESS processes, Up: ESS for R - -12.3 Philosophies for using ESS[R] -================================== - -There are two philosophies for using ESS. Most modern best practices -prefer the first. ESS is configured for the first, and this is what the -manual focuses on. - - 1: The source code is real. Objects are realizations of the source -code. Source for EVERY user modified object is placed in a particular -directory or directories, for later editing and retrieval. - - 2: R objects are real. Source code is a temporary realization of the -objects. Dumped buffers should not be saved. -_We_strongly_discourage_this_approach_. However, if you insist, add the -following lines to your Emacs configuration file: - (setq ess-keep-dump-files nil) - (setq ess-delete-dump-files t) - (setq ess-mode-silently-save nil) - - -File: ess.info, Node: Example ESS usage, Prev: Philosophies for using ESS(R), Up: ESS for R - -12.4 Example ESS usage -====================== - -Comments as to what should be happening are prefixed by "##". - - ### Data Analysis Example - - ## Open the file you want with - C-x C-f myfile.R - - ## Edit as appropriate, then start and switch to an *R* - process buffer with - C-c C-z - - ## A new buffer *R* will appear. R will have been started - ## in this buffer. The buffer is in iESS [R] mode. - - ## Return to the script - C-z (or C-c C-z if you have pressed other keys in between) - - ## Send current region (if active), or function, or paragraph at - point with - C-M-x - - ## Send current region or function or paragraph and step with - C-c C-c - - ## Send current line with - C-RET - - ## or load the entire buffer with - C-c C-l - - ## Save the revised myfile.R with - C-x C-s. - - ## Save the entire *R* interaction buffer with - C-x C-s. - - ## Search for documentation with - C-c C-d - - ## Investigate available ESS commands with - C-c C-h - - ## You will be prompted for a file name. The recommended name is - ## myfile.Rout. With this suffix, the file will be opened in - ## ess-transcript. - - - -File: ess.info, Node: ESS for SAS, Next: ESS for BUGS, Prev: ESS for R, Up: Top - -13 ESS for SAS -************** - -* Menu: - -* ESS(SAS)--Design philosophy:: -* ESS(SAS)--Editing files:: -* ESS(SAS)--TAB key:: -* ESS(SAS)--Batch SAS processes:: -* ESS(SAS)--Function keys for batch processing:: -* iESS(SAS)--Interactive SAS processes:: -* iESS(SAS)--Common problems:: -* ESS(SAS)--Graphics:: -* ESS(SAS)--Windows:: -ESS[SAS] was designed for use with SAS. It is descended from emacs -macros developed by John Sall for editing SAS programs and 'SAS-mode' by -Tom Cook. Those editing features and new advanced features are part of -ESS[SAS]. The user interface of ESS[SAS] has similarities with ESS[S] -and the SAS Display Manager. - - -File: ess.info, Node: ESS(SAS)--Design philosophy, Next: ESS(SAS)--Editing files, Up: ESS for SAS - -13.1 ESS[SAS]-Design philosophy -=============================== - -ESS[SAS] was designed to aid the user in writing and maintaining SAS -programs, such as 'FOO.sas'. Both interactive and batch submission of -SAS programs is supported. - - ESS[SAS] was written with two primary goals. - 1. The emacs text editor provides a powerful and flexible development - environment for programming languages. These features are a boon - to all programmers and, with the help of ESS[SAS], to SAS users as - well. - 2. Although a departure from SAS Display Manager, ESS[SAS] provides - similar key definitions to give novice ESS[SAS] users a head start. - Also, inconvenient SAS Display Manager features, like remote - submission and syntax highlighting, are provided transparently; - appealing to advanced ESS[SAS] users. - - -File: ess.info, Node: ESS(SAS)--Editing files, Next: ESS(SAS)--TAB key, Prev: ESS(SAS)--Design philosophy, Up: ESS for SAS - -13.2 ESS[SAS]-Editing files -=========================== - -ESS[SAS] is the mode for editing SAS language files. This mode handles: - - * proper indenting, generated by both and . - * color and font choices based on syntax. - * ability to save and submit the file you are working on as a batch - SAS process with a single keypress and to continue editing while it - is runs in the background. - * capability of killing the batch SAS process through the '*shell*' - buffer or allow the SAS process to keep on running after you exit - emacs. - * single keypress navigation of '.sas', '.log' and '.lst' files - ('.log' and '.lst' files are refreshed with each keypress). - * ability to send the contents of an entire buffer, a highlighted - region, or a single line to an interactive SAS process. - * ability to switch between processes which would be the target of - the buffer (for the above). - - ESS[SAS] is automatically turned on when editing a file with a '.sas' -suffix (or other extension, if specified via 'auto-mode-alist'). The -function keys can be enabled to use the same function keys that the SAS -Display Manager does. The interactive capabilities of ESS require you -to start an inferior SAS process with 'M-x SAS' (*Note -iESS(SAS)--Interactive SAS processes::.) - - At this writing, the indenting and syntax highlighting are generally -correct. Known issues: for multiple line '*' or '%*' comments, only the -first line is highlighted; for '.log' files, only the first line of a -'NOTE:', 'WARNING:' or 'ERROR:' message is highlighted; unmatched -single/double quotes in 'CARDS' data lines are *NOT* ignored; in an -iterative 'DO' statement, 'TO' and 'BY' are not highlighted. - - -File: ess.info, Node: ESS(SAS)--TAB key, Next: ESS(SAS)--Batch SAS processes, Prev: ESS(SAS)--Editing files, Up: ESS for SAS - -13.3 ESS[SAS]- key -======================= - -Two options. The key is bound by default to 'sas-indent-line'. -This function is used to syntactically indent SAS code so 'PROC' and -'RUN' are in the left margin, other statements are indented -'sas-indent-width' spaces from the margin, continuation lines are -indented 'sas-indent-width' spaces in from the beginning column of that -statement. This is the type of functionality that emacs provides in -most programming language modes. This functionality is activated by -placing the following line in your initialization file prior to a -'require'/'load': - (setq ess-sas-edit-keys-toggle nil) - - ESS provides an alternate behavior for that makes it behave as -it does in SAS Display Manager, i.e. move the cursor to the next stop. -The alternate behavior also provides a "TAB" backwards, 'C-', that -moves the cursor to the stop to the left and deletes any characters -between them. This functionality is obtained by placing the following -line in your initialization file prior to a 'require'/'load': - (setq ess-sas-edit-keys-toggle t) - Under the alternate behavior, is bound to 'M-x tab-to-tab-stop' -and the stops are defined by 'ess-sas-tab-stop-list'. - - -File: ess.info, Node: ESS(SAS)--Batch SAS processes, Next: ESS(SAS)--Function keys for batch processing, Prev: ESS(SAS)--TAB key, Up: ESS for SAS - -13.4 ESS[SAS]-Batch SAS processes -================================= - -Submission of a SAS batch job is dependent on your environment. -'ess-sas-submit-method' is determined by your operating system and your -shell. It defaults to ''sh' unless you are running Windows or Mac -Classic. Under Windows, it will default to ''sh' if you are using a -UNIX-imitating shell; otherwise ''ms-dos' for an MS-DOS shell. On -macOS, it will default to ''sh', but under Mac Classic, it defaults to -''apple-script'. You will also set this to ''sh' if the SAS batch job -needs to run on a remote machine rather than your local machine. This -works transparently if you are editing the remote file via ange-ftp/EFS -or tramp. Note that 'ess-sas-shell-buffer-remote-init' is a Local -Variable that defaults to '"ssh"' which will be used to open the buffer -on the remote host and it is assumed that no password is necessary, i.e. -you are using 'ssh-agent'/'ssh-add' or the equivalent (see the -discussion about Local Variables below if you need to change the -default). - - However, if you are editing the file locally and transferring it back -and forth with Kermit, you need some additional steps. First, start -Kermit locally before remotely logging in. Open a local copy of the -file with the 'ess-kermit-prefix' character prepended (the default is -'"#"'). Execute the command 'M-x ess-kermit-get' which automatically -brings the contents of the remote file into your local copy. If you -transfer files with Kermit manually in a '*shell*' buffer, then note -that the Kermit escape sequence is 'C-q C-\ c' rather than 'C-\ c' which -it would be in an ordinary terminal application, i.e. not in an emacs -buffer. Lastly, note that the remote Kermit command is specified by -'ess-kermit-command'. - - The command used by the 'SUBMIT' function key ( or ) to -submit a batch SAS job, whether local or remote, is -'ess-sas-submit-command' which defaults to 'sas-program'. 'sas-program' -is '"invoke SAS using program file"' for Mac Classic and '"sas"' -otherwise. However, you may have to alter 'ess-sas-submit-command' for -a particular program, so it is defined as buffer-local. Conveniently, -it can be set at the end of the program: - endsas; - Local variables: - ess-sas-submit-command: "sas8" - End: - - The command line is also made of 'ess-sas-submit-pre-command', -'ess-sas-submit-post-command' and 'ess-sas-submit-command-options' (the -last of which is also buffer-local). Here are some examples for your -'~/.emacs' or '~/.emacs.d/init.el' file (you may also use -'M-x customize-variable'): - ;'sh default - (setq ess-sas-submit-pre-command "nohup") - ;'sh default - (setq ess-sas-submit-post-command "-rsasuser &") - ;'sh example - (setq-default ess-sas-submit-command "/usr/local/sas/sas") - ;'ms-dos default - (setq ess-sas-submit-pre-command "start") - ;'ms-dos default - (setq ess-sas-submit-post-command "-rsasuser -icon") - ;Windows example - (setq-default ess-sas-submit-command "c:/progra~1/sas/sas.exe") - ;Windows example - (setq-default ess-sas-submit-command "c:\\progra~1\\sas\\sas.exe") - - There is a built-in delay before a batch SAS job is submitted when -using a UNIX-imitating shell under Windows. This is necessary in many -cases since the shell might not be ready to receive a command. This -delay is currently set high enough so as not to be a problem. But, -there may be cases when it needs to be set higher, or could be set much -lower to speed things up. You can over-ride the default in your -'~/.emacs' or '~/.emacs.d/init.el' file by: - (setq ess-sleep-for 0.2) - - For example, '(setq ess-sas-global-unix-keys t)' keys shown, '(setq -ess-sas-global-pc-keys t)' in parentheses; ESS[SAS] function keys are -presented in the next section. Open the file you want to work with -'C-x C-f foo.sas'. 'FOO.sas' will be in ESS[SAS] mode. Edit as -appropriate, then save and submit the batch SAS job. - () - The job runs in the '*shell*' buffer while you continue to edit -'FOO.sas'. If 'ess-sas-submit-method' is ''sh', then the message buffer -will display the shell notification when the job is complete. The ''sh' -setting also allows you to terminate the SAS batch job before it is -finished. - () - Terminating a SAS batch in the '*shell*' buffer. - kill PID - You may want to visit the '.log' (whether the job is still running or -it is finished) and check for error messages. The '.log' will be -refreshed and you will be placed in it's buffer. You will be taken to -the first error message, if any. - () - Goto the next error message, if any. - () - Now, 'refresh' the '.lst' and go to it's buffer. - () - If you wish to make changes, go to the '.sas' file with. - () - Make your editing changes and submit again. - () - - -File: ess.info, Node: ESS(SAS)--Function keys for batch processing, Next: iESS(SAS)--Interactive SAS processes, Prev: ESS(SAS)--Batch SAS processes, Up: ESS for SAS - -13.5 ESS[SAS]-Function keys for batch processing -================================================ - -The setup of function keys for SAS batch processing is unavoidably -complex, but the usage of function keys is simple. There are five -distinct options: - - Option 1 (default). Function keys in ESS[SAS] are not bound to elisp -commands. This is in accordance with the GNU Elisp Coding Standards -(GECS) which do not allow function keys to be bound so that they are -available to the user. - - Options 2-5. Since GECS does not allow function keys to be bound by -modes, these keys are often unused. So, ESS[SAS] provides users with -the option of binding elisp commands to these keys. Users who are -familiar with SAS will, most likely, want to duplicate the function key -capabilities of the SAS Display Manager. There are four options (noted -in parentheses). - - a. SAS Display Manager has different function key definitions for UNIX - (2, 4) and Windows (3, 5); ESS[SAS] can use either. - b. The ESS[SAS] function key definitions can be active in all buffers - (global: 4, 5) or limited (local: 2, 3) only to buffers with files - that are associated with ESS[SAS] as specified in your - 'auto-mode-alist'. - - The distinction between local and global is subtle. If you want the -ESS[SAS] definitions to work when you are in the '*shell*' buffer or -when editing files other than the file extensions that ESS[SAS] -recognizes, you will most likely want to use the global definitions. If -you want your function keys to understand SAS batch commands when you -are editing SAS files, and to behave normally when editing other files, -then you will choose the local definitions. The option can be chosen by -the person installing ESS for a site or by an individual. - - a. For a site installation or an individual, place *ONLY ONE* of the - following lines in your initialization file prior to a - 'require'/'load'. ESS[SAS] function keys are available in ESS[SAS] - if you choose either 2 or 3 and in all modes if you choose 4 or 5: - ;;2; (setq ess-sas-local-unix-keys t) - ;;3; (setq ess-sas-local-pc-keys t) - ;;4; (setq ess-sas-global-unix-keys t) - ;;5; (setq ess-sas-global-pc-keys t) - - The names '-unix-' and '-pc-' have nothing to do with the operating - system that you are running. Rather, they mimic the definitions - that the SAS Display Manager uses by default on those platforms. - - b. If your site installation has configured the keys contrary to your - liking, then you must call the appropriate function. - (load "ess-site") ;; local-unix-keys - (ess-sas-global-pc-keys) - - Finally, we get to what the function keys actually do. You may -recognize some of the nicknames as SAS Display Manager commands (they -are in all capitals). - -UNIX PC Nickname - 'refresh' - revert the current buffer with the file of the same name if the file is - newer than the buffer - 'SUBMIT' - save the current '.sas' file (which is either the '.sas' file in the - current buffer or the '.sas' file associated with the '.lst' or '.log' - file in the current buffer) and submit the file as a batch SAS job - 'PROGRAM' - switch buffer to '.sas' file - 'LOG' - switch buffer to '.log' file, 'refresh' and goto next error message, if - any - 'OUTPUT' - switch buffer to '.lst' file and 'refresh' - 'filetype-1' - switch buffer to 'filetype-1' (defaults to '.txt') file and 'refresh' - 'shell' - switch buffer to '*shell*' - 'VIEWTABLE' - open an interactive 'PROC FSEDIT' session on the SAS dataset near point - toggle-log - toggle ESS[SAS] for '.log' files; useful for certain debugging situations - 'filetype-2' - switch buffer to 'filetype-2' (defaults to '.dat') file and 'refresh' - viewgraph - open a 'GSASFILE' near point for viewing either in emacs or with an - external viewer -'C-' 'C-' rtf-portrait - create an MS RTF portrait file from the current buffer with a file - extension of '.rtf' -'C-' 'C-' rtf-landscape - create an MS RTF landscape file from the current buffer with a file - extension of '.rtf' -'C-' 'C-' submit-region - write region to 'ess-temp.sas' and submit -'C-' 'C-' append-to-log - append 'ess-temp.log' to the current '.log' file -'C-' 'C-' append-to-output - append 'ess-temp.lst' to the current '.lst' file -'C-' 'C-' 'INSIGHT' - open an interactive 'PROC INSIGHT' session on the SAS dataset near point -'C-''C-'toggle-listing - toggle ESS[SAS] for '.lst' files; useful for toggling read-only - - 'SUBMIT', 'PROGRAM', 'LOG' and 'OUTPUT' need no further explanation -since they mimic the SAS Display Manager commands and related function -key definitions. However, six other keys have been provided for -convenience and are described below. - - 'shell' switches you to the '*shell*' buffer where you can interact -with your operating system. This is especially helpful if you would -like to kill a SAS batch job. You can specify a different buffer name -to associate with a SAS batch job (besides '*shell*') with the -buffer-local variable 'ess-sas-shell-buffer'. This allows you to have -multiple buffers running SAS batch jobs on multiple local/remote -computers that may rely on different methods specified by the -buffer-local variable 'ess-sas-submit-method'. - - performs the 'refresh' operation on the current buffer. -'refresh' compares the buffer's last modified date/time with the file's -last modified date/time and replaces the buffer with the file if the -file is newer. This is the same operation that is automatically -performed when 'LOG', 'OUTPUT', 'filetype-1' or are pressed. - - 'filetype-1' switches you to a file with the same file name as your -'.sas' file, but with a different extension ('.txt' by default) and -performs 'refresh'. You can over-ride the default extension; for -example in your '~/.emacs' or '~/.emacs.d/init.el' file: - (setq ess-sas-suffix-1 "csv") ; for example - - will prompt you for the name of a permanent SAS dataset near -point to be opened for viewing by 'PROC FSEDIT'. You can control the -SAS batch command-line with 'ess-sas-data-view-submit-options'. For -controlling the SAS batch commands, you have the global variables -'ess-sas-data-view-libname' and 'ess-sas-data-view-fsview-command' as -well as the buffer-local variable 'ess-sas-data-view-fsview-statement'. -If you have your SAS 'LIBNAME' defined in '~/autoexec.sas', then the -defaults for these variables should be sufficient. - - Similarly, 'C-' will prompt you for the name of a permanent SAS -dataset near point to be opened for viewing by 'PROC INSIGHT'. You can -control the SAS batch command-line with -'ess-sas-data-view-submit-options'. For controlling the SAS batch -commands, you have the global variables 'ess-sas-data-view-libname' and -'ess-sas-data-view-insight-command' as well as the buffer-local variable -'ess-sas-data-view-insight-statement'. - - toggles ESS[SAS] mode for '.log' files which is off by default -(technically, it is 'SAS-log-mode', but it looks the same). The syntax -highlighting can be helpful in certain debugging situations, but large -'.log' files may take a long time to highlight. - - is the same as 'filetype-1' except it is '.dat' by default. - - will prompt you for the name of a 'GSASFILE' near the point in -'.log' to be opened for viewing either with emacs or with an external -viewer. Depending on your version of emacs and the operating system you -are using, emacs may support '.gif' and '.jpg' files internally. You -may need to change the following variables for your own situation. -'ess-sas-graph-view-suffix-regexp' is a regular expression of supported -file types defined via file name extensions. -'ess-sas-graph-view-viewer-default' is the default external viewer for -your platform. 'ess-sas-graph-view-viewer-alist' is an alist of -exceptions to the default; i.e. file types and their associated viewers -which will be used rather than the default viewer. - (setq ess-sas-graph-view-suffix-regexp (concat "[.]\\([eE]?[pP][sS]\\|" - "[pP][dD][fF]\\|[gG][iI][fF]\\|[jJ][pP][eE]?[gG]\\|" - "[tT][iI][fF][fF]?\\)")) ;; default - (setq ess-sas-graph-view-viewer-default "kodakimg") ;; Windows default - (setq ess-sas-graph-view-viewer-default "sdtimage") ;; Solaris default - (setq ess-sas-graph-view-viewer-alist - '(("[eE]?[pP][sS]" . "gv") ("[pP][dD][fF]" . "gv")) ;; default w/ gv - - 'C-' produces US landscape by default, however, it can produce A4 -landscape (first line for "global" key mapping, second for "local"): - (global-set-key [(control f2)] 'ess-sas-rtf-a4-landscape) - (define-key sas-mode-local-map [(control f2)] 'ess-sas-rtf-a4-landscape) - - -File: ess.info, Node: iESS(SAS)--Interactive SAS processes, Next: iESS(SAS)--Common problems, Prev: ESS(SAS)--Function keys for batch processing, Up: ESS for SAS - -13.6 iESS[SAS]-Interactive SAS processes -======================================== - -Inferior ESS (iESS) is the method for interfacing with interactive -statistical processes (programs). iESS[SAS] is what is needed for -interactive SAS programming. iESS[SAS] works best with the SAS -command-line option settings '"-stdio -linesize 80 -noovp --nosyntaxcheck"' (the default of 'inferior-SAS-args'). - - '-stdio' - required to make the redirection of stdio work - '-linesize 80' - keeps output lines from folding on standard terminals - '-noovp' - prevents error messages from printing 3 times - '-nosyntaxcheck' - permits recovery after syntax errors - - To start up iESS[SAS] mode, use: - M-x SAS - - The '*SAS:1.log*' buffer in 'ESStr' mode corresponds to the file -'FOO.log' in SAS batch usage and to the 'SAS: LOG' window in the SAS -Display Manager. All commands submitted to SAS, informative messages, -warnings, and errors appear here. - - The '*SAS:1.lst*' buffer in 'ESSlst' mode corresponds to the file -'FOO.lst' in SAS batch usage and to the 'SAS: OUTPUT' window in the SAS -Display Manager. All printed output appears in this window. - - The '*SAS:1*' buffer exists solely as a communications buffer. The -user should never use this buffer directly. Files are edited in the -'FOO.sas' buffer. The 'C-c C-r' key in ESS[SAS] is the functional -equivalent of bringing a file into the 'SAS: PROGRAM EDITOR' window -followed by 'SUBMIT'. - - For example, open the file you want to work with. - C-x C-f foo.sas - 'FOO.sas' will be in ESS[SAS] mode. Edit as appropriate, and then -start up SAS with the cursor in the 'FOO.sas' buffer. - M-x SAS - Four buffers will appear on screen: -Buffer Mode Description -'FOO.sas' 'ESS[SAS]' your source file -'*SAS:1*' 'iESS[SAS:1]' iESS communication buffer -'*SAS:1.log*' 'Shell ESStr SAS log information - []' -'*SAS:1.lst*' 'Shell ESSlst SAS listing information - []' - If you would prefer each of the four buffers to appear in its own -individual frame, you can arrange for that. Place the cursor in the -buffer displaying 'FOO.sas'. Enter the sequence 'C-c C-w'. The cursor -will normally be in buffer 'FOO.sas'. If not, put it there and -'C-x b FOO.sas'. - - Send regions, lines, or the entire file contents to SAS (regions are -most useful: a highlighted region will normally begin with the keywords -'DATA' or 'PROC' and end with 'RUN;'), 'C-c C-r'. - - Information appears in the log buffer, analysis results in the -listing buffer. In case of errors, make the corrections in the -'FOO.sas' buffer and resubmit with another 'C-c C-r'. - - At the end of the session you may save the log and listing buffers -with the usual 'C-x C-s' commands. You will be prompted for a file -name. Typically, the names 'FOO.log' and 'FOO.lst' will be used. You -will almost certainly want to edit the saved files before including them -in a report. The files are read-only by default. You can make them -writable by the emacs command 'C-x C-q'. - - At the end of the session, the input file 'FOO.sas' will typically -have been revised. You can save it. It can be used later as the -beginning of another iESS[SAS] session. It can also be used as a batch -input file to SAS. - - The '*SAS:1*' buffer is strictly for ESS use. The user should never -need to read it or write to it. Refer to the '.lst' and '.log' buffers -for monitoring output! - - Troubleshooting: *Note iESS(SAS)--Common problems::. - - -File: ess.info, Node: iESS(SAS)--Common problems, Next: ESS(SAS)--Graphics, Prev: iESS(SAS)--Interactive SAS processes, Up: ESS for SAS - -13.7 iESS[SAS]-Common problems -============================== - - 1. iESS[SAS] does not work on Windows. In order to run SAS inside an - emacs buffer, it is necessary to start SAS with the '-stdio' - option. SAS does not support the '-stdio' option on Windows. - 2. If 'M-x SAS' gives errors upon startup, check the following: - * you are running Windows: see 1. - * 'ess-sas-sh-command' (from the ESS 'etc' directory) needs to - be executable; too check, type 'M-x dired'; if not, fix it as - follows, type 'M-:', then at the minibuffer prompt 'Eval:', - type '(set-file-modes "ess-sas-sh-command" 493)'. - * 'sas' isn't in your executable path; to verify, type 'M-:' and - at the minibuffer prompt 'Eval:', type '(executable-find - "sas")' - 3. 'M-x SAS' starts SAS Display Manager. Probably, the command 'sas' - on your system calls a shell script. In that case you will need to - locate the real 'sas' executable and link to it. You can execute - the UNIX command: - find / -name sas -print - Now place a soft link to the real 'sas' executable in your '~/bin' - directory, with for example - cd ~/bin - ln -s /usr/local/sas9/sas sas - Check your 'PATH' environment variable to confirm that '~/bin' -appears before the directory in which the 'sas' shell script appears. - - -File: ess.info, Node: ESS(SAS)--Graphics, Next: ESS(SAS)--Windows, Prev: iESS(SAS)--Common problems, Up: ESS for SAS - -13.8 ESS[SAS]-Graphics -====================== - -Output from a SAS/GRAPH 'PROC' can be displayed in a SAS/GRAPH window -for SAS batch on Windows or for both SAS batch and interactive with -XWindows on UNIX. If you need to create graphics files and view them -with , then include the following (either in 'FOO.sas' or in -'~/autoexec.sas'): - filename gsasfile 'graphics.ps'; - goptions device=ps gsfname=gsasfile gsfmode=append; - 'PROC PLOT' graphs can be viewed in the listing buffer. You may wish -to control the vertical spacing to allow the entire plot to be visible -on screen, for example: - proc plot; - plot a*b / vpos=25; - run; - - -File: ess.info, Node: ESS(SAS)--Windows, Prev: ESS(SAS)--Graphics, Up: ESS for SAS - -13.9 ESS[SAS]-Windows -===================== - - * iESS[SAS] does not work on Windows. *Note iESS(SAS)--Common - problems::. - - * ESS[SAS] mode for editing SAS language files works very well. - *Note ESS(SAS)--Editing files::. - - * There are two execution options for SAS on Windows. You can use - batch. *Note ESS(SAS)--Batch SAS processes::. - - Or you can mark regions with the mouse and submit the code with - 'submit-region' or paste them into SAS Display Manager. - - -File: ess.info, Node: ESS for BUGS, Next: ESS for JAGS, Prev: ESS for SAS, Up: Top - -14 ESS for BUGS -*************** - -ESS[BUGS] provides 5 features. First, BUGS syntax is described to allow -for proper fontification of statements, distributions, functions, -commands and comments in BUGS model files, command files and log files. -Second, ESS creates templates for the command file from the model file -so that a BUGS batch process can be defined by a single file. Third, -ESS provides a BUGS batch script that allows ESS to set BUGS batch -parameters. Fourth, key sequences are defined to create a command file -and submit a BUGS batch process. Lastly, interactive submission of BUGS -commands is also supported. - -14.1 ESS[BUGS]-Model files -========================== - -Model files with the '.bug' extension are edited in ESS[BUGS] mode. -Three keys are bound for your use in ESS[BUGS], 'F2', 'C-c C-c' and '='. -'F2' performs the same action as it does in ESS[SAS], *Note -ESS(SAS)--Function keys for batch processing::. 'C-c C-c' performs the -function 'ess-bugs-next-action' which you will use a lot. Pressing it -in an empty buffer for a model file will produce a template for you. -'=' inserts the set operator, '<-'. - -14.2 ESS[BUGS]-Command files -============================ - -Files ending in '.bmd' are used for BUGS command files. When you have -finished editing your model file and press 'C-c C-c', a command file is -created if one does not already exist. When you are finished editing -your command file, pressing 'C-c C-c' again will submit your command -file as a batch job. - -14.3 ESS[BUGS]-Log files -======================== - -The '.bog' extension is used for BUGS log files. The command line -generated by ESS creates the '.bog' transcript file. - - -File: ess.info, Node: ESS for JAGS, Next: Mailing lists/bug reports, Prev: ESS for BUGS, Up: Top - -15 ESS for JAGS -*************** - -ESS[JAGS] provides 4 features. First, JAGS syntax is described to allow -for proper fontification of statements, distributions, functions, -commands and comments in JAGS model files, command files and log files. -Second, ESS creates templates for the command file from the model file -so that a JAGS batch process can be defined by a single file. Third, -ESS provides a JAGS batch script that allows ESS to set JAGS batch -parameters. Fourth, key sequences are defined to create a command file -and submit a JAGS batch process. - -15.1 ESS[JAGS]-Model files -========================== - -Files with the '.jag' extension are edited in ESS[JAGS] mode. Three -keys are bound for your use in ESS[JAGS], 'F2', 'C-c C-c' and '='. 'F2' -performs the same action as it does in ESS[SAS], *Note -ESS(SAS)--Function keys for batch processing::. 'C-c C-c' performs the -function 'ess-bugs-next-action' which you will use a lot. Pressing it -in an empty buffer for a model file will produce a template for you. -'=' inserts the set operator, '<-'. - - The first press of 'C-c C-c' will set up a template, including some -necessary file-local variables in an empty buffer. These variables are -'ess-jags-chains', 'ess-jags-monitor', 'ess-jags-thin', -'ess-jags-burnin' and 'ess-jags-update'; they appear in the 'Local -Variables' section. When you are finished editing your model file, -pressing 'C-c C-c' will perform the necessary actions to build your -command file for you. - - The 'ess-jags-chains' variable is the number of chains that you want -to initialize and sample from; defaults to 1. The 'ess-jags-monitor' -variable is a list of variables that you want monitored: encase each -variable in double quotes. When you press 'C-c C-c', the appropriate -statements are created in the command file to monitor the list of -variables. By default, no variables are explicitly monitored which -means JAGS will implicitly monitor all "default" variables. The -'ess-jags-thin' variable is the thinning parameter. By default, the -thinning parameter is set to 1, i.e. no thinning. The -'ess-jags-burnin' variable is the number of initial samples to discard. -By default, the burnin parameter is set to 10000. The 'ess-jags-update' -variable is the number of post-burnin samples to keep. By default, the -update parameter is set to 10000. Both 'ess-jags-burnin' and -'ess-jags-update' are multiplied by 'ess-jags-thin' since JAGS does not -do it automatically. - -15.2 ESS[JAGS]-Command files -============================ - -Files ending in '.jmd' are for JAGS command files. For your '.jmd' -file, there is only one variable, 'ess-jags-command', in the 'Local -Variables' section. When you have finished editing your model file and -press 'C-c C-c', a command file is created if one does not already -exist. When you are finished editing your command file, pressing 'C-c -C-c' again will submit your command file as a batch job. The -'ess-jags-command' variable allows you to specify a different JAGS -program to use to run your model; defaults to "jags". - -15.3 ESS[JAGS]-Log files -======================== - -The '.jog' extension is used for JAGS log files. You may find 'F2' -useful to refresh the '.jog' if the batch process over-writes or appends -it. - - -File: ess.info, Node: Mailing lists/bug reports, Next: Customization, Prev: ESS for JAGS, Up: Top - -16 Bugs and Bug Reporting, Mailing Lists -**************************************** - -* Menu: - -* Bugs:: -* Reporting Bugs:: -* Mailing Lists:: -* Help with Emacs:: - - -File: ess.info, Node: Bugs, Next: Reporting Bugs, Up: Mailing lists/bug reports - -16.1 Bugs -========= - - * Commands like 'ess-display-help-on-object' and list completion - cannot be used while the user is entering a multi-line command. - The only real fix in this situation is to use another ESS process. - - * The 'ess-eval-' commands can leave point in the ESS process buffer - in the wrong place when point is at the same position as the last - process output. This proves difficult to fix, in general, as we - need to consider all _windows_ with 'window-point' at the right - place. - - * It's possible to clear the modification flag (say, by saving the - buffer) with the edit buffer not having been loaded into S. - - * Backup files can sometimes be left behind, even when - 'ess-keep-dump-files' is 'nil'. - - * Passing an incomplete S expression to 'ess-execute' causes ESS to - hang. - - * The function-based commands don't always work as expected on - functions whose body is not a parenthesized or compound expression, - and don't even recognize anonymous functions (i.e. functions not - assigned to any variable). - - * Multi-line commands could be handled better by the command history - mechanism. - - * Changes to the continutation prompt in R (e.g. 'options(continue = - " ")') are not automatically detected by ESS. Hence, for now, the - best thing is not to change the continuation prompt. If you do - change the continuation prompt, you will need to change accordingly - the value of 'inferior-ess-secondary-prompt' in - 'R-customize-alist'. - - -File: ess.info, Node: Reporting Bugs, Next: Mailing Lists, Prev: Bugs, Up: Mailing lists/bug reports - -16.2 Reporting Bugs -=================== - -Please send bug reports, suggestions etc. to , -or post them on our github issue tracker -(https://github.com/emacs-ess/ESS/issues) - - The easiest way to do this is within Emacs by typing - - 'M-x ess-submit-bug-report' - - This also gives the maintainers valuable information about your -installation which may help us to identify or even fix the bug. - - If Emacs reports an error, backtraces can help us debug the problem. -Type "M-x set-variable RET debug-on-error RET t RET". Then run the -command that causes the error and you should see a *Backtrace* buffer -containing debug information; send us that buffer. - - Note that comments, suggestions, words of praise and large cash -donations are also more than welcome. - - -File: ess.info, Node: Mailing Lists, Next: Help with Emacs, Prev: Reporting Bugs, Up: Mailing lists/bug reports - -16.3 Mailing Lists -================== - -There is a mailing list for discussions and announcements relating to -ESS. Join the list by sending an e-mail with "subscribe ess-help" (or -"help") in the body to ; contributions -to the list may be mailed to . Rest assured, -this is a fairly low-volume mailing list. - - The purposes of the mailing list include - - * helping users of ESS to get along with it. - * discussing aspects of using ESS. - * suggestions for improvements. - * announcements of new releases of ESS. - * posting small patches to ESS. - - -File: ess.info, Node: Help with Emacs, Prev: Mailing Lists, Up: Mailing lists/bug reports - -16.4 Help with Emacs -==================== - -Emacs is a complex editor with many abilities that we do not have space -to describe here. If you have problems with other features of Emacs -(e.g. printing), there are several sources to consult, including the -Emacs FAQs (try 'M-x view-emacs-faq') and EmacsWiki -(). Please consult them before asking on the -mailing list about issues that are not specific to ESS. - - -File: ess.info, Node: Customization, Next: Indices, Prev: Mailing lists/bug reports, Up: Top - -Appendix A Customizing ESS -************************** - -ESS can be easily customized to your taste simply by including the -appropriate lines in your Emacs configuration file. There are numerous -variables which affect the behavior of ESS in certain situations which -can be modified to your liking. Keybindings may be set or changed to -your preferences, and for per-buffer customizations hooks are also -available. - - Most of these variables can be viewed and set using the Custom -facility within Emacs. Type 'M-x customize-group RET ess RET' to see -all the ESS variables that can be customized. Variables are grouped by -subject to make it easy to find related variables. - - -File: ess.info, Node: Indices, Prev: Customization, Up: Top - -Indices -******* - -* Menu: - -* Key index:: -* Function and program index:: -* Variable index:: -* Concept index:: - - -File: ess.info, Node: Key index, Next: Function and program index, Up: Indices - -Key index -========= - -[index] -* Menu: - -* ,: Handy commands. (line 6) -* {: Indenting. (line 53) -* }: Indenting. (line 53) -* C-c C-. d: Package listing. (line 30) -* C-c C-. H: Package listing. (line 33) -* C-c C-. l: Package listing. (line 10) -* C-c C-. m: Package listing. (line 21) -* C-c C-. r: Package listing. (line 13) -* C-c C-. s: Package listing. (line 27) -* C-c C-. u: Package listing. (line 17) -* C-c C-. w: Package listing. (line 24) -* C-c C-b: Evaluating code. (line 66) -* C-c C-c: Other. (line 9) -* C-c C-c <1>: Evaluating code. (line 39) -* C-c C-e C-d: Edit buffer. (line 9) -* C-c C-e C-s: Styles. (line 15) -* C-c C-e s: Styles. (line 15) -* C-c C-f: Evaluating code. (line 52) -* C-c C-j: Evaluating code. (line 45) -* C-c C-o C-c: Roxygen. (line 45) -* C-c C-o C-h: Roxygen. (line 72) -* C-c C-o C-o: Roxygen. (line 37) -* C-c C-o C-r: Roxygen. (line 51) -* C-c C-o C-t: Roxygen. (line 59) -* C-c C-o n: Roxygen. (line 69) -* C-c C-o p: Roxygen. (line 66) -* C-c C-q: Hot keys. (line 71) -* C-C C-r: Evaluating code. (line 59) -* C-c C-s: Hot keys. (line 34) -* C-c C-t C-s: Namespaced Evaluation. - (line 36) -* C-c C-v: Hot keys. (line 66) -* C-c C-w: Clean. (line 11) -* C-c C-x: Hot keys. (line 24) -* C-c C-z: Other. (line 13) -* C-c M-b: Evaluating code. (line 69) -* C-c M-f: Evaluating code. (line 55) -* C-c M-j: Evaluating code. (line 48) -* C-c M-l: Hot keys. (line 50) -* C-c M-r: Evaluating code. (line 62) -* C-c RET: Resubmit. (line 14) -* C-c `: Error Checking. (line 9) -* C-j: Indenting. (line 60) -* C-M-a: Other edit buffer commands. - (line 10) -* C-M-e: Other edit buffer commands. - (line 14) -* C-M-h: Other edit buffer commands. - (line 18) -* C-M-q: Indenting. (line 49) -* C-M-x: Evaluating code. (line 36) -* C-RET: Evaluating code. (line 32) -* ESC C-a: Other edit buffer commands. - (line 10) -* ESC C-e: Other edit buffer commands. - (line 14) -* ESC C-h: Other edit buffer commands. - (line 18) -* ESC C-q: Indenting. (line 49) -* M-;: Indenting. (line 65) -* M-?: Object names. (line 33) -* M-C-q: Indenting. (line 49) -* M-n l: Sweave and AUCTeX. (line 24) -* M-n P: Sweave and AUCTeX. (line 30) -* M-n s: Sweave and AUCTeX. (line 20) -* M-RET: Resubmit. (line 10) -* RET: Command-line editing. (line 10) -* RET <1>: Resubmit. (line 18) -* TAB: Indenting. (line 35) - - -File: ess.info, Node: Function and program index, Next: Variable index, Prev: Key index, Up: Indices - -Function and program index -========================== - -[index] -* Menu: - -* backward-kill-word: Command-line editing. - (line 22) -* comint-backward-matching-input: Process buffer motion. - (line 31) -* comint-bol: Command-line editing. - (line 31) -* comint-copy-old-input: Transcript resubmit. (line 16) -* comint-delete-output: Last command. (line 24) -* comint-dynamic-complete: Object names. (line 12) -* comint-forward-matching-input: Process buffer motion. - (line 32) -* comint-history-isearch-backward-regexp: Command History. (line 32) -* comint-interrupt-subjob: Other. (line 8) -* comint-kill-input: Command-line editing. - (line 26) -* comint-next-input: Command History. (line 18) -* comint-next-matching-input-from-input: Command History. (line 45) -* comint-next-prompt: Process buffer motion. - (line 15) -* comint-previous-input: Command History. (line 14) -* comint-previous-matching-input-from-input: Command History. (line 41) -* comint-previous-prompt: Process buffer motion. - (line 11) -* comint-show-output: Last command. (line 20) -* dump(): Edit buffer. (line 35) -* ess-change-directory: Package listing. (line 29) -* ess-cleanup: Hot keys. (line 71) -* ess-cleanup <1>: Help. (line 170) -* ess-complete-object-name: Object names. (line 32) -* ess-describe-help-mode: Help. (line 21) -* ess-display-help-on-object: Hot keys. (line 65) -* ess-display-help-on-object <1>: Help. (line 8) -* ess-display-help-on-object <2>: Help. (line 25) -* ess-dump-object-into-edit-buffer: Edit buffer. (line 8) -* ess-electric-brace: Indenting. (line 52) -* ess-eval-buffer: Evaluating code. (line 65) -* ess-eval-buffer-and-go: Evaluating code. (line 68) -* ess-eval-function: Evaluating code. (line 51) -* ess-eval-function-and-go: Evaluating code. (line 54) -* ess-eval-line: Evaluating code. (line 44) -* ess-eval-line-and-go: Evaluating code. (line 47) -* ess-eval-line-and-step: Help. (line 106) -* ess-eval-region: Evaluating code. (line 58) -* ess-eval-region <1>: Help. (line 111) -* ess-eval-region-and-go: Evaluating code. (line 61) -* ess-eval-region-or-function-or-paragraph: Evaluating code. (line 35) -* ess-eval-region-or-function-or-paragraph-and-step: Evaluating code. - (line 38) -* ess-eval-region-or-line-and-step: Evaluating code. (line 31) -* ess-execute-objects: Hot keys. (line 23) -* ess-execute-search: Hot keys. (line 33) -* ess-goto-beginning-of-function-or-para: Other edit buffer commands. - (line 9) -* ess-goto-end-of-function-or-para: Other edit buffer commands. - (line 13) -* ess-handy-commands: Handy commands. (line 6) -* ess-handy-commands <1>: Handy commands. (line 6) -* ess-indent-command: Roxygen. (line 90) -* ess-indent-exp: Indenting. (line 48) -* ess-indent-or-complete: Indenting. (line 34) -* ess-load-file: Hot keys. (line 49) -* ess-load-file <1>: Loading. (line 11) -* ess-mark-function: Other edit buffer commands. - (line 17) -* ess-parse-errors: Hot keys. (line 54) -* ess-parse-errors <1>: Error Checking. (line 9) -* ess-quit: Hot keys. (line 70) -* ess-quit <1>: Help. (line 170) -* ess-R-complete-object-name: Roxygen. (line 80) -* ess-r-package-list-available-packages: Package listing. (line 12) -* ess-r-package-list-local-packages: Package listing. (line 9) -* ess-r-package-update-packages: Package listing. (line 16) -* ess-r-set-evaluation-env: Namespaced Evaluation. - (line 35) -* ess-remote: ESS processes on Remote Computers. - (line 9) -* ess-request-a-process: Multiple ESS processes. - (line 18) -* ess-resynch: Object names. (line 52) -* ess-roxy-hide-all: Roxygen. (line 71) -* ess-roxy-move-beginning-of-line: Roxygen. (line 97) -* ess-roxy-next-entry: Roxygen. (line 68) -* ess-roxy-preview-HTML: Roxygen. (line 58) -* ess-roxy-preview-Rd: Roxygen. (line 50) -* ess-roxy-previous-entry: Roxygen. (line 65) -* ess-roxy-toggle-roxy-region: Roxygen. (line 44) -* ess-roxy-update-entry: Roxygen. (line 36) -* ess-rutils-html-docs: Package listing. (line 32) -* ess-rutils-load-wkspc: Package listing. (line 23) -* ess-rutils-rm-all: Package listing. (line 20) -* ess-rutils-save-wkspc: Package listing. (line 26) -* ess-set-style: Styles. (line 14) -* ess-skip-to-help-section: Help. (line 55) -* ess-skip-to-next-section: Help. (line 46) -* ess-skip-to-previous-section: Help. (line 46) -* ess-smart-comma: Handy commands. (line 6) -* ess-submit-bug-report: Reporting Bugs. (line 6) -* ess-switch-to-end-of-ESS: Help. (line 117) -* ess-switch-to-inferior-or-script-buffer: Other. (line 12) -* ess-swv-latex: Sweave and AUCTeX. (line 23) -* ess-swv-PDF: Sweave and AUCTeX. (line 29) -* ess-swv-PS: Sweave and AUCTeX. (line 26) -* ess-swv-weave: Sweave and AUCTeX. (line 19) -* ess-tracebug: ESS tracebug. (line 6) -* ess-transcript-clean-region: Clean. (line 10) -* ess-transcript-copy-command: Resubmit. (line 13) -* ess-transcript-send-command: Resubmit. (line 9) -* ess-transcript-send-command-and-move: Resubmit. (line 17) -* ess-use-ido, ess-completing-read: Minibuffer completion. - (line 6) -* fill-paragraph: Roxygen. (line 94) -* getting started with tracebug: Getting started with tracebug. - (line 6) -* inferior-ess-send-input: Command-line editing. - (line 9) -* mark-paragraph: Roxygen. (line 85) -* newline-and-indent: Roxygen. (line 102) -* objects(): Hot keys. (line 24) -* printer(): printer. (line 11) -* q(): Hot keys. (line 71) -* R: Starting up. (line 11) -* S: Starting up. (line 11) -* search(): Hot keys. (line 34) -* search() <1>: Object names. (line 19) -* source(): Evaluating code. (line 18) -* source() <1>: Loading. (line 11) -* STERM: Statistical Process running in ESS?. - (line 6) - - -File: ess.info, Node: Variable index, Next: Concept index, Prev: Function and program index, Up: Indices - -Variable index -============== - -[index] -* Menu: - -* comint-delimiter-argument-list: History expansion. (line 28) -* comint-input-ring-size: Command History. (line 9) -* comment-column: Indenting. (line 24) -* ess-ask-about-transfile: Customizing startup. (line 36) -* ess-ask-about-transfile <1>: Saving transcripts. (line 12) -* ess-ask-for-ess-directory: Customizing startup. (line 7) -* ess-ask-for-ess-directory <1>: Customizing startup. (line 21) -* ess-auto-width: Customizing startup. (line 56) -* ess-auto-width-visible: Customizing startup. (line 56) -* ess-delete-dump-files: Source Files. (line 12) -* ess-directory: Source Directories. (line 48) -* ess-dump-filename-template: Source Directories. (line 9) -* ess-eldoc-abbreviation-style: ESS ElDoc. (line 24) -* ess-eldoc-show-on-symbol: ESS ElDoc. (line 18) -* ess-eval-visibly: Evaluating code. (line 14) -* ess-execute-in-process-buffer: Hot keys. (line 13) -* ess-first-tab-never-complete: Indenting. (line 42) -* ess-first-tab-never-complete <1>: Object names. (line 6) -* ess-function-template: Edit buffer. (line 17) -* ess-handy-commands: Handy commands. (line 6) -* ess-handy-commands <1>: Handy commands. (line 9) -* ess-indent-with-fancy-comments: Indenting. (line 27) -* ess-keep-dump-files: Source Files. (line 26) -* ess-plain-first-buffername: Multiple ESS processes. - (line 14) -* ess-post-run-hook: Customizing startup. (line 26) -* ess-pre-run-hook: Customizing startup. (line 21) -* ess-r-flymake-linters: ESS Flymake. (line 16) -* ess-r-flymake-lintr-cache: ESS Flymake. (line 23) -* ess-R-font-lock-keywords: Highlighting. (line 19) -* ess-search-list: Source Directories. (line 62) -* ess-source-directory: Source Directories. (line 22) -* ess-style: Styles. (line 21) -* ess-style-alist: Styles. (line 28) -* ess-switch-to-end-of-proc-buffer: Other. (line 21) -* ess-swv-pdflatex-commands: Sweave and AUCTeX. (line 35) -* ess-use-eldoc: ESS ElDoc. (line 13) -* ess-use-flymake: ESS Flymake. (line 12) -* iESS program arguments: Customizing startup. (line 48) -* inferior-ess-program: Customizing startup. (line 48) -* inferior-R-font-lock-keywords: Highlighting. (line 12) -* Rd-indent-level: R documentation files. - (line 78) -* Rd-mode-hook: R documentation files. - (line 75) -* Rd-to-help-command: R documentation files. - (line 82) - - -File: ess.info, Node: Concept index, Prev: Variable index, Up: Indices - -Concept Index -============= - -[index] -* Menu: - -* aborting R commands: Other. (line 9) -* aborting S commands: Other. (line 9) -* arguments to R program: Customizing startup. (line 51) -* arguments to S program: Customizing startup. (line 51) -* authors: Credits. (line 6) -* autosaving: Source Files. (line 83) -* bug reports: Reporting Bugs. (line 6) -* bugs: Bugs. (line 6) -* changing ESS processes: Multiple ESS processes. - (line 6) -* cleaning up: Hot keys. (line 71) -* comint: Credits. (line 6) -* command history: Command History. (line 6) -* command line arguments: iESS(R)--Inferior ESS processes. - (line 16) -* command-line completion: Object names. (line 6) -* command-line editing: Command-line editing. - (line 6) -* commands: Entering commands. (line 6) -* comments: Source Files. (line 41) -* comments in R: Indenting. (line 18) -* company: Company. (line 6) -* completion in edit buffer: Other edit buffer commands. - (line 24) -* completion of object names: Object names. (line 6) -* completion on file names: Object names. (line 39) -* completion on lists: Object names. (line 37) -* completion, when prompted for object names: Edit buffer. (line 14) -* creating new objects: Edit buffer. (line 14) -* credits: Credits. (line 6) -* customization: Customization. (line 6) -* data frames: Object names. (line 20) -* deleting output: Last command. (line 24) -* directories: Starting up. (line 11) -* dump file directories: Source Directories. (line 20) -* dump file names: Source Directories. (line 6) -* dump files: Edit buffer. (line 27) -* dump files <1>: Source Files. (line 10) -* echoing commands when evaluating: Evaluating code. (line 18) -* edit buffer: Edit buffer. (line 6) -* editing commands: Command History. (line 6) -* editing functions: Editing objects. (line 6) -* editing transcripts: Saving transcripts. (line 18) -* ElDoc: ESS ElDoc. (line 6) -* emacsclient: Emacsclient. (line 6) -* entering commands: Entering commands. (line 6) -* errors: Error Checking. (line 6) -* ESS commands blocking Emacs: Evaluating code. (line 18) -* ess developer: Namespaced Evaluation. - (line 6) -* ESS process buffer: Starting up. (line 17) -* ESS process directory: Starting up. (line 11) -* ESS tracebug: ESS tracebug. (line 6) -* ESS-elsewhere: ESS processes on Remote Computers. - (line 9) -* ess-roxy: Roxygen. (line 6) -* evaluating code with echoed commands: Evaluating code. (line 18) -* evaluating R expressions: Evaluating code. (line 29) -* evaluating S expressions: Evaluating code. (line 29) -* finding function definitions: Xref. (line 6) -* flymake: ESS Flymake. (line 6) -* font-lock mode: Highlighting. (line 7) -* formatting source code: Indenting. (line 32) -* graphics: Graphics. (line 6) -* Handy commands: Handy commands. (line 6) -* help files: Help. (line 6) -* highlighting: Highlighting. (line 7) -* historic backups: Source Files. (line 41) -* hot keys: Hot keys. (line 43) -* icicles: Icicles. (line 6) -* IDO completions: Minibuffer completion. - (line 6) -* indenting: Indenting. (line 32) -* installation: Installation. (line 6) -* interactive use of R: Introduction. (line 31) -* interactive use of S: Introduction. (line 31) -* interrupting R commands: Other. (line 9) -* interrupting S commands: Other. (line 9) -* introduction: Introduction. (line 6) -* keyboard short cuts: Hot keys. (line 43) -* killing temporary buffers: Hot keys. (line 71) -* killing the ESS process: Hot keys. (line 71) -* lists, completion on: Object names. (line 37) -* motion in transcript mode: Transcript Mode. (line 17) -* multi-line commands, resubmitting: Transcript resubmit. (line 33) -* multiple ESS processes: Multiple ESS processes. - (line 6) -* multiple inferior processes: Multiple ESS processes. - (line 6) -* multiple interactive processes: Multiple ESS processes. - (line 6) -* new objects, creating: Edit buffer. (line 14) -* objects: Hot keys. (line 24) -* pages in the process buffer: Transcript. (line 24) -* paging commands in help buffers: Help. (line 28) -* paragraphs in the process buffer: Transcript. (line 13) -* parsing errors: Error Checking. (line 6) -* process buffer: Starting up. (line 17) -* process names: Multiple ESS processes. - (line 8) -* programming in R: Introduction. (line 43) -* programming in S: Introduction. (line 43) -* project work in R: Source Files. (line 41) -* project work in S: Source Files. (line 41) -* quitting from ESS: Hot keys. (line 71) -* re-executing commands: Command History. (line 6) -* reading long command outputs: Last command. (line 19) -* remote Computers: ESS processes on Remote Computers. - (line 9) -* reverting function definitions: Edit buffer. (line 27) -* roxy: Roxygen. (line 6) -* Roxygen: Roxygen. (line 6) -* running R: Starting up. (line 6) -* running S: Starting up. (line 6) -* S+elsewhere: ESS processes on Remote Computers. - (line 9) -* search list: Hot keys. (line 34) -* search list <1>: Source Directories. (line 55) -* sending input: Entering commands. (line 6) -* Space in function argument completion: Function arguments. (line 10) -* starting directory: Starting up. (line 11) -* starting ESS: Starting up. (line 6) -* STERM: Statistical Process running in ESS?. - (line 6) -* temporary buffers: Help. (line 169) -* temporary buffers, killing: Hot keys. (line 71) -* tracebug tutorial: Getting started with tracebug. - (line 6) -* tramp support: ESS processes on Remote Computers. - (line 9) -* transcript: Transcript. (line 9) -* transcript file: Customizing startup. (line 40) -* transcript file names: Saving transcripts. (line 13) -* transcript mode motion: Transcript Mode. (line 17) -* transcripts of R sessions: Introduction. (line 38) -* transcripts of S sessions: Introduction. (line 38) -* using ESS interactively: Introduction. (line 31) -* using R interactively: Introduction. (line 31) -* using S interactively: Introduction. (line 31) -* winjava: winjava. (line 6) -* working directory: Starting up. (line 11) -* working directory <1>: Source Directories. (line 55) -* X Windows: X11. (line 6) -* xref: Xref. (line 6) - - - -Tag Table: -Node: Top268 -Node: Introduction2914 -Node: Features5668 -Node: Current Features6494 -Node: New features9945 -Node: Credits29468 -Node: Manual33085 -Node: Installation35751 -Node: Installing from a third-party repository36688 -Node: Installing from source37635 -Node: Activating and Loading ESS39227 -Node: Check Installation40301 -Node: Interactive ESS40521 -Node: Starting up41366 -Node: Multiple ESS processes42110 -Node: ESS processes on Remote Computers43191 -Node: Customizing startup47294 -Node: Controlling buffer display50184 -Node: Entering commands52782 -Node: Command-line editing53940 -Node: Transcript55173 -Node: Last command56942 -Node: Process buffer motion58368 -Node: Transcript resubmit59871 -Node: Saving transcripts61836 -Node: Command History63626 -Node: Saving History67035 -Node: History expansion67796 -Node: Hot keys71007 -Node: Statistical Process running in ESS?75077 -Node: Emacsclient76356 -Node: Other77148 -Node: Evaluating code78167 -Node: Transcript Mode81848 -Node: Resubmit83001 -Node: Clean84064 -Node: Editing objects85060 -Node: Edit buffer86178 -Node: Loading88224 -Node: Error Checking89251 -Node: Indenting90300 -Node: Styles93342 -Node: Other edit buffer commands95716 -Node: Source Files97372 -Node: Source Directories101976 -Node: Help105129 -Node: Completion109573 -Node: Object names109788 -Node: Function arguments112422 -Node: Minibuffer completion113365 -Node: Company113839 -Node: Icicles114226 -Node: Developing with ESS115546 -Node: ESS tracebug115992 -Node: Getting started with tracebug118999 -Node: Editing documentation121157 -Node: R documentation files121707 -Node: Roxygen125409 -Node: Namespaced Evaluation129783 -Node: Extras131781 -Node: ESS ElDoc132805 -Node: ESS Flymake134301 -Node: Handy commands135395 -Node: Highlighting136592 -Node: Parens137627 -Node: Graphics138103 -Node: printer138774 -Node: X11139530 -Node: winjava139869 -Node: Imenu140281 -Node: Toolbar141128 -Node: Xref141536 -Node: Rdired141859 -Node: Package listing142922 -Node: Org144298 -Node: Sweave and AUCTeX145252 -Node: ESS for R147804 -Node: ESS(R)--Editing files148104 -Node: iESS(R)--Inferior ESS processes148605 -Node: Philosophies for using ESS(R)151255 -Node: Example ESS usage152182 -Node: ESS for SAS153587 -Node: ESS(SAS)--Design philosophy154310 -Node: ESS(SAS)--Editing files155243 -Node: ESS(SAS)--TAB key157097 -Node: ESS(SAS)--Batch SAS processes158463 -Node: ESS(SAS)--Function keys for batch processing163491 -Node: iESS(SAS)--Interactive SAS processes172978 -Node: iESS(SAS)--Common problems176732 -Node: ESS(SAS)--Graphics178255 -Node: ESS(SAS)--Windows179038 -Node: ESS for BUGS179616 -Node: ESS for JAGS181372 -Node: Mailing lists/bug reports184724 -Node: Bugs184988 -Node: Reporting Bugs186613 -Node: Mailing Lists187506 -Node: Help with Emacs188233 -Node: Customization188765 -Node: Indices189539 -Node: Key index189714 -Node: Function and program index194846 -Node: Variable index204266 -Node: Concept index207827 - -End Tag Table diff --git a/elpa/ess-20191014.1343/essd-els.el b/elpa/ess-20191014.1343/essd-els.el deleted file mode 100644 index 1ed6ef98..00000000 --- a/elpa/ess-20191014.1343/essd-els.el +++ /dev/null @@ -1,190 +0,0 @@ -;;; essd-els.el --- S-PLUS 3.x at another location customization -*- lexical-binding: t; -*- - -;; Copyright (C) 1998 Richard M. Heiberger -;; Copyright (C) 1999--2005 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Richard M. Heiberger -;; Created: December 1998 - -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This file defines all the S-PLUS 3.x customizations for ess-mode. - -;;; Code: - -(require 'ess-julia) -(require 'ess-s-lang) -(require 'ess-sp6-d) -(require 'ess-sas-d) -(require 'ess-stata-mode) -(require 'ess-trns) -(require 'ess-utils) - -;; Easily changeable in a user's .emacs -(defvar S+elsewhere-dialect-name "S+6" - "Name of 'dialect' for S-PLUS at another location.") - -(defvar S+elsewhere-start-args "-i" - "Arguments for `S+elsewhere-dialect-name'.") - -(defcustom inferior-ess-remote-pager nil - "Remote pager to use for reporting help files and similar things. -The default value is nil." - :group 'ess-proc - :type '(choice (const nil) string)) - - -(defvar S+elsewhere-customize-alist - (append - '((ess-local-customize-alist . 'S+elsewhere-customize-alist) - (ess-dialect . S+elsewhere-dialect-name) - (ess-object-name-db-file . "ess-spelsewhere-namedb.el" ) - (inferior-ess-program . inferior-S-elsewhere-program) - (inferior-ess-help-command . "help(\"%s\", pager=\"cat\", window=F)\n") - (ess-STERM . "iESS") - ) - S+common-cust-alist) - "Variables to customize for S+elsewhere.") - -(defun S+elsewhere (&optional _proc-name) - "Call 'S-PLUS 3.x', the 'Real Thing' from StatSci." - ;; git commit 104c4d7c56bc239ea245562763caa317bc3a1a84 - (declare (obsolete ess-remote "2000")) - (ess-write-to-dribble-buffer - (format "\n(S+elsewhere): ess-dialect=%s, buf=%s\n" ess-dialect - (current-buffer))) - (let ((inf-buf (inferior-ess nil S+elsewhere-customize-alist))) - (when inferior-ess-language-start - (ess-eval-linewise inferior-ess-language-start)) - inf-buf)) - -(defun S+elsewhere-mode (&optional _proc-name) - "Major mode for editing S+3 source. See `ess-mode' for more help." - (declare (obsolete ess-remote "2000")) - (setq-local ess-local-customize-alist S+elsewhere-customize-alist) - (ess-mode)) - -(define-obsolete-function-alias 'S+elsewhere-transcript-mode #'S-transcript-mode "2000") - -;; This REALLY shouldn't need an editing mode. Just a transcript and -;; an inferior process handler. - -(defun ess-select-alist-dialect (&optional dialect) - "Query user for an ESS DIALECT and return the matching customize-alist." - (interactive) - (let* ((dialects '("R" "S+" "julia" "arc" "vst" "omg" "s3" "s4" "stata" "sp3" "sp4" - "sqpe4" "sp5" "sqpe" "XLS" "SAS")) - (dialect (or dialect - (ess-completing-read "Dialect" dialects nil t)))) - (cond - ((string= dialect "julia") ess-julia-customize-alist) - ((string= dialect "stata") STA-customize-alist) - ((string= dialect "R") ess-r-customize-alist) - ((string= dialect "SAS") SAS-customize-alist) - (t S+elsewhere-customize-alist)))) - -(defun ess-add-ess-process () - "Execute this command from within a buffer running a process to add -the process to `ess-process-name-alist' and to make it the -`ess-current-process-name'. This command will normally be run in a -telnet buffer connected to another computer or in a shell or comint -buffer on the local computer." - (interactive) - (let ((proc (get-buffer-process (buffer-name)))) - (if (not proc) - (error "No process is associated with this buffer") - (set-process-filter proc 'inferior-ess-output-filter) - (setq ess-current-process-name (process-name proc)) - (add-to-list 'ess-process-name-list - (list ess-current-process-name))))) - -(defvar ess-remote nil - "Indicator, t in remote buffers.") - -;;;###autoload -(defun ess-remote (&optional proc-name dialect) - "Execute this command from within a buffer running a process. -It runs `ess-add-ess-process' to add the PROC-NAME to -`ess-process-name-alist' and to make it the -`ess-current-process-name'. It then prompts the user for an ESS -language and sets the editing characteristics appropriately. - -To use this command, first start a process on a remote computer by -manual use of telnet, rlogin, ssh, or some other protocol. Start the -relevant program (\"S\" or \"R\" or \"sas -stdio\") in that buffer. Once -you are talking to S or R or SAS, then do \\[ess-remote] to make -the current buffer an inferior-ess buffer with the right behavior for -the language you are currently working with. With S and R, use C-c -C-n to send lines over. With SAS, use C-c i -`ess-eval-line-and-step-invisibly' to send lines over invisibly. - -DIALECT is the desired ess-dialect. If nil, ask for dialect" - - (interactive) - (ess-add-ess-process) - ;; Need to select a remote-customize-alist - (let ((customize-alist (ess-select-alist-dialect dialect))) - (ess-write-to-dribble-buffer - (format "\n(ESS-remote): ess-dialect=%s, buf=%s\n" ess-dialect - (current-buffer))) - (ess-setq-vars-local customize-alist) - (inferior-ess--set-major-mode ess-dialect) - (setq-local ess-remote t) - (setq ess-local-process-name (or proc-name ess-current-process-name)) - - (goto-char (point-max)) - - (when (equal ess-dialect "R") - ;; ugly fix for evn variable. What can we do :( - (ess-eval-linewise (format "options(pager='%s')\n" - (or inferior-ess-remote-pager inferior-ess-pager)) - nil nil nil 'wait) - (ess-r-load-ESSR)) - - (when (equal ess-dialect "S+") - (ess-command ess-S+--injected-code)) - - (when (equal ess-language "SAS") - (font-lock-mode 0) - (SAS-log-mode) - (shell-mode) - (setq buffer-read-only nil) - (font-lock-mode 1)) - - (ess-process-put 'funargs-cache (make-hash-table :test 'equal)) - (ess-process-put 'funargs-pre-cache nil) - ;; auto-complete - (ess--setup-auto-complete ess-r-ac-sources t) - ;; company - (ess--setup-company ess-r-company-backends t) - - (when inferior-ess-language-start - (ess-eval-linewise inferior-ess-language-start - nil nil nil 'wait-prompt)))) - - - ; Provide package - -(provide 'essd-els) - -;;; essd-els.el ends here diff --git a/elpa/ess-20191014.1343/etc/ESSR.rds b/elpa/ess-20191014.1343/etc/ESSR.rds deleted file mode 100644 index 5fbb48fe..00000000 Binary files a/elpa/ess-20191014.1343/etc/ESSR.rds and /dev/null differ diff --git a/elpa/ess-20191014.1343/etc/ESSR/BUILDESSR b/elpa/ess-20191014.1343/etc/ESSR/BUILDESSR deleted file mode 100755 index 5fe79863..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/BUILDESSR +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/Rscript -## -*- mode: R -*- -## code to build ESSR environemnt. -## Assume that current directory is etc/ESSR -## run "./BUILDESSR" to create ../ESSR.rda - -## exactly as in inferior-ess-r-load-ESSR in ess-r-d.el -source('./R/.load.R', local=TRUE) -ESSR <- .ess.load.ESSR('./R/') -saveRDS(ESSR, file = "../ESSR.rds") diff --git a/elpa/ess-20191014.1343/etc/ESSR/LOADREMOTE b/elpa/ess-20191014.1343/etc/ESSR/LOADREMOTE deleted file mode 100644 index 919ec33f..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/LOADREMOTE +++ /dev/null @@ -1,24 +0,0 @@ -## -*- mode: R -*- -## loading code which is first sent to R on remote sessions -local({ - ver <- '%s' ## <- passed from elisp - root <- '~/.config/ESSR' - if(!file.exists(root)) - dir.create(root, recursive = TRUE) - ## cannot use sprintf here - essr_file <- file.path(root, paste('ESSRv', ver, '.rds', sep = '')) - tryCatch({ - if(!file.exists(essr_file)) { - url <- paste('https://github.com/emacs-ess/ESS/raw/ESSRv', ver, '/etc/ESSR.rds', sep = '') - utils::download.file(url, essr_file) - } - ESSR <- readRDS(essr_file) - ESSR[[".ess.Rversion"]] <- ESSR[[".ess.getRversion"]]() - attach(ESSR) - print(TRUE) - }, - error = function(e) { - print(e) - print(FALSE) - }) -}) diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/.basic.R b/elpa/ess-20191014.1343/etc/ESSR/R/.basic.R deleted file mode 100644 index 8ba5daf7..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/.basic.R +++ /dev/null @@ -1,134 +0,0 @@ -#### Essential functionality needed by ESS - -## Should work on *all* vesions of R. -## Do not use _ in names, nor :: , nor 1L etc, as they -## cannot be parsed in old R versions - -.ess.getRversion <- function() { - if(exists("getRversion", mode="function")) getRversion() - else paste(R.version$major, R.version$minor, sep=".") -} - -## loading ESSR.rda might fail, so re-assign here: -.ess.Rversion <- .ess.getRversion() - -.ess.R.has.utils <- (.ess.Rversion >= "1.9.0") -.ess.utils.name <- paste("package", - if(.ess.Rversion >= "1.9.0") "utils" else "base", - sep = ":") - -## Instead of modern utils::help use one that works in R 1.0.0: -.ess.findFUN <- get("find", .ess.utils.name) - - -### HELP -.ess.help <- function(..., help.type = getOption("help_type")) { - if (is.null(help.type)) { - help.type <- "text" - } - - ## - get("help", ..) searching in global env works with devtools redefines - ## - Redefining to .ess.help this way is necessary because - ## utils:::print.help_files_with_topic (used internally when there's - ## more than one a package) uses the quoted call - ## MM: don't understand; more specifically? - .ess.help <- function(...) { - do.call(get("help", envir = .GlobalEnv), list(...)) - } - - if (.ess.Rversion > "2.10") { - ## Abbreviating help_type to avoid underscore - .ess.help(..., help = help.type) - } else { - .ess.help(..., htmlhelp = help.type == "html") - } -} - -.ess.getHelpAliases <- function(){ - readrds <- - if(.ess.Rversion >= '2.13.0') readRDS - else .readRDS - rds.files <- paste(searchpaths(), "/help/aliases.rds", sep = "") - unlist(lapply(rds.files, - function(f){ - if( file.exists(f) ) - try(names(readrds(f))) - }), - use.names = FALSE) -} - -### SOURCING -.ess.eval <- function(string, visibly = TRUE, output = FALSE, - max.deparse.length = 300, - file = tempfile("ESS"), local = NULL) -{ - if (is.null(local)) { - local <- if (.ess.Rversion > '2.13') parent.frame() else FALSE - } - - ## create FILE, put string into it. Then source. - ## arguments are like in source and .ess.source - cat(string, file = file) - ## The following on.exit infloops in R 3.3.0 - ## https://github.com/emacs-ess/ESS/issues/334 - ## https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16971 - ## So we are cleanning it in .ess.source instead. - ## on.exit(file.remove(file)) - .ess.source(file, visibly = visibly, output = output, - max.deparse.length = max.deparse.length, - local = local, fake.source = TRUE) -} - -.ess.strip.error <- function(msg, srcfile) { - pattern <- paste0(srcfile, ":[0-9]+:[0-9]+: ") - sub(pattern, "", msg) -} - -.ess.file.remove <- function(file){ - if (base::file.exists(file)) base::file.remove(file) - else FALSE -} - -.ess.source <- function(file, visibly = TRUE, output = FALSE, - max.deparse.length = 300, local = NULL, - fake.source = FALSE, keep.source = TRUE, - message.prefix = "") { - if (is.null(local)) { - local <- if (.ess.Rversion > "2.13") - parent.frame() - else FALSE - } - - ss <- - if (.ess.Rversion >= "3.4") - base::source - else if (.ess.Rversion >= "2.8") - function(..., spaced) base::source(...) - else function(..., spaced, keep.source) base::source(...) - - on.exit({ - if (fake.source) - .ess.file.remove(file) - }) - - out <- ss(file, echo = visibly, local = local, print.eval = output, spaced = FALSE, - max.deparse.length = max.deparse.length, keep.source = keep.source) - - if(!fake.source) - cat(sprintf("%sSourced file %s\n", message.prefix, file)) - - ## Return value for org-babel - invisible(out$value) -} - -if(.ess.Rversion < "1.8") - ## (works for "1.7.2"): bquote() was new in 1.8.0 - bquote <- function(expr, where=parent.frame()){ - unquote <- function(e) - if (is.pairlist(e)) as.pairlist(lapply(e, unquote)) - else if (length(e) <= 1) e - else if (e[[1]] == as.name(".")) eval(e[[2]], where) - else as.call(lapply(e, unquote)) - - unquote(substitute(expr)) - } diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/.load.R b/elpa/ess-20191014.1343/etc/ESSR/R/.load.R deleted file mode 100644 index e1c64e88..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/.load.R +++ /dev/null @@ -1,53 +0,0 @@ -## This file is sourced when R starts and `load.ESSR` is called. See -## inferior-ess-r-load-ESSR--local. -## Do not use _ in names, nor :: as they cannot be parsed in old R versions - -## load .base.R and all other files into ESSR environment; then attach ESSR -.ess.load.ESSR <- function(dir) { - .source <- - if(any("keep.source" == names(formals(sys.source)))) - sys.source - else - function(..., keep.source) sys.source(...) - - Rver <- if(exists("getRversion", mode="function")) getRversion() - else paste(R.version$major, R.version$minor, sep=".") - oldR <- Rver <= "1.3.0" - - ESSR <- - if(oldR) ## really old library() revert order a bit - attach(NULL, name = "ESSR") - else if(length(nn <- names(formals(new.env))) && any(nn == "parent")) - new.env(parent = - if(Rver >= "1.9.0") getNamespace("utils") - else .BaseNamespaceEnv) - else - new.env() - - assign(".ess.Rversion", Rver, envir = ESSR) - - ## updated by make !! - VERSION <- "1.5" - assign(".ess.ESSRversion", VERSION, envir = ESSR) - - - ## .basic.R: - try(.source(paste(dir,'/.basic.R', sep = ""), envir = ESSR, keep.source = FALSE)) - - ## all others try(*) as it will fail in old R - if(!oldR) # no sense if(oldR) - for( f in dir(dir, pattern='\\.R$', full.names=TRUE) ) - try(.source(f, envir = ESSR, keep.source = FALSE)) - - if(Rver >= "2.4.0") - attach(ESSR) - else if(!oldR) { ## borrow from older library() - e <- attach(NULL, name = "ESSR") - .Internal(lib.fixup(ESSR, e)) - } else { ## if(oldR), use as in that old library(): - .Internal(lib.fixup(ESSR, .GlobalEnv)) - } - - ## BUILDESSR needs this: - invisible(ESSR) -} diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/completion.R b/elpa/ess-20191014.1343/etc/ESSR/R/completion.R deleted file mode 100644 index 2a2acc06..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/completion.R +++ /dev/null @@ -1,167 +0,0 @@ -## Do *NOT* use 1L -- it gives parse errors in historical versions of R - -## Try a setup working in as old R as possible. -## ===> -## 1) do not use "_" in names! --- seems impossible for the Millenials .. -## 2) use our own simplified definition of '::' and ':::' ? -## -if(!exists("local")) - local <- function(expr, envir = environment()) { invisible(eval(expr, envir=envir)) } - -##' Robust version of -##' utils:::.addFunctionInfo(c = c("recursive", "use.names")) -local({ - U <- asNamespace("utils"); fn <- ".addFunctionInfo" - EX <- exists(fn, envir=U) - if(EX && is.function(FN <- get(fn, envir=U))) { - FN(c = c("recursive", "use.names")); ##dbg: cat("Calling utils:::",fn,"(c = ...)\n") - } -}) - - -.ess_eval <- function(str, env = globalenv()) { - ## don't remove; really need eval(parse( here!! - tryCatch(base::eval(base::parse(text=str), envir = env), - error=function(e) NULL) ## also works for special objects containing @:$ etc -} - -.ess_nonull <- function(x, default = "") { - if (is.null(x)) default - else x -} - -.ess_srcref <- function(name, pkg) { - if (!is.null(pkg) && requireNamespace(pkg)) { - env <- asNamespace(pkg) - } else { - env <- globalenv() - } - fn <- .ess_eval(name, env) - out <- "()\n" - if (is.function(fn) && !is.null(utils::getSrcref(fn))) { - file <- utils::getSrcFilename(fn, full.names = TRUE) - if (file != "") { - line <- .ess_nonull(utils::getSrcLocation(fn, "line"), 1) - col <- .ess_nonull(utils::getSrcLocation(fn, "column"), 1) - out <- sprintf("(\"%s\" %d %d)\n", file, line, col - 1) - } - } - cat(out) -} - - -.ess_fn_pkg <- function(fn_name) { - fn <- .ess_eval(fn_name) - env_name <- base::environmentName(base::environment(fn)) - out <- if (base::is.primitive(fn)) { # environment() does not work on primitives. - "base" - } else if (base::is.function(fn) && env_name != "R_GlobalEnv") { - env_name - } else { - "" - } - base::cat(base::sprintf("%s\n", out)) -} - -.ess_funargs <- function(funname) { - if(.ess.Rversion > '2.14.1') { - ## temporarily disable JIT compilation and errors - comp <- compiler::enableJIT(0) - op <- options(error=NULL) - on.exit({ options(op); compiler::enableJIT(comp) }) - } - fun <- .ess_eval(funname) - if(is.function(fun)) { - special <- grepl('[:$@[]', funname) - args <- if(!special){ - fundef <- paste(funname, '.default',sep='') - do.call('argsAnywhere', list(fundef)) - } - - if(is.null(args)) - args <- args(fun) - if(is.null(args)) - args <- do.call('argsAnywhere', list(funname)) - - fmls <- formals(args) - fmls_names <- names(fmls) - fmls <- gsub('\"', '\\\"', - gsub("\\", "\\\\", as.character(fmls), fixed = TRUE), - fixed=TRUE) - args_alist <- - sprintf("'(%s)", - paste("(\"", fmls_names, "\" . \"", fmls, "\")", - sep = '', collapse = ' ')) - allargs <- - if (special) fmls_names - else tryCatch(gsub(' ?= ?', '', utils:::functionArgs(funname, ''), fixed = FALSE), - error=function(e) NULL) - allargs <- sprintf("'(\"%s\")", - paste(allargs, collapse = '\" "')) - envname <- - if (is.primitive(fun)) "base" - else environmentName(environment(fun)) - if (envname == "R_GlobalEnv") envname <- "" - cat(sprintf('(list \"%s\" %s %s)\n', - envname, args_alist, allargs)) - } -} - - -.ess_get_completions <- function(string, end, suffix = " = ") { - oldopts <- utils::rc.options(funarg.suffix = suffix) - on.exit(utils::rc.options(oldopts)) - if(.ess.Rversion > '2.14.1'){ - comp <- compiler::enableJIT(0) - op <- options(error=NULL) - on.exit({ options(op); compiler::enableJIT(comp)}, add = TRUE) - } - utils:::.assignLinebuffer(string) - utils:::.assignEnd(end) - utils:::.guessTokenFromLine() - utils:::.completeToken() - c(get('token', envir=utils:::.CompletionEnv), - utils:::.retrieveCompletions()) -} - -.ess_arg_help <- function(arg, func){ - op <- options(error=NULL) - on.exit(options(op)) - fguess <- - if(is.null(func)) get('fguess', envir=utils:::.CompletionEnv) - else func - findArgHelp <- function(fun, arg){ - file <- help(fun, try.all.packages=FALSE)[[1]] - hlp <- utils:::.getHelpFile(file) - id <- grep('arguments', tools:::RdTags(hlp), fixed=TRUE) - if(length(id)){ - arg_section <- hlp[[id[[1]]]] - items <- grep('item', tools:::RdTags(arg_section), fixed=TRUE) - ## cat('items:', items, fill=TRUE) - if(length(items)){ - arg_section <- arg_section[items] - args <- unlist(lapply(arg_section, - function(el) paste(unlist(el[[1]][[1]], TRUE, FALSE), collapse=''))) - fits <- grep(arg, args, fixed=TRUE) - ## cat('args', args, 'fits', fill=TRUE) - if(length(fits)) - paste(unlist(arg_section[[fits[1]]][[2]], TRUE, FALSE), collapse='') - } - } - } - funcs <- c(fguess, tryCatch(methods(fguess), - warning=function(w) {NULL}, - error=function(e) {NULL})) - if(length(funcs) > 1 && length(pos <- grep('default', funcs))){ - funcs <- c(funcs[[pos[[1]]]], funcs[-pos[[1]]]) - } - i <- 1; found <- FALSE - out <- 'No help found' - while(i <= length(funcs) && is.null(out <- - tryCatch(findArgHelp(funcs[[i]], arg), - warning=function(w) {NULL}, - error=function(e) {NULL}) - )) - i <- i + 1 - cat('\n\n', as.character(out), '\n') -} diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/debug.R b/elpa/ess-20191014.1343/etc/ESSR/R/debug.R deleted file mode 100644 index a4fcf638..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/debug.R +++ /dev/null @@ -1,227 +0,0 @@ -### BREAKPOINTS -.ESSBP. <- new.env() - -### DEBUG/UNDEBUG -.ess_find_funcs <- function(env) { - objs <- ls(envir = env, all.names = TRUE) - if (length(objs) > 0) - objs <- objs[sapply(objs, exists, envir = env, - mode = 'function', inherits = FALSE)] - objs -} - -.ess_all_functions <- function(packages = c(), env = NULL) { - if(is.null(env)) - env <- parent.frame() - empty <- emptyenv() - coll <- list() - for(p in packages){ - ## package might not be attached - try( - { - objNS <- .ess_find_funcs(asNamespace(p)) - objPKG <- .ess_find_funcs(as.environment(paste0('package:', p))) - objNS <- setdiff(objNS, objPKG) - if(length(objPKG)) - coll[[length(coll) + 1]] <- paste0(p, ':::', objNS) - }, silent = TRUE) - } - while(!identical(empty, env)){ - coll[[length(coll) + 1]] <- .ess_find_funcs(env) - env <- parent.env(env) - } - grep('^\\.ess', unlist(coll, use.names = FALSE), - invert = TRUE, value = TRUE) -} - - -.ess_dbg_flag_for_debuging <- function(fname){ - all <- utils::getAnywhere(fname) - if(length(all$obj) == 0){ - msg <- sprintf("No functions names '%s' found", fname) - } else { - msg <- sprintf("Flagged '%s' for debugging", fname) - tryCatch(lapply(all$obj, debug), - error = function(e){ - msg <- paste0("Error: ", e$message) - }) - } - cat(msg) - .ess_mpi_message(msg) -} - -.ess_dbg_getTracedAndDebugged <- function() -{ - packages <- base::.packages() - tr_state <- tracingState(FALSE) - on.exit(tracingState(tr_state)) - generics <- methods::getGenerics() - all_traced <- c() - for(i in seq_along(generics)){ - genf <- methods::getGeneric(generics[[i]], - package=generics@package[[i]]) - if(!is.null(genf)){ ## might happen !! v.2.13 - menv <- methods::getMethodsForDispatch(genf) - traced <- unlist(eapply(menv, is, 'traceable', all.names=TRUE)) - if(length(traced) && any(traced)) - all_traced <- c(paste(generics[[i]],':', - names(traced)[traced],sep=''), all_traced) - tfn <- getFunction(generics[[i]], mustFind=FALSE, where = .GlobalEnv) - if(!is.null(tfn ) && is(tfn, 'traceable')) # if the default is traced, it does not appear in the menv :() - all_traced <- c(generics[[i]], all_traced) - } - } - debugged_pkg <- unlist(lapply(packages, function(pkgname){ - ns <- asNamespace(pkgname) - funcs <- .ess_find_funcs(ns) - dbged <- funcs[unlist(lapply(funcs, - function(f){ - isdebugged(get(f, envir = ns, inherits = FALSE)) - }))] - if(length(dbged)) - paste0(pkgname, ':::`', dbged, '`') - })) - env <- parent.frame() - ## traced function don't appear here. Not realy needed and would affect performance. - all <- .ess_all_functions(packages = packages, env = env) - which_deb <- lapply(all, function(nm){ - ## if isdebugged is called with string it doess find - tryCatch(isdebugged(get(nm, envir = env)), - error = function(e) FALSE) - ## try(eval(substitute(isdebugged(nm), list(nm = as.name(nm)))), silent = T) - }) - debugged <- all[which(unlist(which_deb, recursive=FALSE, use.names=FALSE))] - unique(c(debugged_pkg, debugged, all_traced)) -} - - -.ess_dbg_UntraceOrUndebug <- function(name, env = parent.frame()) { - tr_state <- tracingState(FALSE) - on.exit(tracingState(tr_state)) - if( grepl('::', name) ){ - ## foo:::bar name - eval(parse(text = sprintf('undebug(%s)', name))) - }else{ - ## name is a name of a function to be undebugged or has a form - ## name:Class1#Class2#Class3 for traced methods - name <- strsplit(name, ':', fixed = TRUE)[[1]] - if( length(name)>1 ){ - ## a method - fun <- name[[1]] - sig <- strsplit(paste(name[-1], collapse=''), '#', fixed=TRUE)[[1]] - untrace(fun, signature = sig) - }else{ - ## function - if( is(getFunction(name, where = parent.frame()), 'traceable') ) - untrace(name) - else if(grepl(":", name)) - undebug(name) - else - undebug(get(name, envir = env)) - }} -} - -.ess_dbg_UndebugALL <- function(funcs) -{ - tr_state <- tracingState(FALSE) - on.exit(tracingState(tr_state)) - env <- parent.frame() - invisible(lapply(funcs, function( nm ) { - ## ugly tryCatch, but there might be several names pointing to the - ## same function, like foo:::bar and bar. An alternative would be - ## to call .ess_dbg_getTracedAndDebugged each time but that might - ## be ery slow - try(.ess_dbg_UntraceOrUndebug(nm, env = env), TRUE) - })) -} - - -### WATCH -.ess_watch_expressions <- list() - -.ess_watch_eval <- function() -{ - env <- as.environment("ESSR") - exps <- get('.ess_watch_expressions', envir = env) - if(length(exps) == 0) { - ## using old style so this can be parsed by R 1.9.1 (e.g): - cat('\n# Watch list is empty!\n', - '# a append new expression', - '# i insert new expression', - '# k kill', - '# e edit the expression', - '# r rename', - '# n/p navigate', - '# u/d,U move the expression up/down', - '# q kill the buffer', - sep="\n") - } else { - .parent_frame <- parent.frame() - .essWEnames <- allNames(exps) - len0p <- !nzchar(.essWEnames) - .essWEnames[len0p] <- seq_along(len0p)[len0p] - for(i in seq_along(exps)) { - cat('\n@---- ', .essWEnames[[i]], ' ', - rep.int('-', max(0, 35 - nchar(.essWEnames[[i]]))), '-@\n', sep = '') - cat(paste('@---:', deparse(exps[[i]][[1]])), ' \n', sep = '') - tryCatch(print(eval(exps[[i]], - envir = .parent_frame)), - error = function(e) cat('Error:', e$message, '\n' ), - warning = function(w) cat('warning: ', w$message, '\n' )) - } - } -} - - -.ess_watch_assign_expressions <- function(elist) { - assign(".ess_watch_expressions", elist, envir = as.environment("ESSR")) -} - -.ess_log_eval <- function(log_name) { - env <- as.environment("ESSR") - if(!exists(log_name, envir = env, inherits = FALSE)) - assign(log_name, list(), envir = env) - log <- get(log_name, envir = env, inherits = FALSE) - .essWEnames <- allNames(.ess_watch_expressions) - cur_log <- list() - .parent_frame <- parent.frame() - for(i in seq_along(.ess_watch_expressions)) { - capture.output( { - cur_log[[i]] <- - tryCatch(eval(.ess_watch_expressions[[i]]), - envir = .parent_frame, - error = function(e) paste('Error:', e$message, '\n'), - warning = function(w) paste('warning: ', w$message, '\n')) - if(is.null(cur_log[i][[1]])) - cur_log[i] <- list(NULL) - }) - } - names(cur_log) <- .essWEnames - assign(log_name, c(log, list(cur_log)), envir = env) - invisible(NULL) -} - - -.ess_package_attached <- function(pack_name){ - as.logical(match(paste0("package:", pack_name), search())) -} - -## magrittr debug_pipe -.ess_pipe_browser <- function(x){ - if(is.list(x)) - evalq({ - browser(skipCalls = 2) - x - }, envir = x) - else if(is.environment(x)) - ## enclos argumentn has no effect for unclear reason, need to hack - eval(bquote({ - x <- .(environment()) - browser(skipCalls = 2) - x - }), envir = x) - else { - browser(skipCalls = 0) - x - } -} diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/misc.R b/elpa/ess-20191014.1343/etc/ESSR/R/misc.R deleted file mode 100644 index e3bba966..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/misc.R +++ /dev/null @@ -1,143 +0,0 @@ -.ess_weave <- function(command, file, encoding = NULL){ - cmd_symb <- substitute(command) - if (grepl('knit|purl', deparse(cmd_symb))) require(knitr) - od <- getwd() - on.exit(setwd(od)) - setwd(dirname(file)) - frame <- parent.frame() - if (is.null(encoding)) - eval(bquote(.(cmd_symb)(.(file))), envir = frame) - else - eval(bquote(.(cmd_symb)(.(file), encoding = .(encoding))), envir = frame) -} - -.ess_knit <- function(file, output = NULL){ - library(knitr) - frame <- parent.frame() - od <- getwd() - on.exit(setwd(od)) - setwd(dirname(file)) - ## this bquote is really needed for data.table := operator to work correctly - eval(bquote(knit(.(file), output = .(output))), envir = frame) -} - - -.ess_sweave <- function(file, output = NULL){ - od <- getwd() - frame <- parent.frame() - on.exit(setwd(od)) - setwd(dirname(file)) - eval(bquote(Sweave(.(file), output = .(output))), envir = frame) -} - -## Users might find it useful. So don't prefix with .ess. -.ess_htsummary <- function(x, hlength = 4, tlength = 4, digits = 3) { - ## fixme: simplify and generalize - snames <- c("mean", "sd", "min", "max", "nlev", "NAs") - d <- " " - num_sumr <- function(x){ - c(f(mean(x, na.rm = TRUE)), - f(sd(x, na.rm = TRUE)), - f(min(x, na.rm = TRUE)), - f(max(x, na.rm = TRUE)), - d, - f(sum(is.na(x), na.rm = TRUE))) - } - f <- function(x) format(x, digits = digits) - - if (is.data.frame(x) | is.matrix(x)) { - if (nrow(x) <= tlength + hlength){ - print(x) - } else { - if (is.matrix(x)) - x <- data.frame(unclass(x)) - ## conversion needed, to avoid problems with derived classes suchs - ## as data.table - h <- as.data.frame(head(x, hlength)) - t <- as.data.frame(tail(x, tlength)) - for (i in 1:ncol(x)) { - h[[i]] <- f(h[[i]]) - t[[i]] <- f(t[[i]]) - } - ## summaries - sumr <- sapply(x, function(c){ - if (is.logical(c)) - ## treat logical as numeric; it's harmless - c <- as.integer(c) - if (is.numeric(c)) - num_sumr(c) - else if (is.factor(c)) c(d, d, d, d, nlevels(c), sum(is.na(c))) - else rep.int(d, length(snames)) - }) - sumr <- as.data.frame(sumr) - row.names(sumr) <- snames - dots <- rep("...", ncol(x)) - empty <- rep.int(" ", ncol(x)) - lines <- rep.int(" ", ncol(x)) - df <- rbind(h, ... = dots, t, `_____` = lines, sumr, ` ` = empty) - print(df) - } - } else { - cat("head(", hlength, "):\n", sep = "") - print(head(x, hlength)) - if (length(x) > tlength + hlength){ - cat("\ntail(", tlength, "):\n", sep = "") - print(tail(x, tlength)) - } - cat("_____\n") - if (is.numeric(x) || is.logical(x)) - print(structure(num_sumr(x), names = snames), quote = FALSE) - else if (is.factor(x)){ - cat("NAs: ", sum(is.na(x), na.rm = TRUE), "\n") - cat("levels: \n") - print(levels(x)) - } - } - invisible(NULL) -} - - -.ess_vignettes <- function(all=FALSE) { - vs <- unclass(browseVignettes(all = all)) - vs <- vs[sapply(vs, length) > 0] - - mat2elist <- function(mat) { - if (!is.null(dim(mat))){ - apply(mat, 1, function(r) - sprintf("(list \"%s\")", - paste0(gsub("\"", "\\\\\"", - as.vector(r[c("Title", "Dir", "PDF", - "File", "R")])), - collapse = "\" \""))) - } - } - cat("(list \n", - paste0(mapply(function(el, name) { - sprintf("(list \"%s\" %s)", - name, paste0(mat2elist(el), collapse = "\n")) - }, - vs, names(vs)), collapse = "\n"), ")\n") -} - -.ess_Rd2txt <- function(rd) { - fun <- tools::Rd2txt - if (length(formals(fun)["stages"]))# newer R version - fun(rd, stages = c("build", "install", "render")) - else - fun(rd) -} - -## Hacked help.start() to use with ess-rutils.el -.ess_help_start <- function(update=FALSE, remote=NULL) { - home <- if (is.null(remote)) { - port <- tools::startDynamicHelp(NA) - if (port > 0L) { - if (update) - make.packages.html(temp=TRUE) - paste0("http://127.0.0.1:", port) - } - else stop(".ess_help_start() requires the HTTP server to be running", - call.=FALSE) - } else remote - paste0(home, "/doc/html/index.html") -} diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/mpi.R b/elpa/ess-20191014.1343/etc/ESSR/R/mpi.R deleted file mode 100644 index 53d7e470..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/mpi.R +++ /dev/null @@ -1,28 +0,0 @@ -## simple Message Parsing Inerface - -.ess_mpi_send <- function(head, ...){ - dots <- lapply(list(...), function(el) { - if (is.null(el)) "nil" - else if (is.logical(el)) {if (el) "t" else "nil"} - else as.character(el) - }) - payload <- paste(dots, collapse = "") - cat(sprintf("_%s%s\\", head, payload)) -} - -.ess_mpi_message <- function(msg){ - .ess_mpi_send("message", msg) -} - -.ess_mpi_y_or_n <- function(prompt, callback = NULL){ - .ess_mpi_send("y-or-n", prompt, callback) -} - -.ess_mpi_eval <- function(expr, callback = NULL){ - .ess_mpi_send("eval", expr, callback) -} - -.ess_mpi_error <- function(msg) { - .ess_mpi_send("error", msg) -} - diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/ns-eval.R b/elpa/ess-20191014.1343/etc/ESSR/R/ns-eval.R deleted file mode 100644 index 83bbaec2..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/ns-eval.R +++ /dev/null @@ -1,421 +0,0 @@ -## NOTE ON S3 METHODS: New S3 methods are not automatically registered. You can -## register them manually after you have inserted method_name.my_class into your -## package environment using ess-developer, like follows: -## -## registerS3method("method_name", "my_class", my_package:::method_name.my_class) -## -## If an S3 methods already exists in a package, ESS-developer will do the right -## thing. - -## evaluate the STRING by saving into a file and calling .ess.ns_source -.ess.ns_eval <- function(string, visibly, output, package, - file = tempfile("ESSDev"), verbose = FALSE, - fallback_env = NULL, local_env = parent.frame()) { - cat(string, file = file) - on.exit(.ess.file.remove(file)) - .ess.ns_source(file, visibly, output, package = package, - verbose = verbose, fake.source = TRUE, - fallback_env = fallback_env, local_env = local_env) -} - - -##' Source FILE into an environment. After having a look at each new object in -##' the environment, decide what to do with it. Handles plain objects, -##' functions, existing S3 methods, S4 classes and methods. -##' @param fallback_env environment to assign objects which don't exist in the -##' package namespace -.ess.ns_source <- function(file, visibly, output, expr, - package = "", verbose = FALSE, - fake.source = FALSE, - fallback_env = NULL, - local_env = NULL) { - oldopts <- options(warn = 2) - on.exit(options(oldopts)) - pname <- paste("package:", package, sep = "") - envpkg <- tryCatch(as.environment(pname), error = function(cond) NULL) - if (is.null(envpkg)) - if (require(package, quietly = TRUE, character.only = TRUE)) { - envpkg <- tryCatch(as.environment(pname), error = function(cond) NULL) - } else { - ## no such package; source in current (local) user environment - return(.ess.source(file, visibly = visibly, - output = output, local = local_env, - fake.source = fake.source)) - } - - envns <- tryCatch(asNamespace(package), error = function(cond) NULL) - if (is.null(envns)) - stop(gettextf("Can't find a namespace environment corresponding to package name '%s\"", - package), domain = NA) - - ## Here we know that both envns and envpkg exists and are environments - if (is.null(fallback_env)) - fallback_env <- .ess.ns_insert_essenv(envns) - - ## Get all Imports envs where we propagate objects - pkgEnvNames <- Filter(.ess.is_package, search()) - packages <- lapply(pkgEnvNames, function(envName) substring(envName, 9)) - importsEnvs <- lapply(packages, function(pkgName) parent.env(asNamespace(pkgName))) - - ## Evaluate the FILE into new ENV - env <- .ess.ns_evalSource(file, visibly, output, substitute(expr), package, fake.source) - envPackage <- getPackageName(env, FALSE) - if (nzchar(envPackage) && envPackage != package) - warning(gettextf("Supplied package, %s, differs from package inferred from source, %s", - sQuote(package), sQuote(envPackage)), domain = NA) - - ## Get all sourced objects, methods and classes - allObjects <- objects(envir = env, all.names = TRUE) - allObjects <- allObjects[!(allObjects %in% c(".cacheOnAssign", ".packageName"))] - MetaPattern <- methods:::.TableMetaPattern() - ClassPattern <- methods:::.ClassMetaPattern() - allPlainObjects <- allObjects[!(grepl(MetaPattern, allObjects) | - grepl(ClassPattern, allObjects))] - allMethodTables <- allObjects[grepl(MetaPattern, allObjects)] - allClassDefs <- allObjects[grepl(ClassPattern, allObjects)] - - ## PLAIN OBJECTS and FUNCTIONS: - funcNs <- funcPkg <- newFunc <- newNs <- newObjects <- newPkg <- objectsNs <- objectsPkg <- character() - dependentPkgs <- list() - - for (this in allPlainObjects) { - thisEnv <- get(this, envir = env) - thisNs <- NULL - - ## NS - if (exists(this, envir = envns, inherits = FALSE)){ - thisNs <- get(this, envir = envns) - if(is.function(thisNs) || is.function(thisEnv)){ - if(is.function(thisNs) && is.function(thisEnv)){ - if(.ess.differs(thisEnv, thisNs)){ - environment(thisEnv) <- environment(thisNs) - .ess.assign(this, thisEnv, envns) - funcNs <- c(funcNs, this) - if(exists(".__S3MethodsTable__.", envir = envns, inherits = FALSE)){ - S3_table <- get(".__S3MethodsTable__.", envir = envns) - if(exists(this, envir = S3_table, inherits = FALSE)) - .ess.assign(this, thisEnv, S3_table) - } - } - }else{ - newNs <- c(newNs, this) - } - }else{ - if(!identical(thisEnv, thisNs)){ - .ess.assign(this, thisEnv, envns) - objectsNs <- c(objectsNs, this) - } - } - }else{ - newNs <- c(newNs, this) - } - - ## PKG - if (exists(this, envir = envpkg, inherits = FALSE)){ - thisPkg <- get(this, envir = envpkg) - if(is.function(thisPkg) || is.function(thisEnv)){ - if(is.function(thisPkg) && is.function(thisEnv)){ - if(.ess.differs(thisPkg, thisEnv)){ - environment(thisEnv) <- environment(thisPkg) - .ess.assign(this, thisEnv, envpkg) - funcPkg <- c(funcPkg, this) - } - }else{ - newPkg <- c(newPkg, this) - } - }else{ - if(!identical(thisPkg, thisEnv)){ - .ess.assign(this, thisEnv, envpkg) - objectsPkg <- c(objectsPkg, this) - } - } - }else{ - newPkg <- c(newPkg, this) - } - - if (!is.null(thisNs)) { - isDependent <- .ess.ns_propagate(thisEnv, this, importsEnvs) - newDeps <- stats::setNames(list(packages[isDependent]), this) - dependentPkgs <- c(dependentPkgs, newDeps) - } - } - - ## deal with new plain objects and functions - for (this in intersect(newPkg, newNs)) { - thisEnv <- get(this, envir = env, inherits = FALSE) - if (exists(this, envir = fallback_env, inherits = FALSE)){ - thisGl <- get(this, envir = fallback_env) - if (.ess.differs(thisEnv, thisGl)) { - if (is.function(thisEnv)) { - environment(thisEnv) <- envns - newFunc <- c(newFunc, this) - } else { - newObjects <- c(newObjects, this) - } - .ess.assign(this, thisEnv, fallback_env) - if (.is.essenv(fallback_env)) - .ess.assign(this, thisEnv, .GlobalEnv) - } - } else { - if (is.function(thisEnv)) { - environment(thisEnv) <- envns - newFunc <- c(newFunc, this) - } else { - newObjects <- c(newObjects, this) - } - .ess.assign(this, thisEnv, fallback_env) - if (.is.essenv(fallback_env)) - .ess.assign(this, thisEnv, .GlobalEnv) - } - } - - if(length(funcNs)) - objectsNs <- c(objectsNs, sprintf("FUN[%s]", paste(funcNs, collapse = ", "))) - if(length(funcPkg)) - objectsPkg <- c(objectsPkg, sprintf("FUN[%s]", paste(funcPkg, collapse = ", "))) - if(length(newFunc)) - newObjects <- c(newObjects, sprintf("FUN[%s]", paste(newFunc, collapse = ", "))) - - ## CLASSES - classesPkg <- classesNs <- newClasses <- character() - for(this in allClassDefs){ - newPkg <- newNs <- FALSE - thisEnv <- get(this, envir = env) - if(exists(this, envir = envpkg, inherits = FALSE)){ - if(!.ess.identicalClass(thisEnv, get(this, envir = envpkg))){ - .ess.assign(this, thisEnv, envir = envpkg) - classesPkg <- c(classesPkg, this) - } - }else{ - newPkg <- TRUE - } - if(exists(this, envir = envns, inherits = FALSE)){ - if(!.ess.identicalClass(thisEnv, get(this, envir = envns))){ - .ess.assign(this, thisEnv, envir = envns) - classesNs <- c(classesNs, this) - } - }else{ - newNs <- TRUE - } - if(newNs && newPkg){ - if(exists(this, envir = fallback_env, inherits = FALSE)){ - if(!.ess.identicalClass(thisEnv, get(this, envir = fallback_env))){ - .ess.assign(this, thisEnv, envir = fallback_env) - newClasses <- c(newClasses, this) - } - }else{ - .ess.assign(this, thisEnv, envir = fallback_env) - newClasses <- c(newClasses, this) - } - } - } - if(length(classesPkg)) - objectsPkg <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(classesPkg, collapse = ", "))) - if(length(classesNs)) - objectsNs <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(classesNs, collapse = ", "))) - if(length(newClasses)) - newObjects <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(newClasses, collapse = ", "))) - - ## METHODS: - ## Method internals: For efficiency reasons setMethod() caches - ## method definition into a global table which you can get with - ## 'getMethodsForDispatch' function, and when a method is dispatched that - ## table is used. When ess-developer is used to source method definitions the - ## two copies of the functions are identical up to the environment. The - ## environment of the cached object has namespace:foo as it's parent but the - ## environment of the object in local table is precisely namspace:foo. This - ## does not cause any difference in evaluation. - methodNames <- allMethodTables - methods <- sub(methods:::.TableMetaPrefix(), "", methodNames) - methods <- sub(":.*", "", methods) - methodsNs <- newMethods <- character() - for (i in seq_along(methods)){ - table <- methodNames[[i]] - tableEnv <- get(table, envir = env) - if(exists(table, envir = envns, inherits = FALSE)){ - inserted <- .ess.ns_insertMethods(tableEnv, get(table, envir = envns), envns) - if(length(inserted)) - methodsNs <- c(methodsNs, gettextf("%s{%s}", methods[[i]], paste(inserted, collapse = ", "))) - }else if(exists(table, envir = fallback_env, inherits = FALSE)){ - inserted <- .ess.ns_insertMethods(tableEnv, get(table, envir = fallback_env), envns) - if(length(inserted)) - newMethods <- c(newMethods, gettextf("%s{%s}", methods[[i]], paste(inserted, collapse = ", "))) - }else{ - .ess.assign(table, tableEnv, envir = fallback_env) - newMethods <- c(newMethods, gettextf("%s{%s}", methods[[i]], paste(objects(envir = tableEnv, all.names = T), collapse = ", "))) - } - } - if(length(methodsNs)) - objectsNs <- c(objectsNs, gettextf("METH[%s]", paste(methodsNs, collapse = ", "))) - if(length(newMethods)) - newObjects <- c(newObjects, gettextf("METH[%s]", paste(newMethods, collapse = ", "))) - - if (verbose) { - msgs <- unlist(list( - if(length(objectsPkg)) - sprintf("PKG: %s", paste(objectsPkg, collapse = ", ")), - if(length(objectsNs)) - sprintf("NS: %s", paste(objectsNs, collapse = ", ")), - if(length(dependentPkgs)) - .ess.ns_format_deps(dependentPkgs), - if(length(newObjects)) { - env_name <- .ess.ns_env_name(fallback_env) - sprintf("%s: %s", env_name, paste(newObjects, collapse = ", ")) - })) - if(length(msgs)) - .ess_mpi_message(paste(msgs, collapse = " ")) - - } - - invisible(env) -} - - -.ess.ns_insertMethods <- function(tableEnv, tablePkg, envns) { - inserted <- character() - for(m in ls(envir = tableEnv, all.names = T)){ - if(exists(m, envir = tablePkg, inherits = FALSE)){ - thisEnv <- get(m, envir = tableEnv) - thisPkg <- get(m, envir = tablePkg) - if(is(thisEnv, "MethodDefinition") && is(thisPkg, "MethodDefinition") && - .ess.differs(thisEnv@.Data, thisPkg@.Data)){ - environment(thisEnv@.Data) <- envns - ## environment of cached method in getMethodsForDispatch table is still env - ## not a problem as such, but might confuse users - .ess.assign(m, thisEnv, tablePkg) - inserted <- c(inserted, m) - }}} - inserted -} - -## our version of R's evalSource -.ess.ns_evalSource <- function(file, visibly, output, expr, package = "", - fake.source = FALSE) { - envns <- tryCatch(asNamespace(package), error = function(cond) NULL) - if(is.null(envns)) - stop(gettextf("Package \"%s\" is not attached and no namespace found for it", - package), domain = NA) - env <- new.env(parent = envns) - env[[".packageName"]] <- package - methods:::setCacheOnAssign(env, TRUE) - if (missing(file)) - eval(expr, envir = env) - else if (is(file, "character")) - for (f in file) { - .ess.source(f, local = env, visibly = visibly, - output = output, keep.source = TRUE, - max.deparse.length = 300, - fake.source = fake.source, - message.prefix = sprintf("[%s] ", package)) - } - else stop(gettextf("Invalid file argument: got an object of class \"%s\"", - class(file)[[1]]), domain = NA) - env -} - - -.ess.assign <- function(x, value, envir) { - ## Cannot add bindings to locked environments - exists <- exists(x, envir = envir, inherits = FALSE) - if (exists && bindingIsLocked(x, envir)) { - unlockBinding(x, envir) - assign(x, value, envir = envir, inherits = FALSE) - op <- options(warn = -1) - on.exit(options(op)) - lockBinding(x, envir) - } else if (exists || !environmentIsLocked(envir)) { - assign(x, value, envir = envir, inherits = FALSE) - } else { - warning(sprintf("Cannot assign `%s` in locked environment", x), - call. = FALSE) - } - invisible(NULL) -} - -.ess.identicalClass <- function(cls1, cls2, printInfo = FALSE) { - slots1 <- slotNames(class(cls1)) - slots2 <- slotNames(class(cls2)) - if(identical(slots1, slots2)){ - vK <- grep("versionKey", slots1) - if(length(vK)) - slots1 <- slots2 <- slots1[-vK] - out <- sapply(slots1, function(nm) identical(slot(cls1, nm), slot(cls2, nm))) - if(printInfo) print(out) - all(out) - } -} - -.ess.differs <- function(f1, f2) { - if (is.function(f1) && is.function(f2)){ - !(identical(body(f1), body(f2)) && identical(args(f1), args(f2))) - }else - !identical(f1, f2) -} - - -.ess.is_package <- function(envName) { - isPkg <- identical(substring(envName, 0, 8), "package:") - isPkg && (envName != "package:base") -} - -.ess.ns_propagate <- function(obj, name, importsEnvs) { - containsObj <- vapply(importsEnvs, logical(1), FUN = function(envs) { - name %in% names(envs) - }) - - lapply(importsEnvs[containsObj], .ess.assign, - x = name, value = obj) - - containsObj -} - - -.ess.ns_format_deps <- function(dependentPkgs) { - pkgs <- unique(unlist(dependentPkgs, use.names = FALSE)) - - lapply(pkgs, function(pkg) { - isDep <- vapply(dependentPkgs, function(deps) pkg %in% deps, logical(1)) - pkgDependentObjs <- names(dependentPkgs[isDep]) - sprintf("DEP:%s [%s] ", pkg, paste(pkgDependentObjs, collapse = ", ")) - }) -} - -.ess.ns_env_name <- function(env) { - name <- environmentName(env) - name <- - if (name == "") "Local" - else if (grepl("^essenv:", name)) "NEW" - else name - name -} - - -.ess.ns_insert_essenv <- function(nsenv) { - if (is.character(nsenv)) - nsenv <- base::asNamespace(nsenv) - stopifnot(isNamespace(nsenv)) - if (identical(nsenv, .BaseNamespaceEnv)) - return(.GlobalEnv) - essenv_name <- sprintf("essenv:%s", environmentName(nsenv)) - nsenv_parent <- parent.env(nsenv) - if (environmentName(nsenv_parent) == essenv_name) { - return(nsenv_parent) - } - essenv <- new.env(parent = nsenv_parent) - essenv[[".__ESSENV__."]] <- TRUE - attr(essenv, "name") <- essenv_name - nssym <- ".__NAMESPACE__." - nssym_val <- get(nssym, envir = nsenv, inherits = FALSE) - unlockBinding(nssym, nsenv) - nsenv[[nssym]] <- NULL - on.exit({ - nsenv[[nssym]] <- nssym_val - lockBinding(nssym, nsenv) - }) - parent.env(nsenv) <- essenv - essenv -} - -.is.essenv <- function(env) { - exists(".__ESSENV__.", envir = env, inherits = FALSE) -} diff --git a/elpa/ess-20191014.1343/etc/ESSR/R/pkg.R b/elpa/ess-20191014.1343/etc/ESSR/R/pkg.R deleted file mode 100644 index ebd0463a..00000000 --- a/elpa/ess-20191014.1343/etc/ESSR/R/pkg.R +++ /dev/null @@ -1,26 +0,0 @@ - -.ess_keep <- function(.x, .f, ...) { - is_true <- vapply(.x, .f, logical(1), ...) - .x[is_true] -} - -.ess_devtools_functions <- function() { - if (!requireNamespace("devtools")) { - .ess_mpi_error("devtools is not installed") - stop("internal error") - } - devtools_env <- asNamespace("devtools") - exports <- getNamespaceExports("devtools") - funs_exported <- as.list(devtools_env)[exports] - - is_first_arg <- function(f, arg) { - args <- names(formals(f)) - length(args) && args[[1]] == arg - } - - funs_pkg <- .ess_keep(funs_exported, is.function) - funs_pkg <- .ess_keep(funs_pkg, is_first_arg, "pkg") - funs_names <- sort(names(funs_pkg)) - - funs_names -} diff --git a/elpa/ess-20191014.1343/etc/Makefile b/elpa/ess-20191014.1343/etc/Makefile deleted file mode 100644 index e2d22768..00000000 --- a/elpa/ess-20191014.1343/etc/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -### Makefile - for scripts and icons (./etc) of ESS distribution. -### - -## Before making changes here, please take a look at Makeconf -include ../Makeconf - -#ETCFILES = $(wildcard BACKBUG[S5].BAT backbug[s5] *.S sas-keys.*) -#ETCFILES = ESSR.R ess-developer.R SVN-REVISION *.S sas-keys.* ess-sas-sh-command -# ETCFILES_1 = *.S sas-keys.* ess-sas-sh-command *.jl -ETCFILES_1 = ess-sas-sh-command *.jl -isRELEASE=$(shell test -f .IS.RELEASE && echo 'yes') -ifeq ($(isRELEASE),yes) - ETCFILES = .IS.RELEASE git-ref $(ETCFILES_1) -else - ETCFILES = $(ETCFILES_1) -endif - -#ICONS = $(wildcard icons/*.xpm) -ICONS = icons/*.xpm - -ESSR_UTIL_FILES = ESSR/LOADREMOTE -ESSR_CODE_FILES = ESSR/R/*.R ESSR/R/.*.R - -all: - -show-etc: - @echo $(ETCFILES) - ls -l $(ETCFILES) - -install : - $(INSTALLDIR) $(ETCDIR)/icons - $(INSTALLDIR) $(ETCDIR)/ESSR/R - $(INSTALL) $(ETCFILES) $(ETCDIR) - $(INSTALL) $(ICONS) $(ETCDIR)/icons - $(INSTALL) $(ESSR_UTIL_FILES) $(ETCDIR)/ESSR - $(INSTALL) $(ESSR_CODE_FILES) $(ETCDIR)/ESSR/R - chmod +x $(ETCDIR)/ess-sas-sh-command - -uninstall : - -cd $(ETCDIR) && $(UNINSTALL) $(ETCFILES) - -cd $(ETCDIR) && $(UNINSTALL) $(ICONS) - -cd $(ETCDIR) && $(UNINSTALL) $(ESSR_UTIL_FILES) - -cd $(ETCDIR) && $(UNINSTALL) $(ESSR_CODE_FILES) - - - -## 'clean' shall remove *exactly* those things that are *not* in version control -clean distclean: - rm -rf SVN-REVISION -## 'distclean' removes also things in VC (svn, when they are remade by "make"): -# distclean: clean -# rm -rf ESSR_*.tar.gz diff --git a/elpa/ess-20191014.1343/etc/ess-julia.jl b/elpa/ess-20191014.1343/etc/ess-julia.jl deleted file mode 100644 index efa1ce0c..00000000 --- a/elpa/ess-20191014.1343/etc/ess-julia.jl +++ /dev/null @@ -1,126 +0,0 @@ -module ESS - -# These methods have been deprecated / moved -macro current_module() - return VERSION >= v"0.7-" ? :(@__MODULE__) : :(current_module()) -end - -parse = VERSION >= v"0.7-" ? Base.Meta.parse : Base.parse -function_module = VERSION >= v"0.7-" ? Base.parentmodule : Base.function_module - -function all_help_topics() - ## There are not clear topics anymore. Approximate those with a very general - ## apropos(" ") - Base.Docs.apropos(" ") -end - -function help(topic::AbstractString) - if (VERSION >= v"1.0-") - Core.eval(parentmodule(ESS), parse("@doc $topic")) - elseif (VERSION >= v"0.4-") - Core.eval(@current_module(), parse("@doc $topic")) - else - Base.Help.help(topic) - end -end - -## modified version of function show(io::IO, m::Method) -function fun_args(m::Method) - tv, decls, file, line = Base.arg_decl_parts(m) - io = VERSION >= v"0.7-" ? Base.stdout : STDOUT::IO # STDOUT is no longer in 1.0 - if !isempty(tv) - Base.show_delim_array(io, tv, '{', ',', '}', false) - end - print(io, "(") - join(io, [escape_string(isempty(d[2]) ? d[1] : d[1]*"::"*d[2]) for d in decls], - ",", ",") - Base.print(io, ")") -end - -## modified versionof show(io::IO, mt::MethodTable) -function fun_args(f::Function) - mt = Base.MethodList(methods(f).mt) - mod = function_module(f) # Base.function_module deprecated in 0.7 - if mod == Main - mod = "nil" - end - print("(list \"$mod\" nil '(") - for d in mt - print("\"") - ## method - fun_args(d) - print("\" ") - end - print("))") -end - -function fun_args(s::AbstractString) - try - mod = VERSION >= v"1.0-" ? parentmodule(ESS) : @current_module() - m = Core.eval(mod, parse(s)) - if ! isa(m, String) - fun_args(m) - end - catch - print("(list nil nil nil)") - end -end - -function fun_args(t::DataType) - print("(list nil nil '(") - for d = fieldnames(t) - print("\"$d\" ") - end - print("))") -end - - -### OBJECT COMPLETION -# Must print an output of the form: -# -# Cache Module -# Write Module -# add Function -# free Function -function components(m::Module) - for v in sort(names(m, all=true, imported=true)) - s = string(v) - if !startswith(s, "#") && isdefined(m,v) - println(rpad(s, 30), summary(Core.eval(m,v))) - end - end -end - -function components(t::DataType) - for v in sort(fieldnames(t)) - println(rpad(string(v), 30), "field") - end -end - -function components(v) - t = typeof(v) - if isa(t, DataType) - return components(t) - end -end - - -### MISC -function main_modules(m::Module) - for nm in names(m) - if isdefined(m, nm) - mod = Core.eval(m, nm) - if isa(mod, Module) - print("\"$nm\" ") - end - end - end -end - -if VERSION >= v"0.7-" - main_modules() = main_modules(Base.parentmodule(@current_module())) -else - main_modules() = main_modules(@current_module()) -end - -end diff --git a/elpa/ess-20191014.1343/etc/ess-sas-sh-command b/elpa/ess-20191014.1343/etc/ess-sas-sh-command deleted file mode 100755 index 7c1d9101..00000000 --- a/elpa/ess-20191014.1343/etc/ess-sas-sh-command +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh - -### (C) 1997, Richard M. Heiberger. -### This file is part of ESS. - -## This file is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2, or (at your option) -## any later version. - -## This file is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. - -## A copy of the GNU General Public License is available at -## https://www.r-project.org/Licenses/ - - -# For executing SAS, and running it in the proper manner for ESS -# (feeding output back into appropriate ESS buffers). - -#echo $0 $@ -#sas $1 2>$2 $3 - -set -x -stdout=$1 -stderr=$2 -shift 2 -set +x -echo sas \$stdout 2\>$stderr $@ -sas $stdout 2>$stderr $@ - -## From the SAS online tech support: -## -## Redirecting the SAS Log and Output under UNIX. -## -## There are several ways of redirecting the SAS Log and Output under -## UNIX. -## -## To redirect the SAS Log, follow one of these steps: -## -## 1. -## In the source code, place the following line: -## -## proc printto log=stdout; -## -## to make a duplicate copy of the log in a file in addition -## to redirecting it to stdout, use this command to invoke -## SAS: -## -## sas -altlog doit.log doit.sas -## -## 2.Execute SAS in the background and use the UNIX 'tail' command -## to copy lines to stdout as they are added to the log. Use the -## command: -## -## sas doit.sas &; tail -f doit.log -## -## To redirect the SAS Log and Output under the Korn shell, use the -## following command: -## -## sas -stdio < doit.sas > doit.lst 2> doit.log -## -## To redirect the SAS Log and Output under the C-Shell, use the -## following command: -## -## (sas -stdio < doit.sas > doit.lst) >& doit.log - -## From WWW.SAS.COM: -## How can I make SAS in batch mode behave like interactive SAS, -## continue running my SAS job, and not enter syntax check mode when -## it encounters an error? -## -## You can specify the NOSYNTAXCHECK option when you invoke your SAS -## program. diff --git a/elpa/ess-20191014.1343/license.info b/elpa/ess-20191014.1343/license.info deleted file mode 100644 index 2bf932c3..00000000 --- a/elpa/ess-20191014.1343/license.info +++ /dev/null @@ -1,17 +0,0 @@ -This is license.info, produced by makeinfo version 6.5 from -license.texi. - -The source and documentation of ESS is free software. You can -redistribute it and/or modify it under the terms of the GNU General -Public License as published by the Free Software Foundation; either -version 2, or (at your option) any later version. - - ESS is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License in -the file COPYING in the same directory as this file for more details. - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/mailing.info b/elpa/ess-20191014.1343/mailing.info deleted file mode 100644 index 1cf83d79..00000000 --- a/elpa/ess-20191014.1343/mailing.info +++ /dev/null @@ -1,21 +0,0 @@ -This is mailing.info, produced by makeinfo version 6.5 from -mailing.texi. - -There is a mailing list for discussions and announcements relating to -ESS. Join the list by sending an e-mail with "subscribe ess-help" (or -"help") in the body to ; contributions -to the list may be mailed to . Rest assured, -this is a fairly low-volume mailing list. - - The purposes of the mailing list include - - * helping users of ESS to get along with it. - * discussing aspects of using ESS. - * suggestions for improvements. - * announcements of new releases of ESS. - * posting small patches to ESS. - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/make-regexp.el b/elpa/ess-20191014.1343/make-regexp.el deleted file mode 100644 index 406d9ddb..00000000 --- a/elpa/ess-20191014.1343/make-regexp.el +++ /dev/null @@ -1,238 +0,0 @@ -;;; make-regexp.el --- generate efficient regexps to match strings. - -;; Copyright (C) 1994, 1995 Simon Marshall. - -;; Author: Simon Marshall -;; Keywords: lisp, matching -;; Version: 1.02 - -;; LCD Archive Entry: -;; make-regexp|Simon Marshall|simon@gnu.ai.mit.edu| -;; Generate efficient regexps to match strings.| -;; 11-Jul-1995|1.02|~/functions/make-regexp.el.gz| - -;; The archive is archive.cis.ohio-state.edu in /pub/gnu/emacs/elisp-archive. - -;;; This file is not part of GNU Emacs. - -;;; This program is free software; you can redistribute it and/or modify -;;; it under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 2, or (at your option) -;;; any later version. - -;;; This program is distributed in the hope that it will be useful, -;;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Purpose: -;; -;; To make efficient regexps from lists of strings. - -;; For example: -;; -;; (let ((strings '("cond" "if" "while" "let\\*?" "prog1" "prog2" "progn" -;; "catch" "throw" "save-restriction" "save-excursion" -;; "save-window-excursion" "save-match-data" -;; "unwind-protect" "condition-case" "track-mouse"))) -;; (concat "(" (make-regexp strings t))) -;; -;; => "(\\(c\\(atch\\|ond\\(\\|ition-case\\)\\)\\|if\\|let\\*?\\|prog[12n]\\|save-\\(excursion\\|match-data\\|restriction\\|window-excursion\\)\\|t\\(hrow\\|rack-mouse\\)\\|unwind-protect\\|while\\)" -;; -;; To search for the above regexp takes about 70% of the time as for the simple -;; (concat "(\\(" (mapconcat 'identity strings "\\|") "\\)") regexp. -;; -;; Obviously, the more the similarity between strings, the faster the regexp: -;; -;; (make-regexp '("abort" "abs" "accept" "access" "array" "begin" "body" "case" -;; "constant" "declare" "delay" "delta" "digits" "else" "elsif" -;; "entry" "exception" "exit" "function" "generic" "goto" "if" -;; "others" "limited" "loop" "mod" "new" "null" "out" "subtype" -;; "package" "pragma" "private" "procedure" "raise" "range" -;; "record" "rem" "renames" "return" "reverse" "select" -;; "separate" "task" "terminate" "then" "type" "when" "while" -;; "with" "xor")) -;; -;; => "a\\(b\\(ort\\|s\\)\\|cce\\(pt\\|ss\\)\\|rray\\)\\|b\\(egin\\|ody\\)\\|c\\(ase\\|onstant\\)\\|d\\(e\\(clare\\|l\\(ay\\|ta\\)\\)\\|igits\\)\\|e\\(ls\\(e\\|if\\)\\|ntry\\|x\\(ception\\|it\\)\\)\\|function\\|g\\(eneric\\|oto\\)\\|if\\|l\\(imited\\|oop\\)\\|mod\\|n\\(ew\\|ull\\)\\|o\\(thers\\|ut\\)\\|p\\(ackage\\|r\\(agma\\|ivate\\|ocedure\\)\\)\\|r\\(a\\(ise\\|nge\\)\\|e\\(cord\\|m\\|names\\|turn\\|verse\\)\\)\\|s\\(e\\(lect\\|parate\\)\\|ubtype\\)\\|t\\(ask\\|erminate\\|hen\\|ype\\)\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\|xor" -;; -;; To search for the above regexp takes less than 60% of the time of the simple -;; mapconcat equivalent. -;; -;; But even small regexps may be worth it: -;; -;; (make-regexp '("and" "at" "do" "end" "for" "in" "is" "not" "of" "or" "use")) -;; => "a\\(nd\\|t\\)\\|do\\|end\\|for\\|i[ns]\\|not\\|o[fr]\\|use" -;; -;; as this is 10% faster than the mapconcat equivalent. - -;; Installation: -;; -;; (autoload 'make-regexp "make-regexp" -;; "Return a regexp to match a string item in STRINGS.") -;; -;; (autoload 'make-regexps "make-regexp" -;; "Return a regexp to REGEXPS.") -;; -;; Since these functions were written to produce efficient regexps, not regexps -;; efficiently, it is probably not a good idea to in-line too many calls in -;; your code, unless you use the following neat trick with `eval-when-compile': -;; -;; (defvar definition-regexp -;; (let ((regexp (eval-when-compile -;; (make-regexp '("defun" "defsubst" "defmacro" "defalias" -;; "defvar" "defconst" "defadvice") t)))) -;; (concat "^(" regexp))) -;; -;; The `byte-compile' code will be as if you had defined the variable thus: -;; -;; (defvar definition-regexp -;; "^(\\(def\\(a\\(dvice\\|lias\\)\\|const\\|macro\\|subst\\|un\\|var\\)\\)") - -;; Feedback: -;; -;; Originally written for font-lock, from an idea from Stig's hl319. -;; Please don't tell me that it doesn't produce optimal regexps; I know that -;; already. But (ideas or) code to improve things (are) is welcome. Please -;; test your code and tell me the speed up in searching an appropriate buffer. -;; -;; Please send me bug reports, bug fixes, and extensions, etc. -;; Simon Marshall - -;; History: -;; -;; 1.00--1.01: -;; - Made `make-regexp' take `lax' to force top-level parentheses. -;; - Fixed `make-regexps' for MATCH bug and new `font-lock-keywords'. -;; - Added `unfontify' to user timing functions. -;; 1.01--1.02: -;; - Made `make-regexp' `let' a big `max-lisp-eval-depth'. - -;; The basic idea is to find the shortest common non-"" prefix each time, and -;; squirrel it out. If there is no such prefix, we divide the list into two so -;; that (at least) one half will have at least a one-character common prefix. - -;; In addition, we (a) delay the addition of () parenthesis as long as possible -;; (until we're sure we need them), and (b) try to squirrel out one-character -;; sequences (so we can use [] rather than ()). - -;;; Code: - -(defun make-regexp (strings &optional paren lax) - "Return a regexp to match a string item in STRINGS. -If optional PAREN non-nil, output regexp parentheses around returned regexp. -If optional LAX non-nil, don't output parentheses if it doesn't require them. -Merges keywords to avoid backtracking in Emacs' regexp matcher." - (let* ((max-lisp-eval-depth (* 1024 1024)) - (strings (let ((l strings)) ; Paranoia---make strings unique! - (while l (setq l (setcdr l (delete (car l) (cdr l))))) - (sort strings 'string-lessp))) - (open-paren (if paren "\\(" "")) (close-paren (if paren "\\)" "")) - (open-lax (if lax "" open-paren)) (close-lax (if lax "" close-paren)) - (completion-ignore-case nil)) - (cond - ;; If there's only one string, just return it. - ((= (length strings) 1) - (concat open-lax (car strings) close-lax)) - ;; If there's an empty string, pull it out. - ((string= (car strings) "") - (if (and (= (length strings) 2) (= (length (nth 1 strings)) 1)) - (concat open-lax (nth 1 strings) "?" close-lax) - (concat open-paren "\\|" (make-regexp (cdr strings)) close-paren))) - ;; If there are only one-character strings, make a [] list instead. - ((= (length strings) (apply '+ (mapcar 'length strings))) - (concat open-lax "[" (mapconcat 'identity strings "") "]" close-lax)) - (t - ;; We have a list of strings. Is there a common prefix? - (let ((prefix (try-completion "" (mapcar 'list strings)))) - (if (> (length prefix) 0) - ;; Common prefix! Squirrel it out and recurse with the suffixes. - (let* ((len (length prefix)) - (sufs (mapcar (lambda (str) (substring str len)) strings))) - (concat open-paren prefix (make-regexp sufs t t) close-paren)) - ;; No common prefix. Is there a one-character sequence? - (let ((letters (let ((completion-regexp-list '("^.$"))) - (all-completions "" (mapcar 'list strings))))) - (if (> (length letters) 1) - ;; Do the one-character sequences, then recurse on the rest. - (let ((rest (let ((completion-regexp-list '("^..+$"))) - (all-completions "" (mapcar 'list strings))))) - (concat open-paren - (make-regexp letters) "\\|" (make-regexp rest) - close-paren)) - ;; No one-character sequence, so divide the list into two by - ;; dividing into those that start with a particular letter, and - ;; those that do not. - (let* ((char (substring (car strings) 0 1)) - (half1 (all-completions char (mapcar 'list strings))) - (half2 (nthcdr (length half1) strings))) - (concat open-paren - (make-regexp half1) "\\|" (make-regexp half2) - close-paren)))))))))) - -;; This stuff is realy for font-lock... - -;; Ahhh, the wonders of lisp... -(defun regexp-span (regexp &optional start) - "Return the span or depth of REGEXP. -This means the number of \"\\\\(...\\\\)\" pairs in REGEXP, optionally from START." - (let ((match (string-match (regexp-quote "\\(") regexp (or start 0)))) - (if (not match) 0 (1+ (regexp-span regexp (match-end 0)))))) - -;; The basic idea is to concat the regexps together, keeping count of the span -;; of the regexps so that we can get the correct match for hilighting. -(defun make-regexps (&rest regexps) - "Return a regexp to match REGEXPS -Each item of REGEXPS should be of the form: - - STRING ; A STRING to be used literally. - (STRING MATCH FACE DATA) ; Match STRING at depth MATCH with FACE - ; and highlight according to DATA. - (STRINGS FACE DATA) ; STRINGS is a list of strings FACE is - ; to highlight according to DATA. - -Returns a list of the form: - - (REGEXP (MATCH FACE DATA) ...) - -For example: - - (make-regexps \"^(\" - '((\"defun\" \"defalias\" \"defsubst\" \"defadvice\") keyword) - \"[ \t]*\" - '(\"\\\\([a-zA-Z-]+\\\\)?\" 1 function-name nil t)) - - => - - (\"^(\\\\(def\\\\(a\\\\(dvice\\\\|lias\\\\)\\\\|subst\\\\|un\\\\)\\\\)[ ]*\\\\([a-zA-Z-]+\\\\)?\" - (1 keyword) (4 function-name nil t)) - -Uses `make-regexp' to make efficient regexps." - (let ((regexp "") (data ())) - (while regexps - (cond ((stringp (car regexps)) - (setq regexp (concat regexp (car regexps)))) - ((stringp (nth 0 (car regexps))) - (setq data (cons (cons (+ (regexp-span regexp) - (nth 1 (car regexps))) - (nthcdr 2 (car regexps))) - data) - regexp (concat regexp (nth 0 (car regexps))))) - (t - (setq data (cons (cons (1+ (regexp-span regexp)) - (cdr (car regexps))) - data) - regexp (concat regexp (make-regexp (nth 0 (car regexps)) - t))))) - (setq regexps (cdr regexps))) - (cons regexp (nreverse data)))) - -;; timing functions removed due to name collisions with Gnus - -(provide 'make-regexp) - -;;; make-regexp.el ends here diff --git a/elpa/ess-20191014.1343/news.info b/elpa/ess-20191014.1343/news.info deleted file mode 100644 index b476aa29..00000000 --- a/elpa/ess-20191014.1343/news.info +++ /dev/null @@ -1,416 +0,0 @@ -This is news.info, produced by makeinfo version 6.5 from news.texi. - -Changes and New Features in 19.04 (unreleased): - - * ESS[R]: There is a new menu entry for reloading the R process. It - is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same - process name and start arguments that were used to start the - process. - - * iESS: Process runners now return the inferior buffer. Note that - callers of inferior runners should not assume that the current - buffer has been set to the inferior buffer. Instead, use - 'with-current-buffer' with the return value of the inferior. - - * iESS[SAS]: The SAS keymap was only set in iESS buffers called - '*SAS*'. This is now fixed. - - * ESS[R]: Fixed longstanding indentation issues involving '::' and - ':::' operators. - - * Implement a more reliable check for the process busy state. - Background actions such as completion and directory synchronization - should not block the process and should not cause printing of the - extraneous output to the interpreter. - - * Activate 'goto-address-mode' for url and email highlighting in - inferior buffers. - - * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. - Users who liked the previous behavior (i.e. underscore inserting - "<-") should bind 'ess-insert-assign' to the underscore in their - Emacs initialization file. For example, '(define-key - ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key - inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it - in all ESS R buffers. - - * ESS major modes are now defined using 'define-derived-mode'. This - makes ESS major modes respect modern conventions such as having - -mode-hook and -mode-map. Users are encouraged - to place customizations under the appropriate mode. - - * New option ess-auto-width controls setting the width option on - window changes. Users can change it to 'frame, 'window, or an - integer. See the documentation for details. - 'ess-auto-width-visible' controls visibility. - - * ESS now respects 'display-buffer-alist'. Users can now use - 'display-buffer-alist' to manage how and where windows appear. See - *Note (ess)Controlling buffer display:: for more information and - examples. - - * 'ess-roxy-mode' can now be enabled in non-R buffers. This is - primarily intended to support roxygen documentation for cpp - buffers. Preview functionality is not supported outside R buffers. - - * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. - - * 'ess-style' now has effects when set as a file or directory local - variable. - - * 'ess-default-style' is now obsolete, use 'ess-style' instead. - - * Options for 'ess-gen-proc-buffer-name-function' have been renamed. - ess-gen-proc-buffer-name:projectile-or-simple was renamed to - ess-gen-proc-buffer-name:project-or-simple and - ess-gen-proc-buffer-name:projectile-or-directory was renamed to - ess-gen-proc-buffer-name:project-or-directory. As the name - suggests, these now rely on project.el (included with Emacs) rather - than projectile.el, which is a third-party package. - - * ESS[R]: devtools commands ask about saving modified buffers before - running. Users can disable the questioning with - 'ess-save-silently'. - - * ESS[R] help pages now provide links to other help topics. This is - similar with what you would see with, for example - 'options(help_type = ``html'')' but works with the plain-text - version as well. This only works with 'options(useFancyQuotes = - TRUE)' (the default). - - * 'ess-rdired' buffers now derive from tabulated-list-mode. They - should look better and be a bit faster overall. The size column - now displays object sizes in bytes. - - * 'ess-rdired' buffers now auto-update. The frequency is governed by - the new option 'ess-rdired-auto-update-interval'. - - * ESS[R]: 'electric-layout-mode' is now supported. This - automatically inserts a newline after an opening curly brace in R - buffers. To enable it, customize 'ess-r-mode-hook'. - - * ESS[R]: imenu now supports assignment with the equals sign. - - * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. - - * ESS removed support for many unused languages. This includes old - versions of S+, ARC, OMG, VST, and XLS. - - The following have been made obsolete or removed, see their -documentation for more detail: - - * Libraries for literate data analysis are obsolete and not loaded by - default. This includes 'ess-noweb', 'ess-swv', and related - functionality like 'Rnw-mode'. Users are encouraged to switch to - one of several other packages that deal with these modes. For - example, polymode , - , or markdown-mode with edit-indirect - . - - * Support for 'auto-complete' is obsolete. The 'auto-complete' - package is unmaintained and so ESS support is now obsolete. Users - are encouraged to switch to 'company-mode' instead. - - * User options for controlling display of buffers. This includes - 'ess-show-buffer-action', 'inferior-ess-same-window', - 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See - above about ESS respecting 'display-buffer-alist'. - - * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. - Use the Emacs-wide setting of 'tab-always-indent' instead. - - * 'inferior-ess-*-start-file' variables. All modes except Stata did - not respect customization of this variable. In order to load a - file on startup, you should put a function on - 'ess-*-post-run-hook'. - - Bug Fixes in 18.10.3: - * More 'Makefile' fixes, notably installing '*.el's. - - Bug Fixes in 18.10.2: - * ESS[R] Fix namespace evaluation in non-installed packages. - Evaluation is directed into GlobalEnv as originally intended. - * 'Makefile' fixes, notably for 'make install' and including full - docs in the tarballs. - - Bug Fixes in 18.10-1: - * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and - 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave - as the old versions of 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step'. - - Changes and New Features in 18.10: - - * This is the last release to support Emacs older than 25.1. Going - forward, only GNU Emacs 25.1 and newer will be supported. Soon - after this release, support for older Emacs versions will be - dropped from the git master branch. Note that MELPA uses the git - master branch to produce ESS snapshots, so if you are using Emacs < - 25.1 from MELPA and are unable to upgrade, you should switch to - MELPA-stable. - - * ESS now displays the language dialect in the mode-line. So, for - example, R buffers will now show ESS[R] rather than ESS[S]. - - * The ESS manual has been updated and revised. - - * The ESS initialization process has been further streamlined. If - you update the autoloads (which installation from 'package-install' - does), you should not need to '(require 'ess-site)' at all, as - autoloads should automatically load ESS when it is needed (e.g. - the first time an R buffer is opened). In order to defer loading - your ESS config, you may want to do something like - '(with-require-after-load "ess" )' in your Emacs - init file. Users of the popular 'use-package' Emacs package can - now do '(use-package ess :defer t)' to take advantage of this - behavior. *Note (ess)Activating and Loading ESS:: for more - information on this feature. - - * ESS now respects Emacs conventions for keybindings. This means - that The 'C-c [letter]' bindings have been removed. This affects - 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in - 'sas-mode-local-map'; 'C-c f', which was bound to - 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', - which was bound to 'ess-handy-commands' in 'Rd-mode-map', - 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' - - * Functions 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step' now behave consistently with - other evaluation function inside a package. - - * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets - the working directory to the root of the current package including - for example C or C++ files within '/src'). - - * ESS[R]: Long + + prompts in the inferior no longer offset output. - - * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This - strips the entire + + sequence. - - * ESS modes now inherit from 'prog-mode'. In the next release, ESS - modes will use 'define-derived-mode' so that each mode will have - (for example) its own hooks and keymaps. - - * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. - Users need to install the 'lintr' package to use it. Customizable - options include 'ess-use-flymake', 'ess-r-flymake-linters', and - 'ess-r-flymake-lintr-cache'. - - * ESS[R]: Gained support for xref in Emacs 25+. *Note (emacs)Xref:: - - * ESS[R]: The startup screen is cleaner. It also displays the - startup directory with an explicit 'setwd()'. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[R]: 'Makevars' files open with 'makefile-mode'. - - * New variable 'ess-write-to-dribble'. This allows users to disable - the dribble ('*ESS*') buffer if they wish. - - * All of the '*-program-name' variables have been renamed to - '*-program'. Users who previously customized e.g. - 'inferior-ess-R-program-name' will need to update their - customization to 'inferior-ess-R-program'. These variables are - treated as risky variables. - - * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It - provides similar functionality but for any keybinding, not just - '_'. For instance if you bind it to ';', repeated invocations - cycle through between assignment and inserting ';'. - - * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the - documentation for details. New user customization option - 'ess-assign-list' controls which assignment operators are cycled. - - * ESS[R] In remote sessions, the ESSR package is now fetched from - GitHub. - - * Commands that send the region to the inferior process now deal with - rectangular regions. See the documentation of 'ess-eval-region' - for details. This only works on Emacs 25.1 and newer. - - * ESS[R]: Improvements to interacting with iESS in non-R files. - Interaction with inferior process in non-R files within packages - (for instance C or C++ files) has been improved. This is a work in - progress. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in - JAGS mode. - - Many improvements to fontification: - - * Improved customization for faces. ESS now provides custom faces - for (nearly) all faces used and places face customization options - into their own group. Users can customize these options using 'M-x - customize-group RET ess-faces'. - - * Many new keywords were added to 'ess-R-keywords' and - 'ess-R-modifiers'. See the documentation for details. - - * ESS[R]: 'in' is now only fontified when inside a 'for' construct. - This avoids spurious fontification, especially in the output buffer - where 'in' is a common English word. - - * ESS: Font-lock keywords are now generated lazily. That means you - can now add or remove keywords from variables like 'ess-R-keywords' - in your Emacs configuration file after loading ESS (i.e. in the - ':config' section for 'use-package' users). - - * ESS[R]: Fontification of roxygen '@param' keywords now supports - comma-separated parameters. - - * ESS[R]: Certain keywords are only fontified if followed by a - parenthesis. Function-like keywords such as 'if ()' or 'stop()' - are no longer fontified as keyword if not followed by an opening - parenthesis. The same holds for search path modifiers like - 'library()' or 'require()'. - - * ESS[R]: Fixed fontification toggling. Especially certain syntactic - elements such as '%op%' operators and backquoted function - definitions. - - * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. - This command asks with completion for a font-lock group to toggle. - This functionality is equivalent to the font-lock menu. - - Notable bug fixes: - - * 'prettify-symbols-mode' no longer breaks indentation. This is - accomplished by having the pretty symbols occupy the same number of - characters as their non-pretty cousins. You may customize the new - variable 'ess-r-prettify-symbols' to control this behavior. - - * ESS: Inferior process buffers are now always displayed on startup. - Additionally, they don't hang Emacs on failures. - - Obsolete libraries, functions, and variables: - - * The 'ess-r-args.el' library has been obsoleted and will be removed - in the next release. Use 'eldoc-mode' instead, which is on by - default. - - * Functions and options dealing with the smart assign key are - obsolete. The following functions have been made obsolete and will - be removed in the next release of ESS: 'ess-smart-S-assign', - 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', - 'ess-disable-smart-S-assign'. - - The variable 'ess-smart-S-assign-key' is now deprecated and will be - removed in the next release. If you would like to continue using - '_' for inserting assign in future releases, please bind - 'ess-insert-assign' in 'ess-mode-map' the normal way. - - * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. - Use 'ess-s-versions' instead. You may pass arguments by starting - the inferior process with the universal argument. - - Changes and New Features in 17.11: - - * The ESS initialization process has been streamlined. You can now - load the R and Stata modes independently from the rest of ESS. Just - put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your - init file. This is for experienced Emacs users as this requires - setting up autoloads for '.R' files manually. We will keep - maintaining 'ess-site' for easy loading of all ESS features. - - * Reloading and quitting the process is now more robust. If no - process is attached, ESS now switches automatically to one - (prompting you for selection if there are several running). - Reloading and quitting will now work during a debug session or when - R is prompting for input (for instance after a crash). Finally, - the window configuration is saved and restored after reloading to - prevent the buffer of the new process from capturing the cursor. - - * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working - directory of the current process to the current package directory. - - * ESS[R] Lookup for references in inferior buffers has been improved. - New variable 'ess-r-package-source-roots' contains package - sub-directories which are searched recursively during the file - lookup point. Directories in 'ess-tracebug-search-path' are now - also searched recursively. - - * ESS[R] Namespaced evaluation is now automatically enabled only in - the 'R/' directory. This way ESS will not attempt to update - function definitions from a package if you are working from e.g. a - test file. - - Changes and New Features in 16.10: - - * ESS[R]: Syntax highlighting is now more consistent. Backquoted - names are not fontified as strings (since they really are - identifiers). Furthermore they are now correctly recognized when - they are function definitions or function calls. - * ESS[R]: Backquoted names and '%op%' operators are recognized as - sexp. This is useful for code navigation, e.g. with 'C-M-f' and - 'C-M-b'. - * ESS[R]: Integration of outline mode with roxygen examples fields. - You can use outline mode's code folding commands to fold the - examples field. This is especially nice to use with well - documented packages with long examples set. Set - 'ess-roxy-fold-examples' to non-nil to automatically fold the - examples field when you open a buffer. - * ESS[R]: New experimental feature: syntax highlighting in roxygen - examples fields. This is turned off by default. Set - 'ess-roxy-fontify-examples' to non-nil to try it out. - * ESS[R]: New package development command 'ess-r-devtools-ask' bound - to 'C-c C-w C-a'. It asks with completion for any devtools command - that takes 'pkg' as argument. - * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. - Currently only implemented for R. The R method runs - 'inferior-ess-r-reload-hook' on reloading. - * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers - as well. - - Bug fixes in 16.10: - * ESS[R]: Fix broken (un)flagging for debugging inside packages - * ESS[R]: Fixes (and improvements) in Package development - * ESS[R]: Completion no longer produces '...=' inside 'list( )'. - * ESS[R]: Better debugging and tracing in packages. - * ESS[R]: Better detection of symbols at point. - * ESS[R]: No more spurious warnings on deletion of temporary files. - * ESS[julia]: help and completion work (better) - * ESS[julia]: available via 'ess-remote' - - Changes and New Features in 16.04: - - * ESS[R]: 'developer' functionality has been refactored. The new - user interface consists of a single command - 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once - an evaluation environment has been set with, all subsequent ESS - evaluation will source the code into that environment. By default, - for file within R packages the evaluation environment is set to the - package environment. Set 'ess-r-package-auto-set-evaluation-env' - to 'nil' to disable this. - * ESS[R]: New 'ess-r-package-mode' This development mode provides - features to make package development easier. Currently, most of - the commands are based on the 'devtools' packages and are - accessible with 'C-c C-w' prefix. See the documentation of - 'ess-r-package-mode' function for all available commands. With - 'C-u' prefix each command asks for extra arguments to the - underlying devtools function. This mode is automatically enabled - in all files within R packages and is indicated with '[pkg:NAME]' - in the mode-line. - * ESS[R]: Help lookup has been improved. It is now possible to get - help for namespaced objects such as pkg::foobar. Furthermore, ESS - recognizes more reliably when you change 'options('html_type')'. - * ESS[R]: New specialized breakpoints for debugging magrittr pipes - * ESS: ESS now implements a simple message passing interface to - communicate between ESS and inferior process. - - Bug fixes in 16.04: - * ESS[R]: Roxygen blocks with backtics are now correctly filled - * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' - * ESS[R]: Error highlighting now understands 'testthat' type errors - * ESS[Julia]: Added getwd and setwd generic commands - - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/obsolete/ess-eldoc.el b/elpa/ess-20191014.1343/obsolete/ess-eldoc.el deleted file mode 100644 index d43d640a..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-eldoc.el +++ /dev/null @@ -1,172 +0,0 @@ -;;; ess-eldoc.el --- Use eldoc to report R function names. - -;; Copyright (C) 1997--2009 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Stephen Eglen -;; Created: 2007-06-30 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; http://www.r-project.org/Licenses/ - -;;; Commentary: - -;;;;; eldoc funcitonality has been moved into the core ;;;;; -;;;;; this file has no effect and is left in ESS in order not to break -;;;;; users configuration - -;; This is an initial attempt to use the emacs facility ELDOC in R -;; buffers. Eldoc is used in Emacs lisp buffers to show the function -;; arglist and docstrings for variables. To try it, view an emacs -;; lisp buffer, and then do M-x turn-on-eldoc-mode, and move over -;; function and variable names. - -;; This file extends eldoc to work in R buffers. It currently uses -;; Sven's ess-r-args.el file to retrieve args for a given R function -;; (via ess-r-args-get). Note that it works slightly different to -;; Sven's code, in that you just need to have the point over the name -;; of an R function, or inside its arguments list, for eldoc to show -;; the arg list. - -;; To use this functionality, simply add -;; -;; (require 'ess-eldoc) -;; -;; to your .emacs file. When you visit a R mode, eldoc will be turned -;; on. However, you will first need to associate the R buffer with an -;; *R* process so that args can be looked up -- otherwise, eldoc will -;; silently not report anything. So, e.g. try: -;; C-x C-f somefile.R -;; M-x R (so that somefile.R is associated with *R*) -;; eldoc should then work. - -;; e.g. put the following rnorm() command in an R buffer. The line -;; underneath shows a key of what arg list will be shown as you move -;; across the rnorm line. - -;; rnorm(n=100, mean=sqrt(20), sd=10) -;; 1111111111111222223333333311444111 -;; 1: rnorm -;; 2: mean -;; 3: sqrt -;; 4: sd -;; - -;; Note that the arg list for rnorm() should be shown either when you -;; are on the function name, or in the arg list. However, since the -;; 2nd and 3rd arguments are also function names, the arg lists of -;; those function names are reported instead. This might be seen as -;; undesirable behaviour, in which case a solution would be to only -;; look up the function name if it is followed by (. - -;; If you want to use this feature in *R* buffers, add the following -;; to .emacs: -;; (add-hook 'inferior-ess-mode-hook 'ess-use-eldoc) - - -;; In the current version, I do not cache the arg list, but that was -;; done in an earlier version, to save repeated calls to -;; ess-r-args-get. - -;; This code has been tested only in Emacs 22.1. It will not work on -;; Emacs 21, because it needs the variable -;; eldoc-documentation-function. - -;;;; VS [25-02-2012]: all these issues were at least partially addresed in the -;;;; new implementation: - -;; Bug (in eldoc?): the arg list for legend() is too long to fit in -;; minibuffer, and it seems that we see the last N lines of the arg -;; list, rather than the first N lines. It would be better to see the -;; first N lines since the more important args come first. - -;; Doc issue: the eldoc vars (e.g. eldoc-echo-area-use-multiline-p) -;; work only for elisp mode. - -;; Issue: You will probably see the message "Using process 'R'" flash; -;; this is generated by `ess-request-a-process', and I'd like to avoid -;; that appearing, non-interactively. - -;; If *R* is currently busy (e.g. processing Sys.sleep(999)), then the -;; eldoc commands won't work; ess-command could be silenced in this -;; regard perhaps with a new SILENT arg for example to prevent the -;; call to (ess-error). - - -;;; Code: - -;; ;; This could be done on buffer local basis. -;; (setq ess-r-args-noargsmsg "") - -;; ;; following two defvars are not currently used. -;; (defvar ess-eldoc-last-name nil -;; "Name of the last function looked up in eldoc. -;; We remember this to see whether we need to look up documentation, or used -;; the cached value in `ess-eldoc-last-args'.") - -;; (defvar ess-eldoc-last-args nil -;; "Args list last looked up for eldoc. Used as cache.") - -;; (defun ess-eldoc-2 () -;; ;; simple, old version. -;; (interactive) -;; (ess-r-args-get (ess-read-object-name-default))) - -;; (defun ess-eldoc-1 () -;; "Return the doc string, or nil. -;; This is the first version; works only on function name, not within arg list." -;; (interactive) - -;; ;; Possible ways to get the function at point. -;; ;;(setq name (thing-at-point 'sexp)) -;; ;;(setq name (ess-read-object-name-default)) -;; ;;(setq name (find-tag-default)) - -;; (if ess-current-process-name -;; (progn -;; (setq name (ess-guess-fun)) ;guess the word at point. -;; (if (equal (length name) 0) -;; nil -;; ;; else -;; (unless (equal name ess-eldoc-last-name) -;; ;; name is different to the last name we lookedup, so get -;; ;; new args from R and store them. -;; (setq ess-eldoc-last-args (ess-r-args-get name) -;; ess-eldoc-last-name name)) -;; ess-eldoc-last-args)) -;; ;; no ESS process current. -;; nil) -;; ) - - -;; (defsubst ess-guess-fun () -;; "Guess what the function at point is." -;; ;; Derived from Man-default-man-entry in man.el -;; (let (word) -;; (save-excursion -;; (skip-chars-backward "-a-zA-Z0-9._+:") -;; (let ((start (point))) -;; (skip-chars-forward "-a-zA-Z0-9._+:") -;; (setq word (buffer-substring-no-properties start (point))))) -;; word)) - -(defun ess-use-eldoc () - "Does nothing. Defined not to break old users' code." - (interactive)) - -(provide 'ess-eldoc) - -;;; ess-eldoc.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-mouse.el b/elpa/ess-20191014.1343/obsolete/ess-mouse.el deleted file mode 100644 index 88e877f5..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-mouse.el +++ /dev/null @@ -1,222 +0,0 @@ -;;; ess-mouse.el --- Support for mouse- or cursor-sensitive actions - -;; Copyright (C) 2001 Richard M. Heiberger -;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Richard M. Heiberger -;; Created: 25 Mar 2001 -;; Maintainer: ESS-core - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Support for mouse- or cursor-sensitive actions. This is based on -;; and uses mouseme.el. mouseme.el only does mouse sensititivity. -;; The new functions ess-mouse-me and ess-mouse-me-helper do similar -;; things based on the cursor, not the mouse, and can be bound to a -;; keystroke. - -;;; Code: - - ; Requires and autoloads - -;;*;; Requires -(require 'mouseme) -(require 'ess-trns) -;;(if (or (equal window-system 'w32) -;; (equal window-system 'win32) -;; (equal window-system 'mswindows)) -;; (require 'essiw32b)) - -(defun ess-mouse-me () - "Popup a menu of functions to run on selected string or region." - (interactive) - (ess-mouse-me-helper - (lambda (name) - (or (x-popup-menu (list '(0 0) - (get-buffer-window (get-buffer (buffer-name)))) - (funcall mouse-me-build-menu-function name)) - (error "No command to run"))))) - - - -(defun ess-mouse-me-helper (func) - "Determine the string to use to process EVENT and call FUNC to get cmd." - (let (name sp sm mouse beg end cmd mmtype) - ;; temporarily goto where the event occurred, get the name clicked - ;; on and enough info to figure out what to do with it - (save-match-data - (save-excursion - (setq sp (point)) ; saved point - (setq sm (mark t)) ; saved mark -;;; (set-buffer (window-buffer (posn-window (event-start event)))) -;;; (setq mouse (goto-char (posn-point (event-start event)))) - (setq mouse (point)) ;; ess-mouse-me-helper - ;; if there is a region and point is inside it - ;; check for sm first incase (null (mark t)) - ;; set name to either the thing they clicked on or region - (if (and sm - (or (and transient-mark-mode mark-active) - (eq last-command 'mouse-drag-region)) - (>= mouse (setq beg (min sp sm))) - (<= mouse (setq end (max sp sm)))) - (setq name (buffer-substring beg end)) - (setq name (funcall mouse-me-get-string-function)) - (if (listp name) - (setq beg (nth 1 name) - end (nth 2 name) - name (car name)) - (goto-char mouse) - (while (not (looking-at (regexp-quote name))) - (backward-char 1)) - (setq beg (point)) - (setq end (search-forward name)))))) - ;; check if name is null, meaning they clicked on no word - (if (or (null name) - (and (stringp name) (string= name "" ))) - (error "No string to pass to function")) - ;; popup a menu to get a command to run - (setq cmd (funcall func name)) - ;; run the command, eval'ing if it was a list - (if (listp cmd) - (setq cmd (eval cmd))) - (setq mmtype (get cmd 'mouse-me-type)) - (cond ((eq mmtype 'region) - (funcall cmd beg end)) - ((eq mmtype 'string) - (funcall cmd name)) - (t - (funcall cmd name))))) - -(defcustom ess-S-mouse-me-menu-commands-alist - '("S-Plus 4 and 6 GUI under Windows" - ("Edit.data" . ess-mouse-me-Edit.data) - "----" - ("print" . ess-mouse-me-print) - ("summary" . ess-mouse-me-summary) - ("plot" . ess-mouse-me-plot) - ("show" . ess-mouse-me-show) - ("help" . ess-display-help-on-object) - ("args" . ess-mouse-me-args) - "----" - ("Browser on" . ess-mouse-me-browser-on) - ("Browser off" . ess-mouse-me-browser-off)) - "Command menu used by `mouse-me-build-menu'. -A alist of elements where each element is either a cons cell or a string. -If a cons cell the car is a string to be displayed in the menu and the -cdr is either a function to call passing a string to, or a list which evals -to a function to call passing a string to. If the element is a string -it makes a non-selectable element in the menu. To make a separator line -use a string consisting solely of hyphens. - -The function returned from this menu will be called with one string -argument. Or if the function has the symbol property `mouse-me-type' -and if its value is the symbol `region' it will be called with the -beginning and ending points of the selected string. If the value is -the symbol `string' it will be called with one string argument." - :type '(repeat sexp) - :group 'mouseme) - - -(defun ess-mouse-me-Edit.data (string) - (ess-mouse-me-eval-expanded string "Edit.data(" ")" nil nil nil)) - -(defun ess-mouse-me-print (string) - (ess-mouse-me-eval-expanded string "" "" nil nil t)) -(defun ess-mouse-me-summary (string) - (ess-mouse-me-eval-expanded string "summary(" ")" nil nil t)) -(defun ess-mouse-me-plot (string) - (ess-mouse-me-eval-expanded string "plot(" ")") nil nil nil) -(defun ess-mouse-me-show (string) - (ess-mouse-me-eval-expanded string "show(" ")") nil nil nil) -(defun ess-mouse-me-args (string) - (ess-mouse-me-eval-expanded string "args(" ")" nil nil t)) - -(defun ess-mouse-me-browser-on (string) - (if (equal (substring ess-dialect 0 1) "R") - (ess-eval-linewise (concat "debug(" string ")")) - (ess-mouse-me-eval-expanded string "trace(" ", exit=browser)") nil nil nil)) - -(defun ess-mouse-me-browser-off (string) - (if (equal (substring ess-dialect 0 1) "R") - (ess-eval-linewise (concat "undebug(" string ")")) - (ess-mouse-me-eval-expanded string "untrace(" ")") nil nil nil)) - - - -(defun ess-mouse-me-eval-expanded (string &optional head tail commands-buffer - page value-returned) - "Send the expanded STRING to the inferior-ess process using `ess-command' -after first concating the HEAD and TAIL. Put answer in COMMANDS-BUFFER if -specified, otherwise in \"tmp-buffer\". In either -case the buffer containing the answer is renamed to the value of the -constructed command. If PAGE is non-nil, expand -the string one more time by embedding it in a \"page()\" command." - (interactive) - (let* (scommand - page-scommand - (lproc-name ess-local-process-name) - (ess-mouse-customize-alist ess-local-customize-alist)) - (if (not head) (setq head "summary(")) - (if (not tail) (setq tail ")")) - (if (not commands-buffer) (setq commands-buffer - (get-buffer-create "tmp-buffer"))) - (setq scommand (concat head string tail)) - - (ess-make-buffer-current) - (pop-to-buffer-same-window commands-buffer) - (ess-setq-vars-local (eval ess-mouse-customize-alist) (current-buffer)) - (setq ess-local-process-name lproc-name) - (ess-command (concat scommand "\n") commands-buffer) - (if (not value-returned) (pop-to-buffer-same-window (nth 1 (buffer-list)))) - (if (not value-returned) - nil - (if ess-microsoft-p ;; there ought to be a filter - (while (search-forward "\r" nil t) ;; function to keep the ^M - (replace-match "" nil t))) ;; from showing up at all - (ess-transcript-mode) - (setq ess-local-process-name lproc-name) - (rename-buffer scommand)))) - - - ; Provide package - -(provide 'ess-mouse) - - - -;;;;;;;; STARTUP STUFF ;;;;;;;;;;;; - -(make-variable-buffer-local 'mouse-me-menu-commands) - -(defun ess-S-mouse-me-menu-commands () - (if (equal ess-language "S") - (setq mouse-me-menu-commands ess-S-mouse-me-menu-commands-alist))) - -;; (define-key ess-mode-map [S-mouse-3] 'ess-mouse-me) -;; (define-key inferior-ess-mode-map [S-mouse-3] 'ess-mouse-me) -;; (defun ess-S-mouse-me-ess-transcript-mode () -;; (define-key ess-transcript-mode-map [S-mouse-3] 'ess-mouse-me)) -;; -(add-hook 'ess-mode-hook 'ess-S-mouse-me-menu-commands) -(add-hook 'inferior-ess-mode-hook 'ess-S-mouse-me-menu-commands) -(add-hook 'ess-transcript-mode-hook 'ess-S-mouse-me-menu-commands) -;; (add-hook 'ess-transcript-mode-hook 'ess-S-mouse-me-ess-transcript-mode) - - -;;; ess-mouse.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-noweb-font-lock-mode.el b/elpa/ess-20191014.1343/obsolete/ess-noweb-font-lock-mode.el deleted file mode 100644 index b9ebfbca..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-noweb-font-lock-mode.el +++ /dev/null @@ -1,392 +0,0 @@ -;;; ess-noweb-font-lock-mode.el --- edit noweb files with GNU Emacs - -;; Copyright (C) 1999 by Adnan Yaqub (AYaqub@orga.com) -;; and Mark Lunt (mark.lunt@mrc-bsu.cam.ac.uk -;; Copyright (C) 2002 by A.J. Rossini -;; Copyright (C) 2003--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Maintainer: ESS-core - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ -;; - -;;; Commentary: - -;; Code-dependent highlighting -;; ***** -;; -;; Adding highlighting to ess-noweb-mode.el -;; -;; Here is a description of how one can add highlighting via the -;; font-lock package to noweb buffers. It uses the hooks provided by -;; ess-noweb-mode.el. The solution provides the following features: -;; 1) The documentation chunks are highlighted in the ess-noweb-doc-mode -;; (e.g., LaTeX). -;; 2) The code chunks without mode comments (-*- mode -*-) are -;; highlighted in the ess-noweb-code-mode. -;; 3) The code chunks with mode comments (-*- mode -*-) on the first -;; line of the first chunk with this name are highlighted in the mode -;; in the comment. -;; -;; For example, given the file: -;; -;; % -*- mode: Noweb; ess-noweb-code-mode: c-mode -*- -;; -;; \begin{itemize} -;; \item a main routine written in C, -;; \item a log configuration file parser written in YACC, and -;; \item a lexical analyzer written in Lex. -;; \end{itemize} -;; -;; <>= -;; /* DO NOT EDIT ME! */ -;; /* This file was automatically generated from %W% (%G%). */ -;; @ -;; -;; <>= -;; .\" -*- nroff -*- -;; .\" DO NOT EDIT ME! -;; .\" This file was automatically generated from %W% (%G%). -;; @ -;; -;; The LaTeX list is highlighted in latex-mode (the default noweb doc -;; mode), the chunk <> is highlighted in c-mode (the -;; default noweb code mode), and the chunk <> is -;; highlighted in nroff-mode due to the "-*- nroff -*-" comment. -;; -;; Chunks are highlighted each time point moves into them from a -;; different mode. They are also fontified 'on the fly', but this is -;; less reliable, since the syntax can depend on the context. It's as -;; good as you would get outside ess-noweb-mode, though. -;; -;; To use it, you must add -;; (require 'ess-noweb-font-lock-mode) to your .emacs file. -;; Then, if you use either global-font-lock or turn-on-font-lock -;; statements, any ess-noweb-mode buffers will be fontified -;; appropriately. (We have to redefine turn-on-font-lock, but it -;; saves breaking other packages (in particular ESS, which I use a -;; lot), that assume that turn-on-font-lock is the way to turn on -;; font locking. - -;; Alternatively, you can turn ess-noweb-font-lock-mode on and off by -;; using M-x ess-noweb-font-lock-mode. However, turning -;; ess-noweb-font-lock-mode off when global-font-lock-mode is t makes it -;; impossible to use font-locking in that buffer subsequently, other -;; than by turning ess-noweb-font-lock-mode back on. - -;; 2) The highlighting sometimes get confused, but this is no longer -;; a noweb problem. Highlighting should work as well within a chunk -;; as it does without ess-noweb-mode. -;; There are some problems with, for example latex-mode: a `$' in a -;; verbatim environment with throw the font-locking out. -;; One slight blemish is that code-quotes are highlighted as comments -;; as they are being entered. They are only highlighted correctly -;; after `ess-noweb-font-lock-fontify-chunk' has been run, either as a -;; command or through changing to a different chunk and back again -;; (unless they lie on a single line, in which case they are -;; fontified correctly once they are completed). - -;;; Code: - -(require 'ess-noweb-mode) -(require 'font-lock) - -(defvar ess-noweb-font-lock-mode nil - "Buffer local variable, t iff this buffer is using `ess-noweb-font-lock-mode'.") - -(defvar ess-noweb-use-font-lock-mode t - "DO NOT CHANGE THIS VARIABLE -If you use `nw-turn-on-font-lock' to turn on font-locking, then turn it -off again, it would come back on again of its own accord when you -changed major-mode. This variable is used internally to stop it.") - -(defvar ess-noweb-font-lock-mode-hook nil - "Hook that is run after entering ess-noweb-font-lock mode.") - -(defvar ess-noweb-font-lock-max-initial-chunks 30 - "Maximum number of chunks to fontify initially. -If nil, will fontify the entire buffer when -ess-noweb-font-lock-initial-fontify-buffer is called" ) - -;; (defvar old-beginning-of-syntax nil -;; "Stores the function used to find the beginning of syntax in the -;; current major mode. ess-noweb-font-lock-mode needs a different one." ) - -(defvar ess-noweb-font-lock-doc-start-face font-lock-reference-face - "Face to use to highlight the `@' at the start of each doc chunk") - -(defvar ess-noweb-font-lock-brackets-face font-lock-reference-face - "Face to use to highlight `<<', `>>' `[[' and `]]' ") - -(defvar ess-noweb-font-lock-chunk-name-face font-lock-keyword-face - "Face to use to highlight the between `<<' and `>>'") - -(defvar ess-noweb-font-lock-code-quote-face font-lock-keyword-face - "Face to use to highlight the between `[[' and `]]'") - -;; Now we add [[ess-noweb-font-lock-mode]] to the list of existing minor -;; modes. The string ``NWFL'' will be added to the mode-line: ugly, but -;; brief. - -(if (not (assq 'ess-noweb-font-lock-mode minor-mode-alist)) - (setq minor-mode-alist (append minor-mode-alist - (list '(ess-noweb-font-lock-mode " NWFL"))))) - -;; An ugly kludge to get around problems with global-font-lock, which -;; fontifies the entire buffer in the new major mode every time you -;; change mode, which is time-consuming and makes a pigs trotters of -;; it. Trying to stop it looks tricky, but using this function as your -;; `font-lock-fontify-buffer' function stops it wasting your time - -(defalias 'nwfl-donowt #'ignore) - -;; The following function is just a wrapper for ess-noweb-font-lock-mode, -;; enabling it to be called as ess-noweb-font-lock-minor-mode instead. - -(define-obsolete-function-alias 'ess-noweb-font-lock-minor-mode - #'ess-noweb-font-lock-mode "ESS-16.11") - -;; Here we get to the meat of the problem -;;;###autoload -(defun ess-noweb-font-lock-mode ( &optional arg) - ;; FIXME: Don't define a new minor mode. Instead, arrange for normal - ;; font-lock to call our functions such as - ;; ess-noweb-font-lock-fontify-chunk-by-number. - "Minor mode for syntax highlighting when using `ess-noweb-mode' to edit noweb files. -Each chunk is fontified in accordance with its own mode." - (interactive "P") - (if (or ess-noweb-mode ess-noweb-font-lock-mode) - (progn - ;; This bit is tricky: copied almost verbatim from bib-cite-mode.el - ;; It seems to ensure that the variable ess-noweb-font-lock-mode is made - ;; local to this buffer. It then sets ess-noweb-font-lock-mode to `t' if - ;; 1) It was called with a prefix argument greater than 0 - ;; or 2) It was called with no argument, and ess-noweb-font-lock-mode is - ;; currently nil - ;; ess-noweb-font-lock-mode is nil if the prefix argument was <= 0 or there - ;; was no prefix argument and ess-noweb-font-lock-mode is currently `t' - (set (make-local-variable 'ess-noweb-font-lock-mode) - (if arg - (> (prefix-numeric-value arg) 0) - (not ess-noweb-font-lock-mode))) - ;; Now, if ess-noweb-font-lock-mode is true, we want to turn - ;; ess-noweb-font-lock-mode on - (cond - (ess-noweb-font-lock-mode ;Setup the minor-mode - (when (and (boundp 'global-font-lock-mode) global-font-lock-mode) - (mapc #'ess-noweb-make-variable-permanent-local - '(font-lock-fontify-buffer-function - font-lock-unfontify-buffer-function)) - (setq font-lock-fontify-buffer-function #'nwfl-donowt) - (setq font-lock-unfontify-buffer-function #'nwfl-donowt)) - (mapc #'ess-noweb-make-variable-permanent-local - '(ess-noweb-font-lock-mode - font-lock-dont-widen - ;; font-lock-beginning-of-syntax-function - syntax-begin-function - ess-noweb-use-font-lock-mode - after-change-functions)) - (setq ess-noweb-font-lock-mode t - font-lock-dont-widen t) - (add-hook 'after-change-functions - #'font-lock-after-change-function nil t) - ;; FIXME: Why add ess-noweb-font-lock-mode-fn to our own hook, - ;; instead of just calling ess-noweb-font-lock-mode-fn directly? - (add-hook 'ess-noweb-font-lock-mode-hook #'ess-noweb-font-lock-mode-fn) - (add-hook 'ess-noweb-changed-chunk-hook - #'ess-noweb-font-lock-fontify-this-chunk) - (run-hooks 'ess-noweb-font-lock-mode-hook) - (message "ess-noweb-font-lock mode: use `M-x ess-noweb-font-lock-describe-mode' for more info")) - ;; If we didn't do the above, then we want to turn ess-noweb-font-lock-mode - ;; off, no matter what (hence the condition `t') - (t - (when (and (boundp 'global-font-lock-mode) global-font-lock-mode) - ;; (setq font-lock-fontify-buffer-function - ;; 'font-lock-default-fontify-buffer) - ;; Get back our unfontify buffer function - (setq font-lock-unfontify-buffer-function - #'font-lock-default-unfontify-buffer)) - (remove-hook 'ess-noweb-font-lock-mode-hook #'ess-noweb-font-lock-mode-fn) - (remove-hook 'ess-noweb-changed-chunk-hook - #'ess-noweb-font-lock-fontify-this-chunk) - (remove-hook 'after-change-functions - #'font-lock-after-change-function ) - (font-lock-default-unfontify-buffer) - (setq ess-noweb-use-font-lock-mode nil) - (message "ess-noweb-font-lock-mode removed")))) - (message "ess-noweb-font-lock-mode can only be used with ess-noweb-mode"))) - -(defun ess-noweb-start-of-syntax () - "Go to the place to start fontifying from" - (interactive) - (goto-char (car (ess-noweb-chunk-region)))) - -(defvar font-latex-extend-region-functions) -(defvar syntax-begin-function) - -(defun ess-noweb-font-lock-fontify-chunk-by-number ( chunk-num ) - "Fontify chunk CHUNK-NUM based on the current major mode." - (save-excursion - (font-lock-set-defaults) - ;; (setq old-beginning-of-syntax font-lock-beginning-of-syntax-function) - (setq font-lock-keywords - ;; (append font-lock-keywords - ;; '(("\\(\\[\\[\\)\\([^]]*\\]*\\)\\(\\]\\]\\|\\$\\)" - ;; (1 ess-noweb-font-lock-brackets-face prepend ) - ;; (2 ess-noweb-font-lock-code-quote-face prepend) - ;; (3 ess-noweb-font-lock-brackets-face prepend)) - ;; ("^[ \t\n]*\\(<<\\)\\([^>]*\\)\\(>>=?\\)" - ;; (1 ess-noweb-font-lock-brackets-face prepend ) - ;; (2 ess-noweb-font-lock-chunk-name-face prepend) - ;; (3 ess-noweb-font-lock-brackets-face prepend)) - ;; ("^@[ \t\n]+" - ;; (0 ess-noweb-font-lock-doc-start-face prepend ))))) - (append font-lock-keywords - '(("^[ \t\n]*\\(<<\\)\\([^>]*\\)\\(>>=?\\)" - ;; FIXME: Why not use ess-noweb-font-lock-brackets-face? - (1 font-lock-reference-face prepend ) - ;; FIXME: Why not use ess-noweb-font-lock-chunk-name-face? - (2 font-lock-keyword-face prepend) - (3 font-lock-reference-face prepend)) - ("^@[ \t\n]+" - (0 font-lock-reference-face prepend ))))) - - - (let ((r (cons (marker-position (cdr (aref ess-noweb-chunk-vector - chunk-num))) - (marker-position (cdr (aref ess-noweb-chunk-vector - (1+ chunk-num)))))) - (font-latex-extend-region-functions nil);; don't extend anything - (font-lock-extend-region-functions nil)) ;; this infloops :( - (save-restriction - (narrow-to-region (car r) (cdr r)) - ;; (sit-for 3) - (font-lock-fontify-region (car r) (cdr r))) - t))) - - -(defun ess-noweb-font-lock-fontify-this-chunk () - "Fontify this chunk according to its own major mode. -Since we are in the chunk, the major mode will already have been set -by ess-noweb-mode.el" - (interactive) - (ess-noweb-font-lock-fontify-chunk-by-number (ess-noweb-find-chunk-index-buffer))) - -(defun ess-noweb-font-lock-initial-fontify-buffer () - "Applies syntax highlighting to some or all chunks in a noweb buffer. -The number of chunks is set by `ess-noweb-font-lock-max-initial-chunks': if -this is nil, the entire buffer is fontified. -It is intended to be called when first entering `ess-noweb-font-lock-mode'. -For other purposes, use `ess-noweb-font-lock-fontify-chunks'." - (interactive) - ;; This will be tricky. It will be very slow to go throught the chunks - ;; in order, switching major modes all the time. - ;; So, we will do the documentation in one pass, the code in a second - ;; pass. This could still be a little slow if we have to swap between - ;; different code modes regularly, but it should be bearable. It should - ;; only happen when the file is first read in, anyway - (save-excursion - (let (start-chunk end-chunk this-chunk) - (setq this-chunk (ess-noweb-find-chunk-index-buffer)) - (if ess-noweb-font-lock-max-initial-chunks - (progn - (setq start-chunk - (max 0 - (- this-chunk - (/ ess-noweb-font-lock-max-initial-chunks 2)))) - ;; Don't you just love hairy lisp syntax ? The above means set the - ;; starting chunk to the current chunk minus half of - ;; ess-noweb-font-lock-max-initial-chunks, unless that is negative in - ;; which case set it to 0 - (setq end-chunk (+ start-chunk ess-noweb-font-lock-max-initial-chunks)) - (if (> end-chunk (- (length ess-noweb-chunk-vector) 2)) - (setq end-chunk (- (length ess-noweb-chunk-vector) 2)))) - ;; If ess-noweb-font-lock-max-initial-chunks is nil, do the whole buffer - (progn - (setq start-chunk 0) - (setq end-chunk (- (length ess-noweb-chunk-vector) 2)))) - (ess-noweb-font-lock-fontify-chunks start-chunk end-chunk)))) - -(defun ess-noweb-font-lock-fontify-buffer () - "This function will fontify each chunk in the buffer appropriately." - (interactive) - (let ((start-chunk 0) - (end-chunk (- (length ess-noweb-chunk-vector) 2))) - (ess-noweb-font-lock-fontify-chunks start-chunk end-chunk))) - -(defun ess-noweb-font-lock-fontify-chunks (start-chunk end-chunk) - "Fontify a noweb file from START-CHUNK to END-CHUNK." - (interactive) - (let ((chunk-counter start-chunk)) - (save-excursion - (message "Fontifying from %d to %d" start-chunk end-chunk) - ;; Want to set DOC mode for the first Doc chunk, not for the others - (while (stringp (car (aref ess-noweb-chunk-vector chunk-counter))) - (setq chunk-counter (+ chunk-counter 1))) - (goto-char (cdr (aref ess-noweb-chunk-vector chunk-counter))) - (ess-noweb-select-mode) - ;; Now go through the chunks, fontifying the documentation ones. - (while (<= chunk-counter end-chunk) - (if (not (stringp (car (aref ess-noweb-chunk-vector chunk-counter)))) - (ess-noweb-font-lock-fontify-chunk-by-number chunk-counter)) - (message "Fontifying documentation chunks: chunk %d" chunk-counter) - (setq chunk-counter (+ 1 chunk-counter))) - ;; Go back to the start and go through the chunks, fontifying the code ones. - (setq chunk-counter start-chunk) - (message "About to do code chunks") - (while (<= chunk-counter end-chunk) - (when (stringp (car (aref ess-noweb-chunk-vector chunk-counter))) - ;; It's a code chunk: goto it to set the correct code mode, then - ;; fontify it. - (message "Fontifying code chunks: chunk %d" chunk-counter) - (goto-char (cdr (aref ess-noweb-chunk-vector chunk-counter))) - (ess-noweb-select-mode) - (ess-noweb-font-lock-fontify-this-chunk)) - (setq chunk-counter (1+ chunk-counter)))) - (ess-noweb-select-mode))) - -(defun ess-noweb-font-lock-mode-fn() - "Function that is intended to be attached to ess-noweb-font-lock-mode-hook." - (ess-noweb-font-lock-initial-fontify-buffer)) - -;; This is a wee bit of a hack. If people attach `turn-on-font-lock' -;; to their major mode hook, it will play hell with -;; ess-noweb-font-lock-mode. I had hoped that providing a replacement -;; `nw-turn-on-font-lock' would solve the problem, but it didn't -;; (sometimes turn-on-font-lock appears in places other than -;; `.emacs', such as in ESS). So rather than have it fall over if -;; turn-on-lock was around, I redefined turn-on-font-lock to do the -;; right thing. - -(define-obsolete-function-alias 'nw-turn-on-font-lock - #'turn-on-font-lock "ESS-16.11") - -(defadvice turn-on-font-lock (around ess-noweb-font-lock activate) - ;; FIXME: An advice on turn-on-font-lock is definitely not sufficient, - ;; since font-lock can be enabled without going through turn-on-font-lock! - (if (not ess-noweb-mode) - ad-do-it - (if (and (not ess-noweb-font-lock-mode) ess-noweb-use-font-lock-mode) - (ess-noweb-font-lock-mode)))) - -(provide 'ess-noweb-font-lock-mode) -;; ***** -;; -;; Adnan Yaqub (AYaqub@orga.com) -;; ORGA Kartensysteme GmbH // An der Kapelle 2 // D-33104 Paderborn // Germany -;; Tel. +49 5254 991-823 //Fax. +49 5254 991-749 - - -;;; ess-noweb-font-lock-mode.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-noweb-mode.el b/elpa/ess-20191014.1343/obsolete/ess-noweb-mode.el deleted file mode 100644 index 392693c9..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-noweb-mode.el +++ /dev/null @@ -1,1938 +0,0 @@ -;;; ess-noweb-mode.el --- edit noweb files with GNU Emacs - -;; Copyright (C) 1995 by Thorsten.Ohl @ Physik.TH-Darmstadt.de -;; with a little help from Norman Ramsey -;; and Mark Lunt -;; and A.J. Rossini -;; Copyright (C) 1999--2010 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu. - -;; ESS-related Changes first added by Mark Lunt and A.J. Rossini, March, 1999. - -;; Maintainer: ESS-core - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;; See bottom of this file for information on language-dependent -;; highlighting, and recent changes. -;; - -;; BASED ON: (from Mark Lunt). -;; -- Id: ess-noweb-mode.el,v 1.11 1999/03/21 20:14:41 root Exp -- - - -;;; NEWS: - -;; * [tho] M-n q, aka: M-x ess-noweb-fill-chunk -;; -;; * [tho] `M-n TAB', aka: `M-x ess-noweb-complete-chunk' -;; -;; * [tho] ess-noweb-occur -;; -;; * [nr] use `M-n' instead of `C-c n' as default command prefix -;; -;; * [nr] don't be fooled by -;; -;; @ -;; <>= -;; int foo; -;; @ %def foo -;; Here starts a new documentation chunk! -;; <>= -;; int bar; -;; -;; * [nr] switch mode changing commands off during isearch-mode -;; -;; * [tho] ess-noweb-goto-chunk proposes a default -;; -;; * commands for tangling, weaving,.. for Sweave: --> ./ess-swv.el -;; - - -;;; TODO: - -;; * _maybe_ replace our `ess-noweb-chunk-vector' by text properties. We -;; could then use highlighting to jazz up the visual appearance. -;; (Highlighting is sorted: `ess-noweb-chunk-vector' can be -;; ditched. It is simple to determine if we are in a doc or code -;; chunk.) -;; -;; * wrapped `ess-noweb-goto-next' and `ess-noweb-goto-previous' -;; -;; * more range checks and error exits -;; -;; * `ess-noweb-hide-code-quotes' should be superfluous now, and could -;; be removed. For ESS 5.3.10, we disable these, using the new variable -;; ess-noweb-code-quote-handling. If nobody misses that code-protecting -;; behavior, all that should be removed entirely. - -;;; Code: - -(require 'ess-custom) -(require 'ess-utils) - -(defcustom Rnw-mode-hook nil - "Hook run when entering Rnw mode." - :type 'hook - :group 'ess-R) - -(defvar-local ess--make-local-vars-permanent nil - "If this variable is non-nil in a buffer make all variable permannet. -Used in noweb modes.") -(put 'ess--make-local-vars-permanent 'permanent-local t) - -(defvar weave-process) - - -;;; Variables - -;; (defconst ess-noweb-mode-RCS-Id -;; "Imported to ESS Subversion repository and RCS ids not maintained.") - -;; (defconst ess-noweb-mode-RCS-Name -;; " ") - -(defvar-local ess--make-local-vars-permanent nil - "If this variable is non-nil in a buffer make all variable permannet. -Used in noweb modes.") -(put 'ess--make-local-vars-permanent 'permanent-local t) - -(defvar ess-noweb-mode-prefix "\M-n" - "Prefix key to use for noweb mode commands. -The value of this variable is checked as part of loading noweb mode. -After that, changing the prefix key requires manipulating keymaps.") - -(defvar ess-noweb-mode-load-hook nil - "Hook that is run after noweb mode is loaded.") - -(defvar ess-noweb-mode-hook nil - "Hook that is run after entering noweb mode.") - -(defvar ess-noweb-select-code-mode-hook nil - "Hook that is run after the code mode is selected. -This is the place to overwrite keybindings of the ess-noweb-CODE-MODE.") - -(defvar ess-noweb-select-doc-mode-hook nil - "Hook that is run after the documentation mode is selected. -This is the place to overwrite keybindings of the ess-noweb-DOC-MODE.") - -(defvar ess-noweb-select-mode-hook nil - "Hook that is run after the documentation or the code mode is selected. -This is the place to overwrite keybindings of the other modes.") - -(defvar ess-noweb-changed-chunk-hook nil - "Hook that is run every time point moves from one chunk to another. -It will be run whether or not the major-mode changes.") - -(defvar ess-noweb-default-code-mode 'fundamental-mode - "Default major mode for editing code chunks. -This is set to FUNDAMENTAL-MODE by default, but you might want to -change this in the Local Variables section of your file to something -more appropriate, like C-MODE, FORTRAN-MODE, or even -INDENTED-TEXT-MODE.") - -(defvar ess-noweb-code-mode 'c-mode - "Major mode for editing this particular code chunk. -It defaults to ess-noweb-default-code-mode, but can be reset by a comment -on the first line of the chunk containing the string -\"-*- NEWMODE -*-\" or -\"-*- NEWMODE-mode -*-\" or -\"-*- mode: NEWMODE -*- \" or -\"-*- mode: NEWMODE-mode -*- \" -Option three is recommended, as it is the closest to standard emacs usage.") - -(defvar ess-noweb-default-doc-mode 'latex-mode - "Major mode for editing documentation chunks. -Sensible choices would be tex-mode, latex-mode, sgml-mode, or -html-mode. Maybe others will exist someday.") - -(defvar ess-noweb-doc-mode-syntax-table nil - "A syntax-table syntax table that makes quoted code in doc chunks to -behave.") - -(defvar ess-noweb-last-chunk-index 0 - "This keeps track of the chunk we have just been in. If this is not -the same as the current chunk, we have to check if we need to change -major mode.") - -(defvar ess-noweb-chunk-vector nil - "Vector of the chunks in this buffer.") - -(defvar ess-noweb-narrowing nil - "If not NIL, the display will always be narrowed to the -current chunk pair.") - -(defvar ess-noweb-electric-@-and-< t - "If not nil, the keys `@' and `<' will be bound to ess-noweb-ELECTRIC-@ -and ess-noweb-ELECTRIC-<, respectively.") - -(defvar ess-noweb-use-mouse-navigation t - "If not nil, enables moving between chunks using mouse-1. -Clicking on the '<<' at the beginning of a chunk name takes you to the -previous occurence of that chunk name, clicking on the '>>' takes you -to the next. -Assumes mouse-1 is bound to mouse-set-point, so if you have rebound -mouse-1, this will override your binding.") - -(defvar ess-noweb-code-quotes-handling nil - "If not nil, the function pair \\[ess-noweb-hide-code-quotes] and -\\[ess-noweb-restore-code-quotes] are used to \"protect\" code inside -\"[[\" .. \"]]\" pairs. Note that rarely this has been found to be buggy -with the \"catastrophic\" consequence of whole parts of your document being -replaced by sequences of '*'.") - -(defvar ess-noweb-doc-mode ess-noweb-default-doc-mode - "Default major mode for editing noweb documentation chunks. -It is not possible to have more than one doc-mode in a file. -However, this variable is used to determine whether the doc-mode needs -to by added to the mode-line") - -;; The following is apparently broken -- dangling code that was -;; commented out. Need to see if we can get it working? - -(defvar ess-noweb-weave-options "-delay") -(defvar ess-noweb-latex-viewer "xdvi") -(defvar ess-noweb-html-viewer "netscape") - -(defun ess-noweb-weave (&optional name) - (interactive) - (let ((buffer (get-buffer-create "Weave Buffer"))) - (if (not name) - (progn - ;; Assume latex documentation, but set to html if appropriate - (if (eq ess-noweb-doc-mode 'html-mode) - (setq name (concat (substring (buffer-file-name) 0 - (string-match ".nw" name)) - ".html")) - (setq name (concat (substring (buffer-file-name) 0 - (string-match ".nw" name)) - ".tex"))))) - (setq name (concat "> " name)) - (setq ess-noweb-weave-options (concat ess-noweb-weave-options name)) - (start-process weave-process buffer "noweave" ess-noweb-weave-options))) -;;(defun ess-noweb-view ()) - - -;;; Setup -(defvar ess-noweb-mode nil - "Buffer local variable, T iff this buffer is edited in noweb mode.") - -;; For some reason that I do not understand, `newline' does not do the -;; right thing in quoted code. If point is not preceded by whitespace, -;; it moves to the beginning of the current line, not the beginning of -;; the new line. `newline 1' works fine, hence the kludge. I'd love to -;; understand what's going on, though. Try running M-x newline in the -;; middle of a code quote in a doc chunk to see -;; what I mean: its odd. - -(defun ess-noweb-newline (&optional arg) - "A kludge to get round very odd behaviour of newline in quoted code." - (interactive "p") - (if arg (newline arg) (newline 1)) - (ess-noweb-indent-line)) - -(defvar ess-noweb-mode-prefix-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-\M-x" 'ess-eval-chunk) - (define-key map "\C-c" 'ess-eval-chunk-and-step) - (define-key map "\C-n" 'ess-noweb-next-chunk) - (define-key map "\C-p" 'ess-noweb-previous-chunk) - (define-key map "\M-n" 'ess-noweb-goto-next) - (define-key map "\M-m" 'ess-noweb-insert-default-mode-line) - (define-key map "\M-p" 'ess-noweb-goto-previous) - (define-key map "c" 'ess-noweb-next-code-chunk) - (define-key map "C" 'ess-noweb-previous-code-chunk) - (define-key map "d" 'ess-noweb-next-doc-chunk) - (define-key map "D" 'ess-noweb-previous-doc-chunk) - (define-key map "g" 'ess-noweb-goto-chunk) - (define-key map "\C-l" 'ess-noweb-update-chunk-vector) - (define-key map "\M-l" 'ess-noweb-update-chunk-vector) - (define-key map "w" 'ess-noweb-copy-chunk-as-kill) - (define-key map "W" 'ess-noweb-copy-chunk-pair-as-kill) - (define-key map "k" 'ess-noweb-kill-chunk) - (define-key map "K" 'ess-noweb-kill-chunk-pair) - (define-key map "m" 'ess-noweb-mark-chunk) - (define-key map "M" 'ess-noweb-mark-chunk-pair) - (define-key map "n" 'ess-noweb-narrow-to-chunk) - (define-key map "N" 'ess-noweb-narrow-to-chunk-pair) - (define-key map "t" 'ess-noweb-toggle-narrowing) - (define-key map "\t" 'ess-noweb-complete-chunk) - (define-key map "q" 'ess-noweb-fill-chunk) - (define-key map "i" 'ess-noweb-new-chunk) - (define-key map "o" 'ess-noweb-occur) - ;;(define-key map "v" 'ess-noweb-mode-version) - (define-key map "h" 'ess-noweb-describe-mode) - ;; do *NOT* override C-h (give all keybindings startings with M-n! - map) - "noweb minor-mode prefix keymap") - -(defvar ess-noweb-minor-mode-map - (let ((map (make-sparse-keymap))) - (if ess-noweb-electric-@-and-< - (progn - (define-key map "@" 'ess-noweb-electric-@) - (define-key map "<" 'ess-noweb-electric-<))) - (define-key map "\M-q" 'ess-noweb-fill-paragraph-chunk) - (define-key map [(control meta ?\\)] 'ess-noweb-indent-region) - ;;(define-key map "\C-c\C-n" 'ess-noweb-indent-line) ; Override TeX-normal! - (define-key map "\t" 'ess-noweb-indent-line) - ;; (define-key map [tab] 'ess-noweb-indent-line) ;; interferes with ac - (define-key map "\r" 'ess-noweb-newline) - ;; (define-key map [return] 'ess-noweb-newline) ;; interferes with ac - (define-key map [mouse-1] 'ess-noweb-mouse-first-button) - (define-key map ess-noweb-mode-prefix ess-noweb-mode-prefix-map) - map) - "ESS Noweb minor mode keymap") - -(easy-menu-define - ess-noweb-minor-mode-menu ess-noweb-minor-mode-map - "Menu keymap for noweb." - '("Noweb" - ("Movement" - ["Previous chunk" ess-noweb-previous-chunk t] - ["Next chunk" ess-noweb-next-chunk t] - ["Previous chunk of same name" ess-noweb-goto-previous t] - ["Next chunk of same name" ess-noweb-goto-next t] - ["Goto chunk" ess-noweb-goto-chunk t] - ["Previous code chunk" ess-noweb-previous-code-chunk t] - ["Next code chunk" ess-noweb-next-code-chunk t] - ["Previous documentation chunk" ess-noweb-previous-doc-chunk t] - ["Next documentation chunk" ess-noweb-next-doc-chunk t]) - ("Editing" - ["Copy chunk" ess-noweb-copy-chunk-as-kill t] - ["Copy chunk pair" ess-noweb-copy-chunk-pair-as-kill t] - ["Kill chunk" ess-noweb-kill-chunk t] - ["Kill chunk pair" ess-noweb-kill-chunk-pair t] - ["Mark chunk" ess-noweb-mark-chunk t] - ["Mark chunk pair" ess-noweb-mark-chunk-pair t]) - ("Narrowing" - ["Narrow to chunk" ess-noweb-narrow-to-chunk t] - ["Narrow to chunk pair" ess-noweb-narrow-to-chunk-pair t] - ["Toggle auto narrowing" ess-noweb-toggle-narrowing t] - ["Widen" widen t]) - ("Modes" - ["Set documentation mode" ess-noweb-set-doc-mode t] - ["Set default code mode" ess-noweb-set-code-mode t] - ["Set code mode for this chunk" ess-noweb-set-this-code-mode t] - ["Insert default mode line" ess-noweb-insert-default-mode-line t]) - ("Tangling" - ["Tangle current chunk" ess-noweb-tangle-chunk t] - ["Tangle current thread" ess-noweb-tangle-current-thread t] - ["Tangle named thread" ess-noweb-tangle-thread t]) - ("Miscellaneous" - ["Complete chunk name" ess-noweb-complete-chunk t] - ["Fill current chunk" ess-noweb-fill-chunk t] - ["Insert new chunk" ess-noweb-new-chunk t] - ["Update the chunk vector" ess-noweb-update-chunk-vector t] - ["Chunk occurrences" ess-noweb-occur t]) - "--" - ["Help" ess-noweb-describe-mode t] - ;;["Version" ess-noweb-mode-version t] - )) - -;; Add ess-noweb-mode to the list of minor modes -(if (not (assq 'ess-noweb-mode minor-mode-alist)) - (setq minor-mode-alist (append minor-mode-alist - (list '(ess-noweb-mode " Noweb"))))) -;; Add ess-noweb-minor-mode-map to the list of minor-mode keymaps -;; available. Then, whenever ess-noweb-mode is activated, the keymap is -;; automatically activated -(if (not (assq 'ess-noweb-mode minor-mode-map-alist)) - (setq minor-mode-map-alist - (cons (cons 'ess-noweb-mode ess-noweb-minor-mode-map) - minor-mode-map-alist))) - -(defun ess-noweb-minor-mode (&optional arg) - "Minor meta mode for editing noweb files. See ess-noweb-mode." - (interactive) - (ess-noweb-mode arg)) ; this was ess-noweb-minor-mode??? (truly recursive) - -(declare-function ess-noweb-font-lock-mode "ess-noweb-font-lock-mode") - -;;;###autoload -(defun ess-noweb-mode ( &optional arg ) - "Minor meta mode for editing noweb files. -`Meta' refers to the fact that this minor mode is switching major -modes depending on the location of point. - -The following special keystrokes are available in noweb mode: - -Movement: -\\[ess-noweb-next-chunk] \tgoto the next chunk -\\[ess-noweb-previous-chunk] \tgoto the previous chunk -\\[ess-noweb-goto-previous] \tgoto the previous chunk of the same name -\\[ess-noweb-goto-next] \tgoto the next chunk of the same name -\\[ess-noweb-goto-chunk] \t\tgoto a chunk -\\[ess-noweb-next-code-chunk] \t\tgoto the next code chunk -\\[ess-noweb-previous-code-chunk] \t\tgoto the previous code chunk -\\[ess-noweb-next-doc-chunk] \t\tgoto the next documentation chunk -\\[ess-noweb-previous-doc-chunk] \t\tgoto the previous documentation chunk - -Copying/Killing/Marking/Narrowing: -\\[ess-noweb-copy-chunk-as-kill] \t\tcopy the chunk the point is in into the kill ring -\\[ess-noweb-copy-chunk-pair-as-kill] \t\tcopy the pair of doc/code chunks the point is in -\\[ess-noweb-kill-chunk] \t\tkill the chunk the point is in -\\[ess-noweb-kill-chunk-pair] \t\tkill the pair of doc/code chunks the point is in -\\[ess-noweb-mark-chunk] \t\tmark the chunk the point is in -\\[ess-noweb-mark-chunk-pair] \t\tmark the pair of doc/code chunks the point is in -\\[ess-noweb-narrow-to-chunk] \t\tnarrow to the chunk the point is in -\\[ess-noweb-narrow-to-chunk-pair] \t\tnarrow to the pair of doc/code chunks the point is in -\\[widen] \twiden -\\[ess-noweb-toggle-narrowing] \t\ttoggle auto narrowing - -Filling and Indenting: -\\[ess-noweb-fill-chunk] \tfill (or indent) the chunk at point according to mode -\\[ess-noweb-fill-paragraph-chunk] \tfill the paragraph at point, restricted to chunk -\\[ess-noweb-indent-line] \tindent the line at point according to mode - -Insertion: -\\[ess-noweb-insert-default-mode-line] \tinsert a line to set this file's code mode -\\[ess-noweb-new-chunk] \t\tinsert a new chunk at point -\\[ess-noweb-complete-chunk] \tcomplete the chunk name before point -\\[ess-noweb-electric-@] \t\tinsert a `@' or start a new doc chunk -\\[ess-noweb-electric-<] \t\tinsert a `<' or start a new code chunk - -Modes: -\\[ess-noweb-set-doc-mode] \t\tset the major mode for editing doc chunks -\\[ess-noweb-set-code-mode] \tset the major mode for editing code chunks -\\[ess-noweb-set-this-code-mode] \tset the major mode for editing this code chunk - -Misc: -\\[ess-noweb-occur] \t\tfind all occurrences of the current chunk -\\[ess-noweb-update-chunk-vector] \tupdate the markers for chunks -\\[ess-noweb-describe-mode] \tdescribe ess-noweb-mode -" (interactive "P") - ;; This bit is tricky: copied almost verbatim from bib-cite-mode.el - ;; It seems to ensure that the variable ess-noweb-mode is made - ;; local to this buffer. It then sets ess-noweb-mode to `t' if - ;; 1) It was called with an argument greater than 0 - ;; or 2) It was called with no argument, and ess-noweb-mode is - ;; currently nil - ;; ess-noweb-mode is nil if the argument was <= 0 or there - ;; was no argument and ess-noweb-mode is currently `t' - (kill-all-local-variables) - (set (make-local-variable 'ess-noweb-mode) - (if arg - (> (prefix-numeric-value arg) 0) - (not ess-noweb-mode))) - ;; Now, if ess-noweb-mode is true, we want to turn - ;; ess-noweb-mode on - (cond - (ess-noweb-mode ;Setup the minor-mode - (mapc 'ess-noweb-make-variable-permanent-local - '(ess-noweb-mode - ess-local-process-name ;; also made permanent in ess-mode, but let it be - ess-dialect - ess-language - ess-use-flymake - after-change-functions - before-change-functions - ess-noweb-narrowing - ess-noweb-chunk-vector - post-command-hook - isearch-mode-hook - isearch-mode-end-hook - ess-noweb-doc-mode - ess-noweb-code-mode - ess-noweb-default-code-mode - ess-noweb-last-chunk-index)) - (setq-local ess-use-flymake nil) - (ess-noweb-update-chunk-vector) - (setq ess-noweb-last-chunk-index - (if (equal 0 (ess-noweb-find-chunk-index-buffer)) 1 0)) - (if font-lock-mode - (progn - (font-lock-mode -1) - (ess-noweb-font-lock-mode 1))) - (add-hook 'post-command-hook 'ess-noweb-post-command-function) - - (add-hook 'after-change-functions 'ess-noweb-after-change-function nil t) - (add-hook 'before-change-functions 'ess-noweb-before-change-function nil t) - - (add-hook 'ess-noweb-select-doc-mode-hook 'ess-noweb-auto-fill-doc-mode) - (add-hook 'ess-noweb-select-code-mode-hook 'ess-noweb-auto-fill-code-mode) - (add-hook 'isearch-mode-hook 'ess-noweb-note-isearch-mode) - (add-hook 'isearch-mode-end-hook 'ess-noweb-note-isearch-mode-end) - (setq ess-noweb-doc-mode-syntax-table nil) - (run-hooks 'ess-noweb-mode-hook) - (message - "noweb mode: use `M-x ess-noweb-describe-mode' for further information")) - ;; If we didn't do the above, then we want to turn ess-noweb-mode - ;; off, no matter what (hence the condition `t') - (t - (remove-hook 'post-command-hook 'ess-noweb-post-command-function) - - (remove-hook 'after-change-functions 'ess-noweb-after-change-function t) - (remove-hook 'before-change-functions 'ess-noweb-before-change-function t) - - (remove-hook 'ess-noweb-select-doc-mode-hook 'ess-noweb-auto-fill-doc-mode) - (remove-hook 'ess-noweb-select-code-mode-hook 'ess-noweb-auto-fill-code-mode) - (remove-hook 'isearch-mode-hook 'ess-noweb-note-isearch-mode) - (remove-hook 'isearch-mode-end-hook 'ess-noweb-note-isearch-mode-end) - (if (and (boundp 'ess-noweb-font-lock-mode) - ess-noweb-font-lock-mode) - (progn - (ess-noweb-font-lock-mode -1) - (message "ESS-Noweb and ESS-Noweb-Font-Lock Modes Removed")) - (message "ESS-Noweb mode removed"))))) - -(defun ess-noweb-make-variable-permanent-local (var) - "Declare VAR buffer local, but protect it from beeing killed -by major mode changes." - (make-variable-buffer-local var) - (put var 'permanent-local 't)) - -(defun ess-noweb-note-isearch-mode () - "Take note of an incremental search in progress" - (remove-hook 'post-command-hook 'ess-noweb-post-command-function)) - -(defun ess-noweb-note-isearch-mode-end () - "Take note of an incremental search having ended" - (add-hook 'post-command-hook 'ess-noweb-post-command-function)) - -(defun ess-noweb-post-command-function () - "The hook being run after each command in noweb mode." - (ess-noweb-select-mode)) - -(defvar ess-noweb-chunk-boundary-changed nil - "Whether the current change affects a chunk boundary.") - -(defvar ess-noweb-chunk-boundary-regexp "^\\(@[^@]\\)\\|\\(<<\\)") - -(defun ess-noweb-before-change-function (begin end) - "Record changes to chunk boundaries." - (save-excursion - (goto-char begin) - (setq ess-noweb-chunk-boundary-changed - (re-search-forward ess-noweb-chunk-boundary-regexp end t)))) - -(defun ess-noweb-after-change-function (begin end length) - "Function to run after every change in a noweb buffer. -If the changed region contains a chunk boundary, it will update -the chunk vector" - (save-excursion - (goto-char begin) - (when (or ess-noweb-chunk-boundary-changed - (re-search-forward ess-noweb-chunk-boundary-regexp end t)) - (ess-noweb-update-chunk-vector) - (setq ess-noweb-chunk-boundary-changed nil)))) - - -;;; Chunks - -(defun ess-noweb-update-chunk-vector () - "Scan the whole buffer and place a marker at each \"^@\" and \"^<<\". -Record them in ess-noweb-CHUNK-VECTOR." - (interactive) - (save-excursion - (goto-char (point-min)) - (let ((chunk-list (list (cons 'doc (point-marker))))) - (while (re-search-forward "^\\(@\\( \\|$\\|\\( %def\\)\\)\\|<<\\(.*\\)>>=\\)" nil t) - (goto-char (match-beginning 0)) - ;; If the 3rd subexpression matched @ %def, we're still in a code - ;; chunk (sort of), so don't place a marker here. - (if (not (match-beginning 3)) - (setq chunk-list - ;; If the 4th subexpression matched inside <<...>>, - ;; we're seeing a new code chunk. - (cons (cons (if (match-beginning 4) - ;;buffer-substring-no-properties better - ;;than buffer-substring if highlighting - ;;may be used - (buffer-substring-no-properties - (match-beginning 4) (match-end 4)) - 'doc) - (point-marker)) - chunk-list)) - ;; Scan forward either to !/^@ %def/, which will start a docs chunk, - ;; or to /^<<.*>>=$/, which will start a code chunk. - (progn - (forward-line 1) - (while (looking-at "@ %def") - (forward-line 1)) - (setq chunk-list - ;; Now we can tell code vs docs - (cons (cons (if (looking-at "<<\\(.*\\)>>=") - (buffer-substring-no-properties - (match-beginning 1) (match-end 1)) - 'doc) - (point-marker)) - chunk-list)))) - (forward-line 1)) - (setq chunk-list (cons (cons 'doc (point-max-marker)) chunk-list)) - (setq ess-noweb-chunk-vector (vconcat (reverse chunk-list)))))) - -(defun ess-noweb-find-chunk () - "Return a pair consisting of the name (or 'DOC) and the -marker of the current chunk." - (if (not ess-noweb-chunk-vector) - (ess-noweb-update-chunk-vector)) - (aref ess-noweb-chunk-vector (ess-noweb-find-chunk-index-buffer))) - -(defun ess-noweb-chunk-is-code (index) - "Return t if the chunk 'index' is a code chunk, nil otherwise" - (interactive) - (stringp (car (ess-noweb-chunk-vector-aref index)))) - -(defun ess-noweb-in-code-chunk () - "Return t if we are in a code chunk, nil otherwise." - (interactive) - (ess-noweb-chunk-is-code (ess-noweb-find-chunk-index-buffer))) - -(defun ess-noweb-in-mode-line () - "Return the name of the mode to use if we are in a mode line, nil -otherwise." - (interactive) - (let (beg end mode) - (save-excursion - (beginning-of-line 1) - (and (progn - (ess-write-to-dribble-buffer - (format "(n-i-m-l: 1)")) - (search-forward "-*-" - (save-excursion (end-of-line) (point)) - t)) - (progn - (ess-write-to-dribble-buffer - (format "(n-i-m-l: 2)")) - (skip-chars-forward " \t") - (setq beg (point)) - (search-forward "-*-" - (save-excursion (end-of-line) (point)) - t)) - (progn - (ess-write-to-dribble-buffer - (format "(n-i-m-l: 3)")) - (forward-char -3) - (skip-chars-backward " \t") - (setq end (point)) - (goto-char beg) - (setq mode (concat - (downcase (buffer-substring beg end)) - "-mode")) - (if (and (>= (length mode) 11)) - (progn - (if - (equal (substring mode -10 -5) "-mode") - (setq mode (substring mode 0 -5))) - (if - (equal (substring mode 0 5) "mode:") - (setq mode (substring mode 6)))))) - (progn - (ess-write-to-dribble-buffer - (format "(n-i-m-l: 3) mode=%s" mode)) - (intern mode)))))) - -(defun ess-noweb-find-chunk-index-buffer () - "Return the index of the current chunk in ess-noweb-CHUNK-VECTOR." - (ess-noweb-find-chunk-index 0 (1- (length ess-noweb-chunk-vector)))) - -(defun ess-noweb-find-chunk-index (low hi) - (if (= hi (1+ low)) - low - (let ((med (/ (+ low hi) 2))) - (if (< (point) (cdr (aref ess-noweb-chunk-vector med))) - (ess-noweb-find-chunk-index low med) - (ess-noweb-find-chunk-index med hi))))) - -(defun ess-noweb-chunk-region () - "Return a pair consisting of the beginning and end of the current chunk." - (interactive) - (let ((start (ess-noweb-find-chunk-index-buffer))) - (cons (marker-position (cdr (aref ess-noweb-chunk-vector start))) - (marker-position (cdr (aref ess-noweb-chunk-vector (1+ start))))))) - -(defun ess-noweb-copy-code-chunk () - "Copy the current code chunk to the kill ring, excluding the chunk name. -This will be particularly useful when interfacing with ESS." - (interactive) - (let ((r (ess-noweb-chunk-region))) - (save-excursion - (goto-char (car r)) - (if (ess-noweb-in-code-chunk) - (progn - (beginning-of-line 2) - (copy-region-as-kill (point) (cdr r))))))) - -(defun ess-noweb-extract-code-chunk () - "Create a new buffer with the same name as the current code chunk, -and copy all code from chunks of the same name to it." - (interactive) - (save-excursion - (if (ess-noweb-in-code-chunk) - (progn - (let ((chunk-name (car (ess-noweb-find-chunk))) - (chunk-counter 0) - (copy-counter 0) - (this-chunk) (oldbuf (current-buffer))) - (if (get-buffer chunk-name) - (progn - (set-buffer-modified-p nil) - (kill-buffer chunk-name))) - (get-buffer-create chunk-name) - (message "Created buffer %s" chunk-name) - (while (< chunk-counter (- (length ess-noweb-chunk-vector) 2)) - (setq this-chunk (ess-noweb-chunk-vector-aref - chunk-counter)) - (message "Current buffer is %s" (car this-chunk)) - (if (equal chunk-name (car this-chunk)) - (progn - (setq copy-counter (+ copy-counter 1)) - (goto-char (cdr this-chunk)) - (ess-noweb-copy-code-chunk) - (set-buffer chunk-name) - (goto-char (point-max)) - (yank) - (set-buffer oldbuf))) - (setq chunk-counter (+ chunk-counter 1))) - (message "Copied %d bits" copy-counter) - (set-buffer chunk-name) - (copy-region-as-kill (point-min)(point-max))))))) - -(defun ess-noweb-chunk-pair-region () - "Return a pair consisting of the beginning and end of the current pair of -documentation and code chunks." - (interactive) - (let* ((start (ess-noweb-find-chunk-index-buffer)) - (end (1+ start))) - (if (ess-noweb-chunk-is-code start) - (cons (marker-position (cdr (aref ess-noweb-chunk-vector (1- start)))) - (marker-position (cdr (aref ess-noweb-chunk-vector end)))) - (while (not (ess-noweb-chunk-is-code end)) - (setq end (1+ end))) - (cons (marker-position (cdr (aref ess-noweb-chunk-vector start))) - (marker-position (cdr (aref ess-noweb-chunk-vector (1+ end)))))))) - -(defun ess-noweb-chunk-vector-aref (i) - (if (< i 0) - (error "Before first chunk.")) - (if (not ess-noweb-chunk-vector) - (ess-noweb-update-chunk-vector)) - (if (>= i (length ess-noweb-chunk-vector)) - (error "Beyond last chunk.")) - (aref ess-noweb-chunk-vector i)) - -(defun ess-noweb-complete-chunk () - "Complete the chunk name before point, if any." - (interactive) - (if (ess-noweb-in-code-chunk) - (let ((end (point)) - (beg (save-excursion - (if (re-search-backward "<<" - (save-excursion - (beginning-of-line) - (point)) - t) - (match-end 0) - nil)))) - (if beg - (let* ((pattern (buffer-substring beg end)) - (alist (ess-noweb-build-chunk-alist)) - (completion (try-completion pattern alist))) - (cond ((eq completion t)) - ((null completion) - (message "Can't find completion for \"%s\"" pattern) - (ding)) - ((not (string= pattern completion)) - (delete-region beg end) - (insert completion) - (if (not (looking-at ">>")) - (insert ">>"))) - (t - (message "Making completion list...") - (with-output-to-temp-buffer "*Completions*" - (display-completion-list (all-completions pattern alist))) - (message "Making completion list...%s" "done")))) - (message "Not at chunk name..."))) - (message "Not in code chunk..."))) - - -;;; Filling, etc - -(defun ess-noweb-hide-code-quotes () - "Replace all non blank characters in [[...]] code quotes -in the current buffer (you might want to narrow to the interesting -region first) by `*'. Return a list of pairs with the position and -value of the original strings." - (save-excursion - (let ((quote-list nil)) - (goto-char (point-min)) - (while (re-search-forward "\\[\\[" nil 'move) - (let ((beg (match-end 0)) - (end (if (re-search-forward "\\]\\]" nil t) - (match-beginning 0) - (point-max)))) - (goto-char beg) - (while (< (point) end) - ;; Move on to the next word: - (let ((b (progn - (skip-chars-forward " \t\n" end) - (point))) - (e (progn - (skip-chars-forward "^ \t\n" end) - (point)))) - (if (> e b) - ;; Save the string and a marker to the end of the - ;; replacement text. A marker to the beginning is - ;; useless. See ess-noweb-RESTORE-CODE-QUOTES. - (save-excursion - (setq quote-list (cons (cons (copy-marker e) - (buffer-substring b e)) - quote-list)) - (goto-char b) - (insert-char ?* (- e b) t) - (delete-char (- e b)))))))) - (reverse quote-list)))) - -(defun ess-noweb-restore-code-quotes (quote-list) - "Reinsert the strings modified by `ess-noweb-hide-code-quotes'." - (save-excursion - (mapcar (lambda (q) - (let* ((e (marker-position (car q))) - ;; Slightly inefficient, but correct way to find - ;; the beginning of the word to be replaced. - ;; Using the marker at the beginning will loose - ;; if whitespace has been rearranged - (b (save-excursion - (goto-char e) - (skip-chars-backward "*") - (point)))) - (delete-region b e) - (goto-char b) - (insert (cdr q)))) - quote-list))) - -(defun ess-noweb-fill-chunk () - "Fill the current chunk according to mode. -Run `fill-region' on documentation chunks and `indent-region' on code -chunks." - (interactive) - (save-excursion - (save-restriction - (ess-noweb-narrow-to-chunk) - (if (ess-noweb-in-code-chunk) - (progn - ;; Narrow to the code section proper; w/o the first and any - ;; index declaration lines. - (narrow-to-region (progn - (goto-char (point-min)) - (forward-line 1) - (point)) - (progn - (goto-char (point-max)) - (forward-line -1) - (while (looking-at "@") - (forward-line -1)) - (forward-line 1) - (point))) - (if (or indent-region-function indent-line-function) - (indent-region (point-min) (point-max) nil) - (error "No indentation functions defined in %s!" major-mode))) - (if ess-noweb-code-quotes-handling - (let ((quote-list (ess-noweb-hide-code-quotes))) - (fill-region (point-min) (point-max)) - (ess-noweb-restore-code-quotes quote-list)) - (fill-region (point-min) (point-max))))))) - -(defun ess-noweb-indent-region (beg end) - "If region fits inside current chunk, narrow to chunk and then -indent according to mode." - (interactive "r") - (let* ((inx (ess-noweb-find-chunk-index-buffer)) - (ch-beg (marker-position (cdr (aref ess-noweb-chunk-vector inx)))) - (ch-end (marker-position (cdr (aref ess-noweb-chunk-vector (1+ inx)))))) - - (if (and (< ch-beg beg) (> ch-end end)) - (save-excursion - (save-restriction - (setq beg (max beg (progn (goto-char ch-beg) - (forward-line 1) - (point)))) - (setq end (min end (progn (goto-char ch-end) - (forward-line -1) - (point)))) - (narrow-to-region beg end) - (indent-region beg end))) - (indent-region beg end)))) - - -(defun ess-noweb-indent-line () - "Indent the current line according to mode, after narrowing to this chunk." - (interactive) - (ess-noweb-update-chunk-vector) - (save-restriction - (ess-noweb-narrow-to-chunk) - (if (ess-noweb-in-code-chunk) - (progn - ;; Narrow to the code section proper; w/o the first and any - ;; index declaration lines. - (save-excursion - (narrow-to-region (progn - (goto-char (point-min)) - (forward-line 1) - (point)) - (progn - (goto-char (point-max)) - (forward-line -1) - (while (looking-at "@") - (forward-line -1)) - (forward-line 1) - (point)))))) - (indent-according-to-mode))) - -(defun ess-noweb-fill-paragraph-chunk (&optional justify) - "Fill a paragraph in the current chunk." - (interactive "P") - (ess-noweb-update-chunk-vector) - (save-excursion - (save-restriction - (ess-noweb-narrow-to-chunk) - (if (ess-noweb-in-code-chunk) - (progn - ;; Narrow to the code section proper; w/o the first and any - ;; index declaration lines. - (narrow-to-region (progn - (goto-char (point-min)) - (forward-line 1) - (point)) - (progn - (goto-char (point-max)) - (forward-line -1) - (while (looking-at "@") - (forward-line -1)) - (forward-line 1) - (point))) - (fill-paragraph justify)) - (if ess-noweb-code-quotes-handling - (let ((quote-list (ess-noweb-hide-code-quotes))) - (fill-paragraph justify) - (ess-noweb-restore-code-quotes quote-list)) - (fill-paragraph justify)))))) - -(defun ess-noweb-auto-fill-doc-chunk () - "Replacement for `do-auto-fill'." - (save-restriction - (narrow-to-region (car (ess-noweb-chunk-region)) - (save-excursion - (end-of-line) - (point))) - (if ess-noweb-code-quotes-handling - (let ((quote-list (ess-noweb-hide-code-quotes))) - (do-auto-fill) - (ess-noweb-restore-code-quotes quote-list)) - (do-auto-fill)))) - -(defun ess-noweb-auto-fill-doc-mode () - "Install the improved auto fill function, iff necessary." - (if auto-fill-function - (setq auto-fill-function 'ess-noweb-auto-fill-doc-chunk))) - -(defun ess-noweb-auto-fill-code-chunk () - "Replacement for do-auto-fill. Cancel filling in chunk headers" - (unless (save-excursion - (beginning-of-line) - (looking-at "<<")) - (do-auto-fill))) - -(defun ess-noweb-auto-fill-code-mode () - "Install the default auto fill function, iff necessary." - (if auto-fill-function - (setq auto-fill-function 'ess-noweb-auto-fill-code-chunk))) - -;;; Marking - -(defun ess-noweb-mark-chunk () - "Mark the current chunk." - (interactive) - (let ((r (ess-noweb-chunk-region))) - (goto-char (car r)) - (push-mark (cdr r) nil t))) - -(defun ess-noweb-mark-chunk-pair () - "Mark the current pair of documentation and code chunks." - (interactive) - (let ((r (ess-noweb-chunk-pair-region))) - (goto-char (car r)) - (push-mark (cdr r) nil t))) - - -;;; Narrowing - -(defun ess-noweb-toggle-narrowing (&optional arg) - "Toggle if we should narrow the display to the current pair of -documentation and code chunks after each movement. With argument: -switch narrowing on." - (interactive "P") - (if (or arg (not ess-noweb-narrowing)) - (progn - (setq ess-noweb-narrowing t) - (ess-noweb-narrow-to-chunk-pair)) - (setq ess-noweb-narrowing nil) - (widen))) - -(defun ess-noweb-narrow-to-chunk () - "Narrow the display to the current chunk." - (interactive) - (let ((r (ess-noweb-chunk-region))) - (narrow-to-region (car r) (cdr r)))) - -(defun ess-noweb-narrow-to-chunk-pair () - "Narrow the display to the current pair of documentation and code chunks." - (interactive) - (let ((r (ess-noweb-chunk-pair-region))) - (narrow-to-region (car r) (cdr r)))) - - -;;; Killing - -(defun ess-noweb-kill-chunk () - "Kill the current chunk." - (interactive) - (let ((r (ess-noweb-chunk-region))) - (kill-region (car r) (cdr r)))) - -(defun ess-noweb-kill-chunk-pair () - "Kill the current pair of chunks." - (interactive) - (let ((r (ess-noweb-chunk-pair-region))) - (kill-region (car r) (cdr r)))) - -(defun ess-noweb-copy-chunk-as-kill () - "Place the current chunk on the kill ring." - (interactive) - (let ((r (ess-noweb-chunk-region))) - (copy-region-as-kill (car r) (cdr r)))) - -(defun ess-noweb-copy-chunk-pair-as-kill () - "Place the current pair of chunks on the kill ring." - (interactive) - (let ((r (ess-noweb-chunk-pair-region))) - (copy-region-as-kill (car r) (cdr r)))) - - -;;; Movement - -(defun ess-noweb-sign (n) - "Return the sign of N." - (if (< n 0) -1 1)) - -(defun ess-noweb-next-doc-chunk (&optional cnt) - "Goto to the Nth documentation chunk from point." - (interactive "p") - (widen) - (let ((start (ess-noweb-find-chunk-index-buffer)) - (i 1)) - (while (<= i (abs cnt)) - (setq start (+ (ess-noweb-sign cnt) start)) - (while (ess-noweb-chunk-is-code start) - (setq start (+ (ess-noweb-sign cnt) start))) - (setq i (1+ i))) - (goto-char (marker-position (cdr (ess-noweb-chunk-vector-aref start)))) - (forward-char 1)) - (if ess-noweb-narrowing - (ess-noweb-narrow-to-chunk-pair))) - -(defun ess-noweb-previous-doc-chunk (&optional n) - "Goto to the -Nth documentation chunk from point." - (interactive "p") - (ess-noweb-next-doc-chunk (- n))) - -(defun ess-noweb-next-code-chunk (&optional cnt) - "Goto to the Nth code chunk from point." - (interactive "p") - (widen) - (let ((start (ess-noweb-find-chunk-index-buffer)) - (i 1)) - (while (<= i (abs cnt)) - (setq start (+ (ess-noweb-sign cnt) start)) - (while (not (ess-noweb-chunk-is-code start)) - (setq start (+ (ess-noweb-sign cnt) start))) - (setq i (1+ i))) - (goto-char (marker-position (cdr (ess-noweb-chunk-vector-aref start)))) - (forward-line 1)) - (if ess-noweb-narrowing - (ess-noweb-narrow-to-chunk-pair))) - -(defun ess-noweb-previous-code-chunk (&optional n) - "Goto to the -Nth code chunk from point." - (interactive "p") - (ess-noweb-next-code-chunk (- n))) - -(defun ess-noweb-next-chunk (&optional n) - "If in a documentation chunk, goto to the Nth documentation -chunk from point, else goto to the Nth code chunk from point." - (interactive "p") - (if (ess-noweb-in-code-chunk) - (ess-noweb-next-code-chunk n) - (ess-noweb-next-doc-chunk n))) - -(defun ess-noweb-previous-chunk (&optional n) - "If in a documentation chunk, goto to the -Nth documentation -chunk from point, else goto to the -Nth code chunk from point." - (interactive "p") - (ess-noweb-next-chunk (- n))) - -(defvar ess-noweb-chunk-history nil - "") - -(defun ess-noweb-goto-chunk () - "Goto the named chunk." - (interactive) - (widen) - (let* ((completion-ignore-case t) - (alist (ess-noweb-build-chunk-alist)) - (chunk (ess-completing-read - "Chunk" (delete "" (mapcar 'car alist)) nil t nil - ess-noweb-chunk-history (ess-noweb-goto-chunk-default)))) - (goto-char (cdr (assoc chunk alist)))) - (if ess-noweb-narrowing - (ess-noweb-narrow-to-chunk-pair))) - -(defun ess-noweb-goto-chunk-default () - (save-excursion - (if (re-search-backward "<<" - (save-excursion - (beginning-of-line) - (point)) - 'move) - (goto-char (match-beginning 0))) - (if (re-search-forward "<<\\(.*\\)>>" - (save-excursion - (end-of-line) - (point)) - t) - (buffer-substring (match-beginning 1) (match-end 1)) - nil))) - -(defun ess-noweb-build-chunk-alist () - (if (not ess-noweb-chunk-vector) - (ess-noweb-update-chunk-vector)) - ;; The naive recursive solution will exceed MAX-LISP-EVAL-DEPTH in - ;; buffers w/ many chunks. Maybe there is a tail recursivce solution, - ;; but iterative solutions should be acceptable for dealing with vectors. - (let ((alist nil) - (i (1- (length ess-noweb-chunk-vector)))) - (while (>= i 0) - (let* ((chunk (aref ess-noweb-chunk-vector i)) - (name (car chunk)) - (marker (cdr chunk))) - (if (and (stringp name) - (not (assoc name alist))) - (setq alist (cons (cons name marker) alist)))) - (setq i (1- i))) - alist)) - -(defun ess-noweb-goto-next (&optional cnt) - "Goto the continuation of the current chunk." - (interactive "p") - (widen) - (if (not ess-noweb-chunk-vector) - (ess-noweb-update-chunk-vector)) - (let ((start (ess-noweb-find-chunk-index-buffer))) - (if (not (ess-noweb-chunk-is-code start)) - (setq start (1+ start))) - (if (ess-noweb-chunk-is-code start) - (let ((name (car (ess-noweb-chunk-vector-aref start))) - (i 1)) - (while (<= i (abs cnt)) - (setq start (+ (ess-noweb-sign cnt) start)) - (while (not (equal (car (ess-noweb-chunk-vector-aref start)) - name)) - (setq start (+ (ess-noweb-sign cnt) start))) - (setq i (1+ i))) - (goto-char (marker-position - (cdr (ess-noweb-chunk-vector-aref start)))) - (forward-line 1)))) - (if ess-noweb-narrowing - (ess-noweb-narrow-to-chunk-pair))) - -(defun ess-noweb-goto-previous (&optional cnt) - "Goto the previous chunk." - (interactive "p") - (ess-noweb-goto-next (- cnt))) - -(defun ess-noweb-occur (arg) - "Find all occurences of the current chunk. -This function simply runs OCCUR on \"<>\"." - (interactive "P") - (let ((n (if (and arg - (numberp arg)) - arg - 0)) - (idx (ess-noweb-find-chunk-index-buffer))) - (if (ess-noweb-chunk-is-code idx) - (occur (regexp-quote (concat "<<" - (car (aref ess-noweb-chunk-vector idx)) - ">>")) - n) - (setq idx (1+ idx)) - (while (not (ess-noweb-chunk-is-code idx)) - (setq idx (1+ idx))) - (occur (regexp-quote (concat "<<" - (car (aref ess-noweb-chunk-vector idx)) - ">>")) - n)))) - - -;;; Insertion - -(defun ess-noweb-new-chunk (name) - "Insert a new chunk." - (interactive "sChunk name: ") - (insert "@ \n<<" name ">>=\n") - (save-excursion - (insert "@ %def \n")) - (ess-noweb-update-chunk-vector)) - -(defun ess-noweb-at-beginning-of-line () - (equal (save-excursion - (beginning-of-line) - (point)) - (point))) - -(defun ess-noweb-electric-@ (arg) - "Smart incarnation of `@', starting a new documentation chunk, maybe. -If given an numerical argument, it will act just like the dumb `@'. -Otherwise and if at the beginning of a line in a code chunk: -insert \"@ \" and update the chunk vector." - (interactive "P") - (if arg - (self-insert-command (if (numberp arg) arg 1)) - (if (and (ess-noweb-at-beginning-of-line) - (ess-noweb-in-code-chunk)) - (progn - (insert "@ ") - (ess-noweb-update-chunk-vector)) - (self-insert-command 1)))) - -(defun ess-noweb-electric-< (arg) - "Smart incarnation of `<', starting a new code chunk, maybe. -If given an numerical argument, it will act just like the dumb `<'. -Otherwise and if at the beginning of a line in a documentation chunk: -insert \"<<>>=\", a closing \"@\" and a newline if necessary. Leave point -in the middle and and update the chunk vector." - (interactive "P") - (if arg - (self-insert-command (if (numberp arg) arg 1)) - (if (and (ess-noweb-at-beginning-of-line) - (not (ess-noweb-in-code-chunk))) - (progn - (insert "<<") - (save-excursion - (insert ">>=\n@ ") - (if (not (looking-at "\\s *$")) - (newline))) - (ess-noweb-update-chunk-vector)) - (self-insert-command 1)))) - - -;;; Modes - -(defun ess-noweb-set-chunk-code-mode () - "Set the ess-noweb-code-mode for the current chunk" - (interactive) - (if (ess-noweb-in-code-chunk) - (progn - ;; Reset code-mode to default and then check for a mode comment. - (setq ess-noweb-code-mode ess-noweb-default-code-mode) - (let (mode chunk-name) - (save-excursion - (save-restriction - (end-of-line) - (re-search-backward "^[ \t]*<<\\(.*\\)>>=" nil t) - (setq chunk-name (match-string 1)) - (widen) - (goto-char (point-min)) - (re-search-forward (concat "^<<" (regexp-quote chunk-name) ">>=") nil t) - (beginning-of-line 2) - (setq mode (ess-noweb-in-mode-line)) - (if (functionp mode) - (setq ess-noweb-code-mode mode)))))) - (error "This only makes sense in a code chunk"))) - -(defun ess-noweb-set-doc-syntax-table () - "Sets the doc-mode syntax-table to treat code quotes as comments." - (interactive) - (let ((square-bracket-string (char-to-string (char-syntax ?\[)))) - (if (string= square-bracket-string "(") - (progn - (modify-syntax-entry ?\[ "(]12b" ess-noweb-doc-mode-syntax-table) - (modify-syntax-entry ?\] ")[34b" ess-noweb-doc-mode-syntax-table)) - (progn - (modify-syntax-entry ?\[ - (concat square-bracket-string " 12b") - ess-noweb-doc-mode-syntax-table) - (modify-syntax-entry ?\] - (concat square-bracket-string " 34b") - ess-noweb-doc-mode-syntax-table))))) - -(defun ess-noweb-select-mode () - "Select ess-noweb-DOC-MODE or ess-noweb-CODE-MODE, as appropriate." - (interactive) - (let ((this-chunk-index (ess-noweb-find-chunk-index-buffer))) - ;; Has the last change to the buffer taken us into a different - ;; chunk ? - (if (not (equal this-chunk-index ess-noweb-last-chunk-index)) - (progn - (setq ess-noweb-last-chunk-index this-chunk-index) - (if (ess-noweb-in-code-chunk) - ;; Inside a code chunk - (progn - ;; Find out which code mode to use - (ess-noweb-set-chunk-code-mode) - ;; If we aren't already using it, use it. - (if (not (equal major-mode ess-noweb-code-mode)) - (progn - (funcall ess-noweb-code-mode) - (run-hooks 'ess-noweb-select-mode-hook) - (run-hooks 'ess-noweb-select-code-mode-hook)))) - ;; Inside a documentation chunk - (progn - (if (not (equal major-mode ess-noweb-doc-mode)) - (progn - (funcall ess-noweb-doc-mode))) - (if (not ess-noweb-doc-mode-syntax-table) - (progn - (message "Setting up syntax table") - (setq ess-noweb-doc-mode-syntax-table - (make-syntax-table (syntax-table))) - (ess-noweb-set-doc-syntax-table))) - (set-syntax-table ess-noweb-doc-mode-syntax-table) - (run-hooks 'ess-noweb-select-mode-hook) - (run-hooks 'ess-noweb-select-doc-mode-hook))) - (run-hooks 'ess-noweb-changed-chunk-hook))))) - -(defun ess-noweb-set-doc-mode (mode) - "Change the major mode for editing documentation chunks." - (interactive "CNew major mode for documentation chunks: ") - (setq ess-noweb-doc-mode mode) - (setq ess-noweb-doc-mode-syntax-table nil) - ;;Pretend we've changed chunk, so the mode will be reset if necessary - (setq ess-noweb-last-chunk-index (1- ess-noweb-last-chunk-index)) - (ess-noweb-select-mode)) - -(defun ess-noweb-set-code-mode (mode) - "Change the major mode for editing all code chunks." - (interactive "CNew major mode for all code chunks: ") - (setq ess-noweb-default-code-mode mode) - ;;Pretend we've changed chunk, so the mode will be reset if necessary - (setq ess-noweb-last-chunk-index (1- ess-noweb-last-chunk-index)) - (ess-noweb-select-mode)) - -(defun ess-noweb-set-this-code-mode (mode) - "Change the major mode for editing this code chunk. -The only sensible way to do this is to add a mode line to the chunk" - (interactive "CNew major mode for this code chunk: ") - (if (ess-noweb-in-code-chunk) - (progn - (setq ess-noweb-code-mode mode) - (save-excursion - (save-restriction - (let (chunk-name) - (widen) - (end-of-line) - (re-search-backward "^[ \t]*<<\\(.*\\)>>=" nil t) - (setq chunk-name (match-string 1)) - (goto-char (point-min)) - (re-search-forward (concat "^<<" (regexp-quote chunk-name) ">>=") nil t) - (beginning-of-line 2)) - ;; remove mode-line, if there is one - (if (ess-noweb-in-mode-line) - (progn - (kill-line) - (kill-line))) - (if (not (equal ess-noweb-code-mode ess-noweb-default-code-mode)) - (progn - (setq mode (substring (symbol-name mode) 0 -5)) - ;; Need to set major mode so that we can comment out - ;; the mode line - (funcall ess-noweb-code-mode) - (if (not (boundp 'comment-start)) - (setq comment-start "#")) - (insert comment-start - " -*- " mode - " -*- " comment-end "\n"))) - (setq ess-noweb-last-chunk-index (1- ess-noweb-last-chunk-index))))) - (message "This only makes sense in a code chunk."))) - -;;; Misc - -(defvar ess-version) -(defun ess-noweb-mode-version () - "Echo the RCS identification of noweb mode." - (interactive) - (message "Thorsten's ess-noweb-mode, now part of ESS version %s" ess-version)) - -(defun ess-noweb-describe-mode () - "Describe noweb mode." - (interactive) - (describe-function 'ess-noweb-mode)) - -(defun ess-noweb-insert-default-mode-line () - "Insert line that will set the noweb mode of this file in emacs. -The file is set to use the current doc and default-code modes, so -ensure they are set correctly (with ess-noweb-set-code-mode and -ess-noweb-set-doc-mode) before calling this function" - (interactive) - (save-excursion - (goto-char 1) - (if (ess-noweb-in-mode-line) - (progn - (kill-line) - (kill-line))) - (if (not (eq major-mode ess-noweb-doc-mode)) - (ess-noweb-select-mode)) - (insert comment-start " -*- mode: noweb; ess-noweb-default-code-mode: " - (symbol-name ess-noweb-default-code-mode) - (if (not (eq ess-noweb-doc-mode ess-noweb-default-doc-mode)) - (concat "; ess-noweb-doc-mode: " (symbol-name - ess-noweb-doc-mode) ";") - ";") - " -*-" comment-end "\n")) - (ess-noweb-select-mode)) - -(defun ess-noweb-mouse-first-button (event) - (interactive "e") - (mouse-set-point event) - (if (and ess-noweb-use-mouse-navigation - (eq (save-excursion - (end-of-line) - (re-search-backward "^[\t ]*\\(<<\\)\\(.*\\)\\(>>\\)" nil t)) - (save-excursion - (beginning-of-line) (point)))) - (progn - (if (< (point) (match-beginning 2)) - (let ((chunk-name (buffer-substring-no-properties - (match-beginning 2) - (match-end 2)))) - (re-search-backward (concat "<<" (regexp-quote chunk-name) ">>") nil t)) - (if (and (<= (match-end 2) (point)) - (> (+ 2 (match-end 2)) (point))) - (let ((chunk-name (buffer-substring-no-properties - (match-beginning 2) - (match-end 2)))) - (re-search-forward (concat "<<" (regexp-quote chunk-name) ">>") nil t))))))) - - -;;; Debugging - -(defun ess-noweb-log (s) - (let ((b (current-buffer))) - (pop-to-buffer-same-window (get-buffer-create "*noweb-log*")) - (goto-char (point-max)) - (setq buffer-read-only nil) - (insert s) - (setq buffer-read-only t) - (pop-to-buffer-same-window b))) - - - - - -(defvar ess-noweb-thread-alist nil - "A list of threads in the current buffer. -Each entry in the list contains 5 elements: -1) The name of the threads -2) The name of the immdiate parent thread in which it is used (nil if - it is a \"top-level\" thread which is not used anywhere). -3) The name of the top-level parent thread in which it is used (i.e. a - thread in which it is used but which is not itself used anywhere: - nil if this thread is not used anywhere. -4) The format string to use to define line numbers in the output - file of this thread. Should only be set if this thread is not used - anywhere: if a thread is used as part of another thread, the parent - thread's format string should be used. -5) If this is nil, tabs are converted to spaces in the tangled - file. If it is a number, tabs are copied to the tangled file - unchanged, and tabs are also used for indentation, with the number - of spaces per tab defined by this number. This MUST be set in order - to tangle makefiles, which depend on tabs.Should only be set if - this thread is not used anywhere. otherwise set to nil. " - ) - -(defun ess-noweb-update-thread-alist () - "Updates the list of threads in the current buffer. -Each entry in the list contains 5 elements: -1) The name of the thread -2) The name of the immdiate parent thread in which it is used (nil if - it is a \"top-level\" thread which is not used anywhere). -3) The name of the top-level parent thread in which it is used (i.e. a - thread in which it is used but which is not itself used anywhere: - nil if this thread is not used anywhere. -4) The format string to use to define line numbers in the output - file of this thread. Should only be set if this thread is not used - anywhere: if a thread is used as part of another thread, the parent - thread's format string should be used. -5) If this is nil, tabs are converted to spaces in the tangled - file. If it is a number, tabs are copied to the tangled file - unchanged, and tabs are also used for indentation, with the number - of spaces per tab defined by this number. This MUST be set in order - to tangle makefiles, which depend on tabs.Should only be set if - this thread is not used anywhere. otherwise set to nil. " - (interactive) - (save-excursion - (goto-char (point-min)) - (let ((thread-alist) (thread-list-entry) (chunk-use-name) - (current-thread) (new-thread-alist)) - (while (re-search-forward - "^[ \t]*<<\\(.*\\)>>\\(=\\)?" nil t) - (goto-char (match-beginning 0)) - ;; Is this the definition of a chunk ? - (if (match-beginning 2) - ;;We have a chunk definition - (progn - ;; Get the thread name - (setq current-thread - (buffer-substring-no-properties (match-beginning 1) - (match-end 1))) - ;; Is this thread already in our list ? - (if (assoc current-thread thread-alist) - nil - (progn - ;; If not, create an entry with 4 nils at the end - (setq thread-list-entry - (list (cons current-thread - (make-list 4 nil)))) - ;; And add it to the list - (setq thread-alist - (append thread-alist thread-list-entry))))) - - ;; Not a definition but a use - (progn - ;; Get the thread name - (setq chunk-use-name - (buffer-substring-no-properties (match-beginning 1) - (match-end 1))) - ;; Has the thread already been defined before being used ? - (if (setq thread-list-entry (assoc chunk-use-name - thread-alist)) - ;; If it has, set its parent to be the thread we are in at the moment - (setcar (cdr thread-list-entry) current-thread) - ;; If not, add it to the list, with its parent name and 3 nils - (progn - (setq thread-list-entry - (list (cons chunk-use-name - (cons current-thread - (make-list 3 nil))))) - (setq thread-alist (append thread-alist thread-list-entry))))) - ) - ;;Go to the next line - (beginning-of-line 2)) - ;; Now, the second element of each entry points to that thread's - ;; immediate parent. Need to set it to the thread's ultimate - ;; parent. - (let ((thread-counter 0) - (this-thread) - (this-thread-parent)) - (while (<= thread-counter (1- (length thread-alist))) - (setq this-thread (nth thread-counter thread-alist)) - (setq this-thread-parent (assoc - (car (cdr this-thread)) - thread-alist)) - (while (not (equal nil (car (cdr this-thread-parent)))) - (setq this-thread-parent (assoc - (car (cdr this-thread-parent)) - thread-alist))) - (setq this-thread (cons (car this-thread) - (cons (car (cdr this-thread)) - (cons (car this-thread-parent) - (nthcdr 2 this-thread))))) - (setq new-thread-alist (append new-thread-alist (list this-thread))) - (setq thread-counter (1+ thread-counter)))) - - (setq ess-noweb-thread-alist new-thread-alist)))) - - - ; Option setting functions to go here - -(defun ess-noweb-set-thread-line-format ()) - -(defun ess-noweb-set-thread-tabs ()) - - -(defvar ess-noweb-default-line-number-format nil - "The format string to use to define line numbers in this thread. -If nil, do not use line numbers.") - -(defvar ess-noweb-default-line-number-skip-lines 0 - "The number of initial lines to output before the line number. -This may be useful in shell scripts, where the first line (or two) must have a - specific form.") - -(defvar ess-noweb-default-tab-width 8 - "If a number, convert tabs to that number of spaces in the output. If nil, let tabs through to the output unaltered.") - -(defvar ess-noweb-line-number-format ess-noweb-default-line-number-format - "The format string to use to define line numbers in this thread. -If nil, do not use line numbers.") - -(defvar ess-noweb-line-number-skip-lines ess-noweb-default-line-number-skip-lines - "The number of initial lines to output before the line number. -This may be useful in shell scripts, where the first line (or two) must have a - specific form.") - -(defvar ess-noweb-tab-width ess-noweb-default-tab-width - "If a number, convert tabs to that number of spaces in the output. If nil, let tabs through to the output unaltered.") - -(defun ess-noweb-get-thread-local-variables () - "Get the values of the variables that are local to a thread." - (interactive) - (save-excursion - (save-restriction - (end-of-line) - (re-search-backward "^[ \t]*<<\\(.*\\)>>=" nil t) - (let ((chunk-name (match-string 1))) - (widen) - (goto-char (point-min)) - (re-search-forward (concat "^<<" (regexp-quote chunk-name) ">>=") nil t) - (beginning-of-line 2) - (while (looking-at ".*-\*-.*-\*-") - (let ((this-line (buffer-substring-no-properties - (point) - (progn (end-of-line) (point))))) - (if (string-match - "mode:[ \t]*\\([^\t ]*\\)" this-line) - (setq ess-noweb-code-mode - (match-string-no-properties 1 this-line))) - (if (string-match - "ess-noweb-line-number-format:[ \t]*\"\\([^\"]*\\)\"" this-line) - (setq ess-noweb-line-number-format - (match-string-no-properties 1 this-line))) - (if (string-match - "ess-noweb-line-number-skip-lines:[ \t]*\\([^\t ]*\\)" this-line) - (setq ess-noweb-line-number-skip-lines - (string-to-number - (match-string-no-properties 1 this-line)))) - (if (string-match - "ess-noweb-tab-width:[ \t]*\\([^\t ]*\\)" this-line) - (setq ess-noweb-tab-width - (string-to-number - (match-string-no-properties 1 this-line)))) - (beginning-of-line 2))))))) - -(defun ess-noweb-reset-thread-local-variables () - "Resets the thread-local variables to their default values" - (setq ess-noweb-tab-width ess-noweb-default-tab-width) - (setq ess-noweb-line-number-format ess-noweb-default-line-number-format) - (setq ess-noweb-line-number-skip-lines ess-noweb-default-line-number-skip-lines)) - -(defun ess-noweb-write-line-number (line-number-format buffer) - (if line-number-format - (progn - (let ((this-line (count-lines (point-min)(point)))) - (while (string-match ".*\\(%L\\).*" line-number-format) - (setq line-number-format - (replace-match - (format "%d" this-line) t t line-number-format 1))) - (while (string-match ".*\\(%F\\).*" line-number-format) - (setq line-number-format - (replace-match - (format "%s" (buffer-file-name)) t t line-number-format 1))) - (while (string-match ".*\\(%N\\).*" line-number-format) - (setq line-number-format - (replace-match "\n" t t line-number-format 1))) - (with-current-buffer buffer - (insert line-number-format)))))) - - -(defun ess-noweb-tangle-chunk ( &optional buffer prefix-string) - "Generate the code produced by this chunk, & any threads used in this chunk." - (interactive) - (save-excursion - (ess-noweb-reset-thread-local-variables) - (ess-noweb-get-thread-local-variables) - (ess-noweb-update-chunk-vector) - (let* - ((chunk-end (progn - (end-of-line) - (re-search-forward "^@" nil t) - (beginning-of-line) - (point))) - ;;get name and start point of this chunk - (chunk-start (progn - (re-search-backward "^<<\\([^>]*\\)>>=$" nil t) - (beginning-of-line 2) - (point))) - (chunk-name (buffer-substring-no-properties - (match-end 1) - (match-beginning 1))) - ;; get end of this chunk - ;; Get information we need about this thread - (thread-info (assoc chunk-name ess-noweb-thread-alist)) - (thread-tabs (nth 4 thread-info)) - (line-number-format (nth 3 thread-info)) - (thread-name-re) (post-chunk) (pre-chunk) - (first-line t) - (tangle-buffer (generate-new-buffer "Tangle Buffer"))) - - (progn - (goto-char chunk-start) - ;; If this is a mode-line, ignore it - (while (looking-at ".*-\\*-.*-\\*-") - (beginning-of-line 2)) - ;; If we want to include line numbers, write one - (if line-number-format - (while (> ess-noweb-line-number-skip-lines 0) - (append-to-buffer tangle-buffer - (point) - (save-excursion - (progn - (end-of-line) - (point)))) - (beginning-of-line 2) - (1- ess-noweb-line-number-skip-lines)) - (ess-noweb-write-line-number line-number-format buffer)) - (message "Now at %d" (point)) - - (while (< (point) chunk-end) - (untabify (point) (save-excursion (beginning-of-line 2)(point))) - ;; This RE gave me trouble. Without the `\"', it - ;; recognised itself and so could not copy itself - ;; correctly. - (if (looking-at - "\\([^\n\"@]*\\)<<\\(.*\\)\\(>>\\)\\([^\n\"]*\\)$") - (progn - (save-excursion - (save-restriction - (setq thread-name-re - (concat "<<" - (regexp-quote (match-string 2)) - ">>=")) - (setq pre-chunk (match-string 1)) - (if prefix-string - (setq pre-chunk (concat prefix-string - pre-chunk))) - (setq post-chunk (match-string 4)) - (widen) - (goto-char (point-min)) - (while (re-search-forward thread-name-re nil t) - (ess-noweb-tangle-chunk tangle-buffer pre-chunk) - (forward-line 1))) - (if post-chunk - (with-current-buffer tangle-buffer - (backward-char) - (insert post-chunk) - (beginning-of-line 2))))) - - ;; Otherwise, just copy this line - (setq pre-chunk - (buffer-substring - (point) - (save-excursion - (beginning-of-line 2) - (point)))) - ;; Add a prefix if necessary - (if (and prefix-string - (> (length pre-chunk) 1)) - (setq pre-chunk (concat prefix-string - pre-chunk))) - ;; And copy it to the buffer - (with-current-buffer tangle-buffer - (insert pre-chunk))) - ;; If this is the first line of the chunk, we need to change - ;; prefix-string to consist solely of spaces - (if (and first-line - prefix-string) - (progn - (setq prefix-string - (make-string (length prefix-string) ?\ )) - (setq first-line nil))) - ;; Either way, go to the next line - (beginning-of-line 2)) - - (with-current-buffer tangle-buffer - (goto-char (point-min)) - (while (re-search-forward "\@\<<" nil t) - (replace-match "<<" nil nil) - (forward-char 3)) - (if thread-tabs - (progn - (setq tab-width thread-tabs) - (tabify (point-min)(point-max))) - (untabify (point-min)(point-max)))) - - (if buffer - (with-current-buffer buffer - (insert-buffer-substring tangle-buffer) - (kill-buffer tangle-buffer))) - )))) - -(defun ess-noweb-tangle-thread ( name &optional buffer) - "Given the name of a thread, tangles the thread to buffer. -If no buffer is given, create a new one with the same name as the -thread." - (interactive "sWhich thread ? ") - (if (not buffer) - (progn - (setq buffer (get-buffer-create name)) - (with-current-buffer buffer - (erase-buffer)))) - (save-excursion - (goto-char (point-min)) - (let ((chunk-counter 0)) - (while (re-search-forward - "^<<\\(.*\\)>>=[\t ]*" nil t) - (if (string= (match-string 1) - name) - (progn - (setq chunk-counter (1+ chunk-counter)) - (message "Found %d chunks" chunk-counter) - (ess-noweb-tangle-chunk buffer))))))) - -(defun ess-noweb-tangle-current-thread ( &optional buffer) - (interactive) - (save-excursion - (let* ((chunk-start - (progn - (re-search-backward "^<<\\([^>]*\\)>>=[\t ]*$" - nil t) - (beginning-of-line 2) - (point))) - (chunk-name (buffer-substring-no-properties - (match-end 1) - (match-beginning 1)))) - (ess-noweb-tangle-thread chunk-name buffer)))) - ;menu functions - -;;;###autoload -(defun Rnw-mode () - "Major mode for editing Sweave(R) source. -See `ess-noweb-mode' and `R-mode' for more help." - (interactive) - (require 'ess-noweb);; << probably someplace else - (setq ess--make-local-vars-permanent t) - (ess-noweb-mode 1); turn it on - (ess-noweb-set-doc-mode 'latex-mode) - (ess-noweb-set-code-mode 'R-mode) - (setq ess--local-handy-commands - (append '(("weave" . ess-swv-weave) - ("tangle" . ess-swv-tangle)) - ess-handy-commands) - ess-dialect "R" - ess-language "S") - (put 'ess--local-handy-commands 'permanent-local t) - (run-mode-hooks 'Rnw-mode-hook)) - -(fset 'Snw-mode 'Rnw-mode); just a synonym (for now or ever) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[rR]nw\\'" . Rnw-mode)) -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.[sS]nw\\'" . Snw-mode)) - - -;;; Finale - -(run-hooks 'ess-noweb-mode-load-hook) -(provide 'ess-noweb-mode) - -;; Changes made by Mark Lunt (mark.lunt@mrc-bsu.cam.ac.uk) 22/03/1999 - -;; The possibility of having code chunks using more than one language -;; was added. This was first developed by Adnan Yaqub -;; (AYaqub@orga.com) for syntax highlighting, but even people who hate -;; highlighting may like to maintain their Makefile with their code, -;; or test-scripts with their programs, or even user documentation as -;; latex-mode code chunks. -;; This required quite a few changes to ess-noweb-mode: -;; 1) A new variable `ess-noweb-default-code-mode' was create to do the job -;; `ess-noweb-code-mode' used to. -;; 2) ess-noweb-code-mode now contains the code-mode of the current chunk -;; 3) Each chunk can now have its own mode-line to tell emacs what -;; mode to use to edit it. The function `ess-noweb-in-mode-line' -;; recognises such mode-lines, and the function -;; `ess-noweb-set-this-code-mode' sets the code mode for the current -;; chunk and adds a mode-line if necessary. If several chunks have -;; the same name, the mode-line must appear in the first chunk with -;; that name. -;; 4) The mechanism for deciding whether to change mode was altered, -;; since the old method assumed a single code mode. Now, -;; `ess-noweb-last-chunk-index' keeps track of which chunk we were in -;; last. If we have moved to a different chunk, we have to check -;; which mode we should be in, and change if necessary. - -;; The keymap and menu-map handling was changed. Easymenu was used to -;; define the menu, and it the keymap was attached to the 'official' -;; minor-modes-keymaps list. This means that -;; 1) It was automatically loaded when ess-noweb-mode was active and -;; unloaded when it was inactive. -;; 2) There was no need to worry about the major mode map clobbering -;; it , since it takes precedence over the major mode -;; map. `ess-noweb-setup-keymap' is therefore now superfluous -;; The menu was also reorganised to make it less cluttered, so there -;; would be room for adding tangling and weaving commands (one day). - -;; Mouse navigation (at least under Emacs (AJR)) is supported, in so -;; far as clicking mouse-1 on the '<<' of a chunk name moves to the -;; previous instance of that chunk name, and clicking in the '>>' -;; moves to the next instance. They are not mouse-hightlighted, -;; though: too much hassle for zero added functionality. - -;; ess-noweb-doc-mode has been given its own syntax-table. It is the same -;; as the current doc-mode syntax-table, except that [[ is a comment -;; start and ]] a comment end. Fixes some ugliness in LaTeX-mode if -;; `$' or `%' appear in quoted code (or even `<<', which happens often -;; in C++). -;; (This should make ess-noweb-hide-code-quotes and -;; ess-noweb-restore-code-quotes unnecessary, but I have not yet removed -;; them, nor the calls to them). - -;; A new function `ess-noweb-indent-line' was defined and bound by default -;; to the tab key. This should indent the current line correctly in -;; whichever mode we are currently in. Previously, c-mode in -;; particular did not behave well with indentation (although -;; `ess-noweb-fill-chunk' worked fine). Indentation is only accurate -;; within the chunk: it does not know the syntax at the end of the -;; previous chunk, so it does not know where to start indenting in -;; this chunk. However, provided the indentation within each chunk is correct, -;; notangle will correctly indented code. - -;; (I think it would be good to separate filling and indenting, -;; though, since `indent-region' and `fill-region' have completely -;; different meanings in LaTeX-mode (and both are useful)) - -;; ess-noweb-mode and ess-noweb-minor-mode were given an optional argument, so -;; that (ess-noweb-mode -1) turns it off, (ess-noweb-mode 1) turns it on, and -;; (ess-noweb-mode) toggles it. This is considered normal for minor modes. - -;; buffer-substring changed to buffer-substring-no-properties: -;; comparisons with buffer-substring can be unreliable if highlighting -;; is used. - -;; New functions `ess-noweb-in-code-chunk' & `ess-noweb-chunk-is-code' created -;; to replace (if (stringp (car (ess-noweb-find-chunk)))) and -;; (if (stringp (car (ess-noweb-chunk-vector-aref index)))). - -;; `ess-noweb-insert-mode-line' was renamed -;; `ess-noweb-insert-default-mode-line' and modified to put the mode-line -;; at the start of the file and remove any existing mode-line. - -;; a '<=' in `ess-noweb-find-chunk-index' changed to '<', so we get the -;; right answer if point is on the first character in a chunk - -;; The name of `ess-noweb-post-command-hook' changed to -;; `ess-noweb-post-command-function', since it is a function. - -;; All the highlighting code moved to a separate file: -;; (ess-noweb-font-lock-mode.el) - -;; Menu driven tangling is in the process of being added. It can -;; currently tangle a single chunk or a series of chunks with the -;; same name (which I refer to as a thread) into a separate -;; buffer. This buffer can then be saved to a file, sent to an -;; interpreter, whatever. I haven't tested using line-numbers as yet. - -;;; ess-noweb-mode.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-noweb.el b/elpa/ess-20191014.1343/obsolete/ess-noweb.el deleted file mode 100644 index 23744dcf..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-noweb.el +++ /dev/null @@ -1,138 +0,0 @@ -;;; ess-noweb.el --- support for Literate Data Analysis - -;; Copyright (C) 1999 Mark Lunt -;; Copyright (C) 1999--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Mark Lunt -;; A.J. Rossini -;; Created: April 18, 1999 -;; Maintainer: ESS-core - -;; Keywords: statistics, languages -;; Summary: Noweb support for ESS - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; Code for ESS and Literate Data Analysis. - -;;; Code: - - ; Requires and autoloads - -(require 'ess-custom) -(require 'ess-inf) -(require 'ess-noweb-mode) - - ; Variables - -(defvar ess-noweb-use-font-lock font-lock-mode - "Set to t if you want to use font-locking in ESS noweb buffers.") - -(if ess-noweb-use-font-lock - (require 'ess-noweb-font-lock-mode)) - - ; Functions - -;;*;; Code Chunk evaluation. - -(defun ess-noweb-create-tangle-buffer (name) - (let ((buff (get-buffer-create name)) - (elca (eval ess-local-customize-alist))) - (with-current-buffer buff - (erase-buffer) - (ess-setq-vars-local elca buff)) - buff)) - -(defun ess-eval-chunk (vis) - "Tangle the current chunk and send it to the inferior ESS process. -Arg has same meaning as for `ess-eval-region'." - (interactive "P") - (let ((process-name ess-local-process-name) - new-process-name - (cbuf (current-buffer)) - (temp-buffer (ess-noweb-create-tangle-buffer "Tangle Buffer"))) - (save-excursion - (ess-noweb-tangle-chunk temp-buffer) - (set-buffer temp-buffer) - ;; When the temp buffer is created, it does not inherit any value - ;; of ess-local-process-name from the .Rnw buffer, so we have to set it - ;; here. If ess-local-process-name is not set in the .Rnw buffer, - ;; it will inherit the value that is chosen here. - (set (make-local-variable 'ess-local-process-name) process-name) - (ess-eval-region (point-min) (point-max) vis "Eval Chunk") - (if process-name - (kill-buffer temp-buffer) - ;; if process-name was nil, source buffer did not have a local process - ;; so keep value from temp buffer before killing it. - (setq new-process-name ess-local-process-name) - (kill-buffer temp-buffer) - (set-buffer cbuf) - (set (make-local-variable 'ess-local-process-name) new-process-name))))) - - -(defun ess-eval-chunk-and-step (&optional vis) - "Tangle the current chunk and send it to the inferior ESS process and -step to the next chunk" - (interactive) - (ess-eval-chunk vis) - (ess-noweb-next-code-chunk 1)) - -(defun ess-eval-chunk-and-go (vis) - "Tangle the current chunk, send to the ESS process, and go there. -Arg has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-chunk vis) - (ess-switch-to-ESS t)) - -;;*;; Thread code chunk evaluation - -;; -;; Threads are code chunks which fit into the same "buffer" (I'm (AJR) -;; abusing terminology, but what I mean is things like: -;; <>= -;; code for thing1 -;; @ -;; Documentation -;; <>= -;; continuing code for thing1 -;; @ -;; - -(defun ess-eval-thread (vis) - "Tangle all chunks in the current chunk-thread and send to the ESS process. -Arg has same meaning as for `ess-eval-region'." - (interactive "P") - (let ((temp-buffer (ess-noweb-create-tangle-buffer "Tangle Buffer"))) - (ess-noweb-tangle-current-thread temp-buffer) - (set-buffer temp-buffer) - (ess-eval-region (point-min) (point-max) vis "Eval buffer") - (kill-buffer temp-buffer))) - -(defun ess-eval-thread-and-go (vis) - "Tangle all chunks in the current chunk-thread, send to ESS process, -and go there. Arg has same meaning as for `ess-eval-region'." - (interactive "P") - (ess-eval-thread vis) - (ess-switch-to-ESS t)) - - ; Provide package - -(provide 'ess-noweb) - -;;; ess-noweb.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-r-a.el b/elpa/ess-20191014.1343/obsolete/ess-r-a.el deleted file mode 100644 index ccd958f1..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-r-a.el +++ /dev/null @@ -1,154 +0,0 @@ -;;; ess-r-a.el -- Possible local customizations for R with ESS. -*- lexical-binding: t; -*- - -;; Copyright (C) 1997--2005 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: A.J. Rossini -;; Created: 17 November 1999 -;; Maintainer: ESS-core - -;; Keywords: languages - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; The purpose of this file is to demonstrate some of the extras that -;; have been constructed for the ESS R mode; if they prove -;; interesting, then they might be migrated to ess-r-mode, the primary -;; ESS R mode tools. - -;;; Code: -(require 'ess-inf) -(require 'ess-r-mode) - -;; you can invoke ESS/R from emacs by typing -;; C-u M-x essr -;; with vsize set to (for example) 40M, and nsize set to 600000. - -;; Undefined on non-apple devices -(declare-function ns-do-applescript "nsfns.m" (script)) -(declare-function do-applescript "ess-r-a" (script)) -(unless (fboundp 'do-applescript) - (defalias 'do-applescript 'ns-do-applescript)) - -(defalias 'essr - (read-kbd-macro - "C-u M-x R RET - - vsize = 40M SPC - - nsize = 600000 2*RET")) - -(defun ess-r-do-region (start end) - "Send from START to END to R via AppleScript." - (interactive "r\nP") - (message "Starting evaluation...") - (do-applescript (concat - "try\n" - "tell application \"R\"\n" - "activate\n" - "with timeout of 0 seconds\n" - "cmd \"" (buffer-substring start end) - "\"\n" - "end timeout\n" - "end tell\n" - "end try\n")) - (message "Finished evaluation")) - -(defun ess-r-do-line () - "Send the current line to R via AppleScript." - (interactive) ;; "r\nP") - (message "Starting evaluation...") - (save-excursion - (let ((end (point))) - (move-to-column 0) - (do-applescript (concat - "try\n" - "tell application \"R\"\n" - "activate\n" - "with timeout of 0 seconds\n" - "cmd \"" (buffer-substring (point) end) - "\"\n" - "end timeout\n" - "end tell\n" - "end try\n")))) - (message "Finished evaluation")) - -(defun ess-r-var (beg end) - "Load the current region of numbers into an R variable. -Prompts for a variable name. If none is given, it uses a default -variable name, e. BEG and END denote the region in the current -buffer to be sent." - (interactive "r") - (save-window-excursion - (let ((tmp-file (make-temp-file "ess-r-var")) - cmd - var) - (write-region beg end tmp-file) - - ;; Decide on the variable name to use in R; could use completion. - (setq var (read-string "R Variable name (default e): ")) - (if (equal var "") - (setq var "e")) - - ;; Command to send to the R process. Get R to delete the file - ;; rather than Emacs in case it takes R a long time to run the - ;; scan command. - (setq cmd (concat var " <- scan(\"" tmp-file "\"); " - "unlink(\"" tmp-file "\")" )) - - ;; Put the output from the scan command into the process buffer so - ;; the user has a record of it. - (ess-execute cmd 'buffer)))) - - -;;; Peter Dalgaard's code. -;;; This needs to be cleaned and validated! - -(defun pd::set-up-demo () - (run-ess-r) - (split-window-vertically 6) - (find-file "demos.R") - - ;; Don't need to run this as a function -- ought to be fine if set - ;; just once. - - (defun ajr::scroll-to-end::peterD (emacs) - "Goal: map prompt to bottom of the screen after every command. -Alternatively, use the scroll-in-place package, not sure where that -is)." - (interactive) - (other-buffer 1) - (if (= emacs "emacs") - (setq scroll-up-aggressively t) - (setq scroll-conservatively -4)) ;; <- change this - (other-buffer -1)) - - (defun show-max-other-window () - (interactive) - (other-window 1) - (comint-show-maximum-output) - (other-window -1)) - - ;; call this once - ;; (ajr::scroll-to-end::peterD "emacs") - - (global-set-key [f11] 'show-max-other-window) - (global-set-key [f12] 'ess-eval-line-visibly-and-step)) - - - ; Provide package - -(provide 'ess-r-a) - -;;; ess-r-a.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-r-args.el b/elpa/ess-20191014.1343/obsolete/ess-r-args.el deleted file mode 100644 index 207ad998..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-r-args.el +++ /dev/null @@ -1,354 +0,0 @@ -;;; ess-r-args.el --- Insert R function's arguments - -;; Copyright (C) 2007 Sven Hartenstein -;; Copyright (C) 2007 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; This file is part of ESS - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; http://www.r-project.org/Licenses/ - -;; Last update: 2012-02-27 - -;;; Commentary: - -;; == DOCUMENTATION == - -;; This file provides some functions that show or insert a -;; R-function's arguments (and their default values) by using R's -;; args() function. This code requires ESS (http://ess.r-project.org). -;; For screenshots as well as information on requirements, -;; installation, configuration and troubleshooting, please visit -;; http://www.svenhartenstein.de/emacs-ess.php - -;; == Requirements == - -;; * ESS mode must be loaded and running. -;; * A R process must be running within ESS. -;; * For the tooltip option to work, Emacs must not run within a -;; terminal but (directly) under the X window system (in case of -;; GNU/Linux). - -;; == Installation == - -;; To make Emacs aware of the functions defined in this file load it -;; into Emacs by including something like the following in your -;; ~/.emacs file (adapt "/PATH/TO"!). -;; -;; (add-hook 'ess-mode-hook (lambda () (load "/PATH/TO/ess-r-args.el"))) -;; -;; This file is included with ESS; if you are reading this file as -;; part of the ESS distribution, then you do not need to add the above -;; line. - -;; == Configuration == - -;; Configuration should be done by setting some variables in your -;; ~/.emacs file, the following is an example only, adjust it to your -;; needs. - -;; ;; ess-r-args-noargsmsg is printed, if no argument information -;; ;; could be found. You could set it to an empty string ("") for no -;; ;; message. -;; (setq ess-r-args-noargsmsg "No args found.") -;; -;; ;; ess-r-args-show-as determines how (where) the information is -;; ;; displayed. Set it to 'tooltip little tooltip windows or to -;; ;; 'message (the default) which will use the echo area at the bottom of -;; ;; your Emacs frame. -;; (setq ess-r-args-show-as nil) -;; -;; ;; ess-r-args-show-prefix is a string that is printed in front of -;; ;; the arguments list. The default is "ARGS: ". -;; (setq ess-r-args-show-prefix "ARGS: ") - -;; == Usage == - -;; The functions should be called when point (text cursor) is between -;; two parentheses of a R function call (see screenshots above). It -;; will then (invisibly) query R for which arguments the respective -;; function knows as well as their default values and show or insert -;; the result. - -;; There are currently two functions: ess-r-args-show echoes the -;; arguments in the echo area or as tooltip, ess-r-args-insert prints -;; the arguments at point. - -;; In order to not having to type the whole function name each time -;; you want to see the arguments list, you most probably want to bind -;; the functions to a key which again should be done in your ~/.emacs -;; file. You can also let Emacs call the function each time you insert -;; an opening parenthesis ("("). - -;; -----> do this below - -;; Again, the following is an example only: - -;; bind ess-r-args-show to F2 -;; (define-key ess-mode-map [f2] 'ess-r-args-show) - -;; bind ess-r-args-insert to F3 -;; (define-key ess-mode-map [f3] 'ess-r-args-insert) - -;; == Setting the tooltip position == - -;; Unfortunately (?), tooltips are by default shown at the mouse -;; pointer's position, which is not necessarily where you are looking -;; at. If you use Emacs' mouse-avoidance-mode with option "banish" -;; then the mouse pointer will automatically be put at the upper right -;; corner of the Emacs window so that you know where to look for the -;; tooltip. Emacs also allows for setting the tooltip position -;; relative to the upper left corner of your screen. If you know how -;; to let Emacs determine the point (text cursor) position in pixels -;; from the upper left corner of the screen, please let me know. It -;; would then be possible to show the tooltip near the point, which I -;; would consider preferably. -;; SJE: see code at bottom 2009-01-30... - -;; ;; Put mouse away when using keyboard -;; (mouse-avoidance-mode 'banish) - -;; ;; Set the tooltip position in absolute pixels from the upper left -;; ;; corner of the screen -;; (setq tooltip-frame-parameters -;; '((name . "tooltip") -;; (left . 20) -;; (top . 20))) - -;; == Changelog == - -;; * 2007-04-03: The function should now do nothing (instead of -;; irritating cursor movement) if the current ESS process is -;; anything but R. -;; * 2007-04-05: Function names changed. Much more modular. GPLed. New -;; prefix configuration variable. Minor changes. -;; * 2007-04-30: Error handling added. Bugfix: Emacs used to lock up -;; when function was called within parentheses following the "#" -;; character (Thanks to John Bullock for his bug report!). - -;; == Troubleshooting == - -;; Before sending reports of problems, please check the following. - -;; * Doublecheck the requirements section above. -;; * Please be sure you tried both the "tooltip" option and the "echo -;; area" option and tell me whether both failed or just one. -;; * Check whether it is a key binding problem. Run the function with -;; M-x ess-r-args-show RET. If it works but not the key binding, try -;; binding it to another key. Some window managers might not pass -;; the function key keystrokes to Emacs. - -;; If you encounter problems, please send me detailed bug reports. -;; Please also indicate the ESS version you are running and the Emacs -;; type (GNU vs. X) and operating system. I will do my best to help -;; but please be aware that I'm everything but an emacs lisp expert. - -;; == TODO == - -;; These are things that I would like to see improved. Please let me -;; know if you know how it could be done. - -;; * As mentioned above, I would like to place the tooltip near the -;; point (text cursor) but I do not see how this could be done. -;; * Both the message in the echo area and the tooltip automatically -;; disappear as soon as a key is pressed. That is, you will need to -;; call the function again if you have entered the first -;; parameter(s) and wonder what additional parameters are possible. -;; I would prefer the information to be shown, say, five seconds or -;; so. - -;;; Code: - -(require 'ess-custom) -(require 'ess-inf) -(require 'ess-utils) -(eval-when-compile - (require 'tooltip)); for tooltip-show - -;; These defvars were previously defcustoms in ess-custom -(defvar ess-r-args-noargsmsg "No args found." - "Message returned if \\[ess-r-args-get] cannot find a list of arguments.") -(make-obsolete-variable 'ess-r-args-noargsmsg "Use `eldoc-mode' instead." "ESS 18.10") - -(defvar ess-r-args-show-prefix "ARGS: " - "A prefix string that is shown before the arguments list.") -(make-obsolete-variable 'ess-r-args-show-prefix "Use `eldoc-mode' instead." "ESS 18.10") - -(defvar ess-r-args-show-as 'message - "How ess-r-args-show should show the argument list. Possible values -are: 'message' (the default) or 'tooltip'.") -(make-obsolete-variable 'ess-r-args-show-as "Use `eldoc-mode' instead." "ESS 18.10") - -(defvar ess-r-args-keep-silent ess-S-non-functions - "List of functions names which should *not* trigger \\[ess-r-args-show]; -Defaults to `ess-S-non-functions'.") -(make-obsolete-variable 'ess-r-args-keep-silent "Use `eldoc-mode' instead." "ESS 18.10") - -(defvar ess-r-args-electric-paren nil - "Non-nil means re-assign \"(\" to \\[ess-r-args-auto-show].") -(make-obsolete-variable 'ess-r-args-electric-paren "Use `eldoc-mode' instead." "ESS 18.10") - -(defun ess-message (format-string &rest args) - "Shortcut for \\[message] only if `ess-show-load-messages' is non-nil." - (when (bound-and-true-p ess-show-load-messages) - (message format-string args))) - -(defun ess-r-args-current-function () - "Returns the name of the R function assuming point is currently -within the argument list or nil if no possible function name is -found." - (save-excursion - (condition-case nil (up-list -1) - (error (message "Can't find opening parenthesis."))) - (let ((posend (point))) - (backward-sexp 1) - (let ((rfunname (buffer-substring-no-properties posend (point)))) - (if (posix-string-match "^[a-zA-Z0-9_\.]+$" rfunname) - rfunname nil))))) -(make-obsolete 'ess-r-args-current-function "See `eldoc-mode'" "ESS 18.10") - -(defun ess-r-args-get (&optional function trim) - "Returns string of arguments and their default values of R -function FUNCTION or nil if no possible function name -found. Calls `ess-r-args-current-function' if no argument given. -If TRIM is non-nill remove tabs and newlines and replace ' = ' -with '=' (useful for display in minibuffer to avoid window and -buffer readjustments for multiline string)." - (if (null function) - (setq function (ess-r-args-current-function))) - (when (and function - (or ess-current-process-name - (called-interactively-p 'any))) - (ess-force-buffer-current "R process to use: ") - ;; ^^^^^^^^^^^^^^^ has own error handler - (mapconcat (lambda (arg) (concat (car arg) "=" (cdr arg))) - (cadr (ess-function-arguments function)) - ", "))) - -(make-obsolete 'ess-r-args-get "See `eldoc-mode'" "ESS 18.10") - -;;;###autoload -(defun ess-r-args-show (&optional function) - "Show arguments and their default values of R function. Calls -\\[ess-r-args-current-function] if called without argument." - (interactive "*") - (ess-message "(ess-r-args-show): start") - (if (null function) - (setq function (ess-r-args-current-function))) - (ess-message ".... function='%s'" function) - (when function - (let* ((tt (equal ess-r-args-show-as 'tooltip)) - (args (concat ess-r-args-show-prefix - (ess-r-args-get function (not tt))))) - (ess-message "(ess-r-args-show): args='%s'" args) - (when args - (if (not tt) - (message args) - (require 'tooltip) - ;; value of 30 in next call is just a guess, - ;; should really be based - ;; on something like pixel height of 1-2 vertical - ;; lines of text - (ess-tooltip-show-at-point args 0 30)) - )))) -(make-obsolete 'ess-r-args-show "See `eldoc-mode'" "ESS 18.10") - -;;;###autoload -(defun ess-r-args-auto-show () - "Typically assigned to \"(\": If there's an ess-process, automatically show arguments -and their default values of an R function. Built on \\[ess-r-args-show]." - (interactive) - (insert "("); (skeleton-pair-insert-maybe nil) - (if (and (not eldoc-mode) - ess-local-process-name ; has a process and it must still be running - (ess-get-process ess-local-process-name)) - (ess-r-args-show))) -(make-obsolete 'ess-r-args-auto-show "See `eldoc-mode'" "ESS 18.10") - -;; MM: I would strongly discourage use of the following: -;; it leads to clueless newbie-users who indeed -;; explicitly call a function with all its default arguments; -;; instead of only setting the required arguments -(defun ess-r-args-insert (&optional function) - "Insert arguments and their default values of function. Calls -ess-r-args-current-function if no argument given." - (interactive "*") - (if (null function) - (setq function (ess-r-args-current-function))) - (if function - (let ((args (ess-r-args-get function)) - (pointpos (point))) - (insert args) - (goto-char pointpos)))) -(make-obsolete 'ess-r-args-insert "See `eldoc-mode'" "ESS 18.10") - - -;; (defvar ess-r-object-tooltip-alist -;; '((numeric . "summary") -;; (integer . "summary") -;; (factor . "table") -;; (lm . "summary") -;; (other . "str")) -;; "List of ( . ) to be used in \\[ess-r-object-tooltip]. -;; For example, when called while point is on a factor object, a table of that -;; factor will be shown in the tooltip. -;; The special key \"other\" in the alist defines which function to call when -;; the class is not mached in the alist. The default, str(), is a fairly useful -;; default for many, including data.frame and function objects.") - -;; From Erik Iversion, slightly modified, -;; http://www.sigmafield.org/2009/10/01/r-object-tooltips-in-ess/ -;; (defun ess-r-object-tooltip () -;; "Get info for object at point, and display it in a tooltip." -;; (interactive) -;; (let ((proc (ess-get-process)) -;; (objname (current-word)) -;; (curbuf (current-buffer)) -;; (tmpbuf (get-buffer-create " *ess-r-object-tooltip*")) -;; bs) -;; (when objname -;; (ess-write-to-dribble-buffer -;; (format "ess-r-object-tooltip: objname='%s'\n" objname)) -;; (ess-command (concat "class(" objname ")\n") tmpbuf nil nil nil proc) -;; (with-current-buffer tmpbuf -;; (goto-char (point-min)) -;; ;; CARE: The following can only work in an English language locale! -;; ;; .lang. <- Sys.getenv("LANGUAGE"); Sys.setenv(LANGUAGE="en") -;; ;; .lc. <- Sys.getlocale("LC_MESSAGES"); Sys.setlocale("LC_MESSAGES","en_US.utf-8") -;; ;; and *afterward* Sys.setenv(LANGUAGE=.lang.); Sys.setlocale("LC_MESSAGES", .lc.) -;; ;; but that fails sometimes, e.g., on Windows -;; (unless (re-search-forward "\(object .* not found\)\|unexpected" nil t) -;; (re-search-forward "\"\\(.*\\)\"" nil t) -;; (let* ((objcls (match-string 1)) -;; (myfun (or (cdr (assoc-string objcls ess-r-object-tooltip-alist)) -;; (cdr (assoc 'other ess-r-object-tooltip-alist))))) -;; (ess-command (concat myfun "(" objname ")\n") tmpbuf nil nil nil proc)) -;; (setq bs (buffer-string))))) -;; (if bs -;; (ess-tooltip-show-at-point bs 0 30)))) - -;; Erik: my default key map -;;(define-key ess-mode-map "\C-c\C-g" 'ess-r-object-tooltip) - -;; On http://www.sigmafield.org/2009/10/01/r-object-tooltips-in-ess/ -;; in the comments, "Charlie" recommended - -;; (custom-set-faces -;; '(tooltip ((t (:background "white" :foreground "blue" :foundry "fixed"))))) - - - -(provide 'ess-r-args) - -;;; ess-r-args.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-rutils.el b/elpa/ess-20191014.1343/obsolete/ess-rutils.el deleted file mode 100644 index 82813e26..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-rutils.el +++ /dev/null @@ -1,41 +0,0 @@ -;;; ess-rutils.el --- Convenience features for package and object control. -*- lexical-binding: t; -*- - -;; Author: J. Alexander Branham -;; Maintainer: ESS-Core -;; Keywords: processes - -;; Copyright (c) 2019 Free Software Foundation -;; Copyright (c) 2013-2019 ESS Core -;; Copyright (c) 2005-2013 Sebastian P. Luque - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; History: - -;; This file was originally written by Sebastian Luque in 2004. It was -;; completely rewritten in 2019 and then merged into ess-r-mode as -;; part of contributing ESS to GNU Emacs. - -;;; Commentary: - -;; This file used to have support for listing packages and a few other -;; misc functions. That is now in ess-r-mode. This file is provided -;; only so that users who have (require 'ess-rutils) in their init -;; files don't encounter errors when they update ESS. - -;;; Code: - -(provide 'ess-rutils) - -;;; ess-rutils.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/ess-swv.el b/elpa/ess-20191014.1343/obsolete/ess-swv.el deleted file mode 100644 index e54f6db0..00000000 --- a/elpa/ess-20191014.1343/obsolete/ess-swv.el +++ /dev/null @@ -1,491 +0,0 @@ -;;; ess-swv.el --- Some simple functions for ESS and Sweave - -;; Copyright (C) 2005 David Whiting, A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. -;; Copyright (C) 2006-2008 A.J. Rossini, Richard M. Heiberger, Martin Maechler, -;; Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: David Whiting -;; Created: 15 April 2005 -;; Maintainer: ESS-core - -;; Keywords: statistics, tools - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; -;; Some simple functions for ESS and Sweave -;; david.whiting at ncl.ac.uk -;; Wed Sep 1 14:55:52 CEST 2004 - -;; I have written some very simple elisp functions that I have found -;; useful and thought others might like to see. I dabble with elisp -;; occasionally at best so there are probably better ways to do what I -;; have done, but so far this seems to work for me. There are several -;; things that are hard-coded, I use Linux and I think that this would -;; probably not work in Windows (not as it is now anyway). - -;; With these functions and key bindings all I need to do is open a .Rnw -;; file and, assuming R is running, I press: - -;; M-n s to Sweave the file, then -;; M-n l to run latex on the results of Sweave, then -;; M-n p to make and display a postscript file , or -;; M-n P to make and display a PDF version. - -;; David Whiting to Anthony Rossini, Mar 30 -;; On Wed, Mar 30, 2005 at 11:51:26AM +0200, A.J. Rossini wrote: -;; > I'm going to go ahead and add this stuff to the distribution tonight -;; > if you don't mind. I'd forgotten about it! -;; It would make me very happy indeed. -;; > (however, need permission to do so). -;; Permission granted! - -;; Dave -;; -- -;; David Whiting -;; School of Clinical Medical Sciences, The Medical School -;; University of Newcastle upon Tyne, NE2 4HH, UK. - - -;;; TODO: -;;; -;;; 1. I want to be able to send ess-swv-latex a parameter to tell it -;;; the number of times to run LaTeX (to get references updated -;;; correctly). -;;; -;;; 2. Also need to add ess-swv-Bibtex. -;;; -;;; 3. Might be good to have a way to chain commands. -;;; -;;; 4. ADD to the ../doc/ess.texi !! - - -;;; Code: - -;;; Autoloads and Requires - -(eval-when-compile - (require 'ess-custom)) - -(require 'ess-utils) -(require 'ess-noweb-mode) -(require 'ess-r-mode); for Rnw-mode -(require 'easymenu) - - - -(defvar TeX-command-list) -(defvar TeX-command-default) -(defvar TeX-file-extensions) -(declare-function TeX-normal-mode "tex") - -(defgroup ess-sweave nil - "Mode for editing Sweave (*.[SR]nw) files." - :group 'ess-S - :prefix "ess-") - -(defcustom ess-pdf-viewer-pref nil - "External pdf viewer you like to use from ESS. -Can be a string giving a name of the program or a list with car -giving heprogram and the tail giving the arguments. For example -'(\"okular\" \"--unique\")." - :type '(choice (const nil) (repeat :tag "Command with arguments" string) (string :tag "Command"))) - -(defcustom ess-ps-viewer-pref nil - "External PostScript viewer you like to use from ESS. -If nil, ESS will try finding one from a list." - :type '(choice (const nil) string)) - -(defcustom ess-swv-pdflatex-commands '("texi2pdf" "pdflatex" "make") - "Commands to run a version of pdflatex in \\[ess-swv-PDF]; -the first entry is the default command." - :group 'ess-sweave - :type '(repeat string)) - -(defcustom ess-swv-plug-into-AUCTeX-p nil - "Non-nil means add commands to AUCTeX's \\[TeX-command-list] -to sweave the current noweb file and latex the result." - :group 'ess-sweave - :type '(choice (const :tag "Off" nil) - (const :tag "On" t))) - -(defcustom ess-swv-processing-command ".ess_weave(%s, %s)" - "Command used by `ess-swv-run-in-R'. - -First %s is literally replaced by the processing command (for -example: Sweave) second %s is replaced with a string containing a -processed file and possibly additional argument encoding (example: -\"path/to/foo.Rnw\", encoding='utf-8') - -.ess_weave changes the working directory to that of the supplied -file. - -If you want to simply call knitr or Sweave in global environment -set this command to \"%s(%s)\"." - :group 'ess-R - :type 'string) - -;; currently use exactly for "Sweave", "Stangle", "knit", and "purl" -(defun ess-swv-run-in-R (cmd &optional choose-process block) - "Run \\[cmd] on the current .Rnw file. Utility function not called by user." - (let* ((rnw-buf (current-buffer))) - (if choose-process ;; previous behavior - (ess-force-buffer-current "R process to load into: ") - ;; else - (update-ess-process-name-list) - (cond ((= 0 (length ess-process-name-list)) - (message "no ESS processes running; starting R") - (sit-for 1); so the user notices before the next msgs/prompt - (run-ess-r) - (set-buffer rnw-buf) - ) - ((not (string= "R" (ess-make-buffer-current))); e.g. Splus, need R - (ess-force-buffer-current "R process to load into: ")) - )) - - (save-excursion - ;; (ess-execute (format "require(tools)")) ;; Make sure tools is loaded. - (basic-save-buffer); do not Sweave/Stangle old version of file ! - (let* ((sprocess (ess-get-process ess-current-process-name)) - (sbuffer (process-buffer sprocess)) - (rnw-file (buffer-file-name)) - (Rnw-dir (file-name-directory rnw-file)) - (buf-coding (symbol-name buffer-file-coding-system)) - ;; could consider other encodings, but utf-8 is "R standard" for non-ASCII: - (cmd-args (concat "\"" rnw-file "\"" - (if (string-match "^utf-8" buf-coding) - ", encoding = \"utf-8\""))) - (Sw-cmd - (format ess-swv-processing-command cmd cmd-args))) - (message "%s()ing %S" cmd rnw-file) - ;; need to block when we are running ess-swv-weave-PDF so we - ;; know when to start compiling the generated .tex file - (if block - (progn - (ess-eval-linewise (concat Sw-cmd "\n") nil nil nil t) - (message "Finished %s()ing %S" cmd rnw-file)) - (ess-execute Sw-cmd 'buffer nil nil) - (pop-to-buffer-same-window rnw-buf) - (display-buffer (buffer-name sbuffer))))))) - -(defcustom ess-swv-processor 'sweave - "Processor to use for weaving and tangling. -Currently 'sweave or 'knitr" - :group 'ess-R - :type '(choice (const sweave) (const knitr))) - - -(defun ess-swv-tangle () - "Run Stangle/purl on the current .Rnw file. -Depending on the `ess-swv-processor' used." - (interactive) - (ess-swv-run-in-R (cond ((eq ess-swv-processor 'sweave) "Stangle") - ((eq ess-swv-processor 'knitr) "purl") - (t (error "Not a valid processor %s" ess-swv-processor))))) - -(defun ess-swv-weave (&optional choose) - "Run Sweave/knit on the current .Rnw file. -Depending on the `ess-swv-processor' used. - -If CHOOSE is non-nil, offer a menu of available weavers. -" - (interactive "P") - (let ((processor (if choose - (ess-completing-read "Weaver" '("sweave" "knitr") nil t) - (symbol-name ess-swv-processor)))) - (ess-swv-run-in-R (cond ((string= processor "sweave") "Sweave") - ((string= processor "knitr") "knit") - (t (error "Not a valid processor %s" processor)))))) - -(defun ess-swv-sweave () - "Run Sweave on the current .Rnw file." - (interactive) - (ess-swv-run-in-R "Sweave")) - -(defun ess-swv-stangle () - "Run Stangle on the current .Rnw file." - (interactive) - (ess-swv-run-in-R "Stangle")) - -(defun ess-swv-knit () - "Run knit on the current .Rnw file." - (interactive) - (ess-swv-run-in-R "knit")) - -(defun ess-swv-purl () - "Run purl on the current .Rnw file." - (interactive) - (ess-swv-run-in-R "purl")) - -;; trying different viewers; thanks to an original patch for -;; ess-swv.el from Leo : -(defun ess-get-ps-viewer () - "Get external PostScript viewer to be used from ESS. -Use `ess-ps-viewer-pref' when that is executably found by \\[executable-find]. -Otherwise try a list of fixed known viewers." - (file-name-nondirectory - (or (and ess-ps-viewer-pref ; -> ./ess-custom.el - (executable-find ess-ps-viewer-pref)) - (executable-find "gv") - (executable-find "evince") - (executable-find "kghostview")))) - -(defun ess-get-pdf-viewer () - "Get external PDF viewer to be used from ESS. -Use `ess-pdf-viewer-pref' when that is executably found by \\[executable-find]. -Otherwise try a list of fixed known viewers." - (let ((viewer (or ess-pdf-viewer-pref - ;; (and (stringp ess-pdf-viewer-pref) ; -> ./ess-custom.el - ;; (executable-find ess-pdf-viewer-pref)) - (executable-find "evince") - (executable-find "kpdf") - (executable-find "okular") - (executable-find "xpdf") - (executable-find "acroread") - (executable-find "xdg-open") - ;; this one is wrong, (ok for time being as it is used only in swv) - (when (fboundp 'ess-get-words-from-vector) - (car (ess-get-words-from-vector - "getOption(\"pdfviewer\")\n")))))) - (when (stringp viewer) - (setq viewer (file-name-nondirectory viewer))) - viewer)) - -(defun ess-swv-weave-PDF (&optional choose) - "Sweave/knit, compile TeX, and display PDF. -Run Sweave or knit depending on `ess-swv-processor' used. - -If CHOOSE is non-nil, offer a menu of available weavers. -" - (interactive "P") - (let ((processor (if choose - (ess-completing-read "Weaver" '("sweave" "knitr") nil t) - (symbol-name ess-swv-processor)))) - (ess-swv-run-in-R (cond ((string= processor "sweave") "Sweave") - ((string= processor "knitr") "knit") - (t (error "Not a valid processor %s" processor))) - nil t) - (ess-swv-PDF nil t))) - - -(defun ess-swv-latex () - "Run LaTeX on the product of Sweave()ing the current file." - (interactive) - (save-excursion - (let* ((namestem (file-name-sans-extension (buffer-file-name))) - (latex-filename (concat namestem ".tex")) - (tex-buf (get-buffer-create " *ESS-tex-output*"))) - (message "Running LaTeX on '%s' ..." latex-filename) - (switch-to-buffer tex-buf) - (call-process "latex" nil tex-buf 1 latex-filename) - (switch-to-buffer (buffer-name)) - (display-buffer tex-buf) - (message "Finished running LaTeX" )))) - - -(defun ess-swv-PS () - "Create a postscript file from a dvi file (name based on the current -Sweave file buffer name) and display it." - (interactive) - (let* ((buf (buffer-name)) - (namestem (file-name-sans-extension (buffer-file-name))) - (dvi-filename (concat namestem ".dvi")) - (psviewer (ess-get-ps-viewer))) - (shell-command (concat "dvips -o temp.ps " dvi-filename)) - (shell-command (concat psviewer " temp.ps & ")) - (switch-to-buffer buf) - )) - -(defun ess-swv-PDF (&optional pdflatex-cmd hide-compile-buffer) - "From LaTeX file, create a PDF (via 'texi2pdf' or 'pdflatex', ...), by -default using the first entry of `ess-swv-pdflatex-commands' and display it." - (interactive) - (setq pdflatex-cmd - (or pdflatex-cmd - (and (eq (length ess-swv-pdflatex-commands) 1) - (car ess-swv-pdflatex-commands)) - (ess-completing-read "pdf latex command" - ess-swv-pdflatex-commands ; <- collection to choose from - nil 'confirm ; or 'confirm-after-completion - nil nil (car ess-swv-pdflatex-commands)))) - (let* ((buf (buffer-name)) - (namestem (file-name-sans-extension (buffer-file-name))) - (latex-filename (concat namestem ".tex")) - (tex-buf (get-buffer-create "*ESS-tex-output*")) - (pdfviewer (ess-get-pdf-viewer)) - (pdf-status) - (cmdstr-win (format "start \"%s\" \"%s.pdf\"" pdfviewer namestem)) - (pdffile (format "%s.pdf" namestem)) - (cmd (if (stringp pdfviewer) - (list pdfviewer pdffile) - (append pdfviewer (list pdffile))))) - - ;;(shell-command (concat "pdflatex " latex-filename)) - (message "Running '%s' on '%s' ..." pdflatex-cmd latex-filename) - (with-current-buffer tex-buf (erase-buffer)) - (setq pdf-status - (call-process pdflatex-cmd nil tex-buf t - (if (string= "texi2" (substring pdflatex-cmd 0 5)) - ;; workaround (bug?): texi2pdf or texi2dvi *fail* to work with full path: - (file-name-nondirectory latex-filename) - latex-filename))) - (if (not (= 0 pdf-status)) - (progn (message "** OOPS: error in '%s' (%d)!" pdflatex-cmd pdf-status) - (display-buffer tex-buf)) - ;; else: pdflatex probably ok - ;; (set-process-sentinel proc 'shell-command-sentinel) - (if (and (and ess-microsoft-p - ;; Silence byte compiler warns about w32-fns - (fboundp 'w32-shell-dos-semantics)) - (w32-shell-dos-semantics)) - (shell-command cmdstr-win) - (message "%s" (mapconcat 'identity cmd " ")) - (apply 'start-process (car cmd) nil cmd)) - (unless hide-compile-buffer (display-buffer tex-buf)) - (message "%s finished with status %d" pdflatex-cmd pdf-status)))) - - -(defun ess-insert-Sexpr () - "Insert Sexpr{} into the buffer at point." - (interactive) - (insert "\\Sexpr{}") - (backward-char)) - - -;;; back-compatible wrappers: -(defun ess-makeSweave () "old *DEPRECATED* version of \\[ess-swv-weave]." - (interactive) (ding) - (message - "** warning: ess-makeSweave is deprecated. Do use (ess-swv-weave) instead!") - (ess-swv-weave)) - -(defun ess-makeLatex () "old *DEPRECATED* version of \\[ess-swv-latex]." - (interactive) (ding) - (message - "** warning: ess-makeLatex is deprecated. Do use (ess-swv-latex) instead!") - (ess-swv-latex)) - -(defun ess-makePS () "old *DEPRECATED* version of \\[ess-swv-PS]." - (interactive) (ding) - (message - "** warning: ess-makePS is deprecated. Do use (ess-swv-PS) instead!") - (ess-swv-PS)) - -(defun ess-makePDF () "old *DEPRECATED* version of \\[ess-swv-PDF]." - (interactive) (ding) - (message - "** warning: ess-makePDF is deprecated. Do use (ess-swv-PDF) instead!") - (ess-swv-PDF)) - - -;; AUCTeX integration. This is independent of this library, but it fits -;; here nonetheless since it's an alternative way of Sweave'ing without -;; starting iESS. - -(defun ess-swv-add-TeX-commands () - "Add commands to AUCTeX's \\[TeX-command-list]." - (unless (and (featurep 'tex-site) (featurep 'tex)) - (error "AUCTeX does not seem to be loaded")) - (add-to-list 'TeX-command-list - '("Sweave" "R CMD Sweave %t" - TeX-run-command nil (latex-mode) :help - "Run Sweave") t) - (add-to-list 'TeX-command-list - '("LaTeXSweave" "%l %(mode) %s" - TeX-run-TeX nil (latex-mode) :help - "Run LaTeX after Sweave") t) - (setq TeX-command-default "Sweave") - (mapc (lambda (suffix) - (add-to-list 'TeX-file-extensions suffix)) - '("nw" "Snw" "Rnw"))) - -(defun ess-swv-remove-TeX-commands (x) - "Helper function: check if car of X is one of the Sweave strings" - (let ((swv-cmds '("Sweave" "LaTeXSweave"))) - (unless (member (car x) swv-cmds) x))) - -(defun ess-swv-plug-into-AUCTeX () - "Add commands to AUCTeX's \\[TeX-command-list] to sweave the current noweb -file and latex the result." - (if ess-swv-plug-into-AUCTeX-p - (add-hook 'Rnw-mode-hook 'ess-swv-add-TeX-commands) - (remove-hook 'Rnw-mode-hook 'ess-swv-add-TeX-commands) - (setq TeX-command-list (mapcar 'ess-swv-remove-TeX-commands TeX-command-list) - ;; this will remove the items, leaving nils, so remove them. - TeX-command-list (delq nil TeX-command-list)))) -;; as ess-swv-plug-into-AUCTeX-p is customizable ... : -(if ess-swv-plug-into-AUCTeX-p - (eval-after-load "tex" '(ess-swv-plug-into-AUCTeX))) - -(defun ess-swv-toggle-plug-into-AUCTeX () - "Toggle inclusion of commands to sweave noweb files and latex the results in -\\[TeX-command-list] on and off. Commands are added via \\[Rnw-mode-hook]." - (interactive) - (unless (and (featurep 'tex-site) (featurep 'tex)) - (error "AUCTeX are not available")) - (setq ess-swv-plug-into-AUCTeX-p (not ess-swv-plug-into-AUCTeX-p)) - (ess-swv-plug-into-AUCTeX) - (TeX-normal-mode t) - (if ess-swv-plug-into-AUCTeX-p - (message "Sweave and LaTeXSweave are activated in AUCTeX.") - (message "Sweave and LaTeXSweave are de-activated in AUCTeX."))) - - -;;; Now bind some keys. -(define-key ess-noweb-minor-mode-map "\M-ns" 'ess-swv-sweave) -(define-key ess-noweb-minor-mode-map "\M-nT" 'ess-swv-tangle) -(define-key ess-noweb-minor-mode-map "\M-nl" 'ess-swv-latex) -(define-key ess-noweb-minor-mode-map "\M-np" 'ess-swv-PS) -(define-key ess-noweb-minor-mode-map "\M-nP" 'ess-swv-PDF) -(define-key ess-noweb-minor-mode-map "\M-nr" 'ess-swv-knit) -(define-key ess-noweb-minor-mode-map "\M-nu" 'ess-swv-purl) -(define-key ess-noweb-minor-mode-map "\M-nv" 'ess-swv-weave-PDF) -(define-key ess-noweb-minor-mode-map "\M-nw" 'ess-swv-weave); depends on proc. - -(define-key ess-noweb-minor-mode-map "\M-nx" 'ess-insert-Sexpr) - -;; AND add these to the noweb menu we have anyway ! : -(easy-menu-define ess-swv-menu - ess-noweb-minor-mode-menu - "Submenu for use in `Rnw-mode'." - - '("Sweaving, Tangling, ..." - ["Sweave" ess-swv-sweave t] - ["Tangle" ess-swv-tangle t] - ["LaTeX" ess-swv-latex t] - ["PDF(LaTeX)" ess-swv-PDF t] - ["PS (dvips)" ess-swv-PS t] - ["Knit" ess-swv-knit t] - ["Purl" ess-swv-purl t] - ["View PDF" ess-swv-weave-PDF t] - ["Weave (Sweave/Knit)" ess-swv-weave t] - ["Insert Sexpr" ess-insert-Sexpr t] - ["AUCTeX Interface" ess-swv-toggle-plug-into-AUCTeX - :style toggle :selected ess-swv-plug-into-AUCTeX-p] - )) - -(easy-menu-add-item ess-noweb-minor-mode-menu - nil ;; <= path - ess-swv-menu) - - ; provides - -(provide 'ess-swv) - -;;; ess-swv.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/mouseme.el b/elpa/ess-20191014.1343/obsolete/mouseme.el deleted file mode 100644 index be9cbf7c..00000000 --- a/elpa/ess-20191014.1343/obsolete/mouseme.el +++ /dev/null @@ -1,355 +0,0 @@ -;;; mouseme.el --- mouse menu with commands that operate on strings - -;; Copyright (C) 1997 by Free Software Foundation, Inc. - -;; Author: Howard Melman -;; Keywords: mouse, menu - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; https://www.r-project.org/Licenses/ - -;;; Commentary: - -;; This package provides a command `mouse-me' to be bound to a mouse -;; button. It pops up a menu of commands that operate on strings or a -;; region. The string passed to the selected command is the word or -;; symbol clicked on (with surrounding quotes or other punctuation -;; removed), or the region (if either it was just selected with the -;; mouse or if it was active with `transient-mark-mode' on). If the -;; command accepts a region, the selected region (or the region of the -;; word or symbol clicked on) will be passed to the command. - -;; The idea is that for any given string in a buffer you may want to -;; do different things regardless of the mode of the buffer. URLs -;; now appear in email, news articles, comments in code, and in plain -;; text. You may want to visit that URL in a browser or you may just -;; want to copy it to the kill-ring. For an email address you might -;; want to compose mail to it, finger it, look it up in bbdb, copy it to -;; the kill ring. For a word you may want to spell check it, copy it, -;; change its case, grep for it, etc. Mouse-me provides a menu to -;; make this easy. - -;; The menu popped up is generated by calling the function in the -;; variable `mouse-me-build-menu-function' which defaults to calling -;; `mouse-me-build-menu' which builds the menu from the variable -;; `mouse-me-menu-commands'. See the documentation for these -;; functions and variables for details. - -;; To install, add something like the following to your ~/.emacs: -;; (require 'mouseme) -;; (global-set-key [S-mouse-2] 'mouse-me) - -;;; Code: - -(require 'browse-url) -(require 'thingatpt) - -(eval-when-compile (require 'compile)) - -;;;; Variables - -(defgroup mouseme nil - "Popup menu of commands that work on strings." - :prefix "mouse-me-" - :group 'hypermedia) - -(defcustom mouse-me-get-string-function 'mouse-me-get-string - "Function used by `mouse-me' to get string when no region selected. -The default is `mouse-me-get-string' but this variable may commonly -be made buffer local and set to something more appropriate for -a specific mode (e.g., `word-at-point'). The function will be called -with no arguments and with point at where the mouse was clicked. -It can return either the string or to be most efficient, a list of -three elements: the string and the beginning and ending points of the -string in the buffer." - :type 'function - :options '(mouse-me-get-string) - :group 'mouseme) - -(defcustom mouse-me-build-menu-function 'mouse-me-build-menu - "Function used by `mouse-me' to build the popup menu. -The default is `mouse-me-build-menu' but this variable may commonly -be made buffer local and set to something more appropriate for -a specific mode. The function will be called with one argument, -the string selected, as returned by `mouse-me-get-string-function'." - :type 'function - :options '(mouse-me-build-menu) - :group 'mouseme) - -(defvar mouse-me-grep-use-extension 't - "If non-nil `mouse-me-grep' grep's in files with current file's extension.") - -(defcustom mouse-me-menu-commands - '(("Copy" . kill-new) - ("Kill" . kill-region) - ("Capitalize" . capitalize-region) - ("Lowercase" . downcase-region) - ("Uppercase" . upcase-region) - ("ISpell" . ispell-region) - "----" - ("Browse URL" . browse-url) - ("Dired" . dired) - ("Execute File" . mouse-me-execute) - ("Mail to" . compose-mail) - ("Finger" . mouse-me-finger) - ("BBDB Lookup" . mouse-me-bbdb) - "----" - ("Imenu" . imenu) - ("Find Tag" . find-tag) - ("Grep" . mouse-me-grep) - ("Find-Grep" . mouse-me-find-grep) - "----" - ("Apropos" . apropos) - ("Describe Function" . mouse-me-describe-function) - ("Describe Variable" . mouse-me-describe-variable) - ("Command Info" . mouse-me-emacs-command-info) - ("Man Page" . (if (fboundp 'woman) 'woman 'man)) - ("Profile Function" . mouse-me-elp-instrument-function)) - "Command menu used by `mouse-me-build-menu'. -A list of elements where each element is either a cons cell or a string. -If a cons cell the car is a string to be displayed in the menu and the -cdr is either a function to call passing a string to, or a list which evals -to a function to call passing a string to. If the element is a string -it makes a non-selectable element in the menu. To make a separator line -use a string consisting solely of hyphens. - -The function returned from this menu will be called with one string -argument. Or if the function has the symbol property `mouse-me-type' -and if its value is the symbol `region' it will be called with the -beginning and ending points of the selected string. If the value is -the symbol `string' it will be called with one string argument." - :type '(repeat sexp) - :group 'mouseme) - -(put 'kill-region 'mouse-me-type 'region) -(put 'ispell-region 'mouse-me-type 'region) -(put 'capitalize-region 'mouse-me-type 'region) -(put 'downcase-region 'mouse-me-type 'region) -(put 'upcase-region 'mouse-me-type 'region) - -;;;; Commands - -;;;###autoload -(defun mouse-me (event) - "Popup a menu of functions to run on selected string or region." - (interactive "e") - (mouse-me-helper event (lambda (name) - (or (x-popup-menu event (funcall mouse-me-build-menu-function name)) - (error "No command to run"))))) - -;;;; Exposed Functions - -;; Some tests: -;; -;; -;; http://foo.bar.com/sss/ss.html -;; http://www.ditherdog.com/howard/ -;; mailto:howard@silverstream.com -;; howard@silverstream.com -;; -;; import com.sssw.srv.agents.AgentsRsrc; -;; public AgoHttpRequestEvent(Object o, String db, Request r) -;;
-;; d:\howard\elisp\spoon -;; \howard\elisp\spoon -;; \\absolut\howard\elisp\spoon -;; //absolut/d/Howard/Specs/servlet-2.1.pdf -;; \\absolut\d\Howard\Specs\servlet-2.1.pdf -;; gnuserv-frame. - -(defun mouse-me-get-string () - "Return a string from the buffer of text surrounding point. -Returns a list of three elements, the string and the beginning and -ending positions of the string in the buffer in that order." - (save-match-data - (save-excursion - (let ((start (point)) beg end str p) - (skip-syntax-forward "^ >()\"") - (setq end (point)) - (goto-char start) - (skip-syntax-backward "^ >()\"") - (setq beg (point)) - (setq str (buffer-substring-no-properties beg end)) - ;; remove junk from the beginning - (if (string-match "^\\([][\"'`.,?:;!@#$%^&*()_+={}|<>-]+\\)" str) - (setq str (substring str (match-end 1)) - beg (+ beg (match-end 1)))) - ;; remove URL: from the front, it's common in email - (if (string-match "^\\(URL:\\)" str) - (setq str (substring str (match-end 1)) - beg (+ beg (match-end 1)))) - ;; remove junk from the end - (if (string-match "\\([][\"'.,?:;!@#$%^&*()_+={}|<>-]+\\)$" str) - (setq end (- end (length (match-string 1 str))) ; must set end first - str (substring str 0 (match-beginning 1)))) - (list str beg end))))) - -(defun mouse-me-build-menu (name) - "Return a menu tailored for NAME for `mouse-me' from `mouse-me-menu-commands'." - (list "Mouse Me" (cons "Mouse Me" - (append (list (cons - (if (< (length name) 65) - name - "...Long String...") - 'kill-new) - "---") - mouse-me-menu-commands)))) - -;;;; Commands for the menu - -(defun mouse-me-emacs-command-info (string) - "Look in Emacs info for command named STRING." - (interactive "sCommand: ") - (let ((s (intern-soft string))) - (if (and s (commandp s)) - (Info-goto-emacs-command-node s) - (error "No command named `%s'" string)))) - -(defun mouse-me-describe-function (string) - "Describe function named STRING." - (interactive "sFunction: ") - (let ((s (intern-soft string))) - (if (and s (fboundp s)) - (describe-function s) - (error "No function named `%s'" string)))) - -(defun mouse-me-describe-variable (string) - "Desribe variable named STRING." - (interactive "sVariable: ") - (let ((s (intern-soft string))) - (if (and s (boundp s)) - (describe-variable s) - (error "No variable named `%s'" string)))) - -(defun mouse-me-elp-instrument-function (string) - "Instrument Lisp function named STRING." - (interactive "sFunction: ") - (let ((s (intern-soft string))) - (if (and s (fboundp s)) - (elp-instrument-function s) - (error "Must be the name of an existing Lisp function")))) - -(defun mouse-me-execute (string) - "Execute STRING as a filename." - (interactive "sFile: ") - (if (fboundp 'w32-shell-execute) - (w32-shell-execute "open" (convert-standard-filename string)) - (message "This function currently working only in W32."))) - - -(defun mouse-me-bbdb (string) - "Lookup STRING in bbdb." - (interactive "sBBDB Lookup: ") - (if (fboundp 'bbdb) - (bbdb string nil) - (error "BBDB not loaded"))) - -(defun mouse-me-finger (string) - "Finger a STRING mail address." - (interactive "sFinger: ") - (save-match-data - (if (string-match "\\(.*\\)@\\([-.a-zA-Z0-9]+\\)$" string) - (finger (match-string 1 string) (match-string 2 string)) - (error "Not in user@host form: %s" string)))) - -(defun mouse-me-grep (string) - "Grep for a STRING." - (interactive "sGrep: ") - (require 'compile) - (grep-compute-defaults) - (let ((ext (mouse-me-buffer-file-extension))) - (grep (concat grep-command string - (if mouse-me-grep-use-extension - (if ext - (concat " *" ext) - " *")))))) - -(defun mouse-me-find-grep (string) - "Grep for a STRING." - (interactive "sGrep: ") - (grep-compute-defaults) - (let ((reg grep-find-command) - (ext (mouse-me-buffer-file-extension)) - beg end) - (if (string-match "\\(^.+-type f \\)\\(.+$\\)" reg) - (setq reg (concat (match-string 1 reg) - (if mouse-me-grep-use-extension - (concat "-name \"*" ext "\" ")) - (match-string 2 reg)))) - (grep-find (concat reg string)))) - -;;;; Internal Functions - -(defun mouse-me-buffer-file-extension () - "Return the extension of the current buffer's filename or nil. -Returned extension is a string begining with a period." - (let* ((bfn (buffer-file-name)) - (filename (and bfn (file-name-sans-versions bfn))) - (index (and filename (string-match "\\.[^.]*$" filename)))) - (if index - (substring filename index) - ""))) - -(defun mouse-me-helper (event func) - "Determine the string to use to process EVENT and call FUNC to get cmd." - (let (name sp sm mouse beg end cmd mmtype) - ;; temporarily goto where the event occurred, get the name clicked - ;; on and enough info to figure out what to do with it - (save-match-data - (save-excursion - (setq sp (point)) ; saved point - (setq sm (mark t)) ; saved mark - (set-buffer (window-buffer (posn-window (event-start event)))) - (setq mouse (goto-char (posn-point (event-start event)))) - ;; if there is a region and point is inside it - ;; check for sm first incase (null (mark t)) - ;; set name to either the thing they clicked on or region - (if (and sm - (or (and transient-mark-mode mark-active) - (eq last-command 'mouse-drag-region)) - (>= mouse (setq beg (min sp sm))) - (<= mouse (setq end (max sp sm)))) - (setq name (buffer-substring beg end)) - (setq name (funcall mouse-me-get-string-function)) - (if (listp name) - (setq beg (nth 1 name) - end (nth 2 name) - name (car name)) - (goto-char mouse) - (while (not (looking-at (regexp-quote name))) - (backward-char 1)) - (setq beg (point)) - (setq end (search-forward name)))))) - ;; check if name is null, meaning they clicked on no word - (if (or (null name) - (and (stringp name) (string= name "" ))) - (error "No string to pass to function")) - ;; popup a menu to get a command to run - (setq cmd (funcall func)) - ;; run the command, eval'ing if it was a list - (if (listp cmd) - (setq cmd (eval cmd))) - (setq mmtype (get cmd 'mouse-me-type)) - (cond ((eq mmtype 'region) - (funcall cmd beg end)) - ((eq mmtype 'string) - (funcall cmd name)) - (t - (funcall cmd name))))) - -(provide 'mouseme) - -;;; mouseme.el ends here diff --git a/elpa/ess-20191014.1343/obsolete/msdos.el b/elpa/ess-20191014.1343/obsolete/msdos.el deleted file mode 100644 index c76fdbe5..00000000 --- a/elpa/ess-20191014.1343/obsolete/msdos.el +++ /dev/null @@ -1,169 +0,0 @@ -;;; msdos.el --- Run an MS-DOS shell in an NTemacs buffer with bash as the shell - -;; Copyright (C) 1999 Richard M. Heiberger -;; Copyright (C) 2000--2004 A.J. Rossini, Richard M. Heiberger, Martin -;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen. - -;; Author: Richard M. Heiberger -;; Created: February 1999 -;; Maintainer: ESS-core - -;; Keywords: processes - -;; This file is part of ESS. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; A copy of the GNU General Public License is available at -;; http://www.r-project.org/Licenses/ - -;;; Commentary: - -;; The file msdos.el in the next mail message opens an *msdos* buffer -;; in shell-mode and msdos-minor-mode. When cmdproxy.exe/command.com -;; is the emacs shell, then this gets various setting right that M-x -;; shell currently misses. The function M-x msdos-minor-mode could be -;; automatically run by emacs in shell-mode in that case. - -;; When bash is the emacs shell, msdos.el still opens a -;; cmdproxy.exe/command.com shell in the buffer *msdos*. There are -;; occasions when it is necessary to run DOS character-based programs -;; in an emacs window. - -;; I followed the suggestion by AndrewI to look at M-x shell and modify -;; it. It turns out not to have been trivial. - -;; I've listed it as part of ESS (emacs speaks statistics) for now. I -;; will be happy to sign it over to FSF and have it become part of the -;; standard distribution for windows machines. - -;;; Code: - -(require 'shell); and hence 'comint - -;;; Customization and Buffer Variables - -(defcustom explicit-msdos-shell-file-name "cmdproxy.exe" - "*If non-nil, is file name to use for explicitly requested msdos -inferior shell." - :type '(choice (const :tag "None" nil) file) - :group 'shell) - -(defcustom explicit-msdos-comspec-file-name - (if (w32-using-nt) - "cmd.exe" - "command.com") - "*If non-nil, is file name to use for explicitly requested COMSPEC -environment variable." - :type '(choice (const :tag "None" nil) file) - :group 'shell) - -(defvar-local msdos-minor-mode nil - "Non-nil if using msdos-minor mode as a minor mode of some other mode.") - -(defun msdos () - "Run an inferior msdos shell, with I/O through buffer *msdos*. -This function is intended to be used in an Ntemacs session in which -bash is the primary shell. But sometimes an MSDOS window, within emacs, -is also needed. - -If buffer exists but shell process is not running, make new shell. -If buffer exists and shell process is running, just switch to buffer `*msdos*'. -Program used comes from variable `explicit-msdos-shell-file-name'. -If a file `~/.emacs_SHELLNAME' exists, it is given as initial input - (Note that this may lose due to a timing error if the shell - discards input when it starts up.) -The buffer is put in Shell mode, giving commands for sending input -and controlling the subjobs of the shell. See `shell-mode'. -See also the variable `shell-prompt-pattern'. - -The buffer is put into \\[msdos-minor-mode]. See `msdos-minor-mode'. - -The COMSPEC environment variable in the inferior shell, but not in the emacs -process, is set to `explicit-msdos-comspec-file-name'. -The SHELL environment variable in the inferior shell, but not in the emacs -process, is set to `explicit-msdos-shell-file-name'. - -The shell file name (sans directories) is used to make a symbol name -such as `explicit-csh-args'. If that symbol is a variable, -its value is used as a list of arguments when invoking the shell. - -\(Type \\[describe-mode] in the shell buffer for a list of commands.)" - (interactive) - (if (not (comint-check-proc "*msdos*")) - (let* ((prog explicit-msdos-shell-file-name) - (name (file-name-nondirectory prog)) - (startfile (concat "~/.emacs_" name)) - (xargs-name (intern-soft (concat "explicit-" name "-args"))) - shell-buffer - (comspec (getenv "COMSPEC")) - (shell (getenv "SHELL")) - ) - (save-excursion - (setenv "COMSPEC" explicit-msdos-comspec-file-name) - (setenv "SHELL" explicit-msdos-shell-file-name) - (set-buffer (apply 'make-comint "msdos" prog - (if (and xargs-name (boundp xargs-name)) - (symbol-value xargs-name)) - (if (file-exists-p startfile) - (concat "/k " startfile)))) - (setenv "COMSPEC" comspec) - (setenv "SHELL" shell) - (setq shell-buffer (current-buffer)) - (shell-mode) - (msdos-minor-mode) - (sleep-for 4) ; need to wait, else working too fast! - ;;; The `exit' warning should precede the "c:\" prompt. - ;;; If not, then increase the sleep-for time! - (goto-char (point-min)) - (insert - "Remember to exit this buffer with `exit'. If you kill the -buffer without exiting, you may not be able to shut down Windows cleanly.") - (goto-char (point-max))) - (pop-to-buffer shell-buffer)) - (pop-to-buffer "*msdos*"))) - - -(defun msdos-minor-mode () - "Minor mode for running msdos in a shell-mode buffer: -a. Uses \\[set-buffer-process-coding-system] to set the coding system -to `'raw-text-dos'. The DOS C-m C-l end-of-line is critical. The -shell freezes without it. - -b. The variable `comint-completion-addsuffix' is set to `\\' for directories. - -c. Prevents echoing of commands. - -d. strips ctrl-m from output. -" - (interactive) - (setq msdos-minor-mode t) - (set (make-local-variable 'comint-completion-addsuffix) '("\\" . " ")) - (setq comint-process-echoes t) - (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t) - (set-process-coding-system (get-buffer-process (current-buffer)) 'raw-text-dos 'raw-text-dos) - ;; buffer-process-coding-system is critical. - ) - -;; Install ourselves: - - -(put 'msdos-minor-mode 'permanent-local t) -(or (assq 'msdos-minor-mode minor-mode-alist) - (setq minor-mode-alist - (append minor-mode-alist - (list '(msdos-minor-mode " msdos"))))) - -;; Provide ourselves: - -(provide 'msdos) - -;;; msdos.el ends here diff --git a/elpa/ess-20191014.1343/onews.info b/elpa/ess-20191014.1343/onews.info deleted file mode 100644 index f7c08421..00000000 --- a/elpa/ess-20191014.1343/onews.info +++ /dev/null @@ -1,1523 +0,0 @@ -This is onews.info, produced by makeinfo version 6.5 from onews.texi. - -Changes and New Features in 15.09: - - * ESS[R]: The indentation logic has been refactored. It should be - faster, more consistent and more flexible. There are three types - of indentation settings, those starting with 'ess-offset-' give the - actual offsets, those starting with 'ess-indent-' are control - (commonly Boolean) variables, and those starting with 'ess-align-' - are vertical alignment overrides which inhibit default offsets in - specific situations. See 'ess-style-alist' for detailed - description of the new indentation system and provided default - indentation styles. - - * ESS[R]: Deprecation of old indentation settings. As a consequence - of the indentation re-factoring 'ess-brace-imaginary-offset', - 'ess-expression-offset' and all delimiter-specific offsets are - deprecated. The settings for indentation of continued statements - have been replaced by 'ess-offset-continuations'. It can be set to - either 'cascade' or 'straight' (the default). - 'ess-arg-function-offset' has been replaced by - 'ess-indent-from-lhs' and has been generalised to assignments. - This setting now works with both statement blocks and expressions - and only takes effect for offsets set to 'prev-call' and - 'open-delim' in order to produce a consistent indentation. - - * ESS: A test framework has been set up. - - * ESS[R]: A new RStudio style is provided to mimic as closely as - possible R files indented via RStudio. To reproduce the setup of - some of the RStudio users, the RStudio- style with - 'ess-offset-arguments' set to 'prev-line' is also provided. In - addition, the new RRR+ style is equivalent to RRR except it indents - blocks in function calls relatively to the opening delimiter. This - style does not try to save horizontal space and produces more - indentation. - - * ESS[R]: Roxygen fields will now be indented on paragraph refilling - in order to make the documentation more readable. You can also - refill commented lines in the 'examples' field without squashing - the surrounding code in the comments. - - * ESS[R]: ESS can now format your code! This is controlled through - the settings 'ess-fill-calls' and 'ess-fill-continuations'. When - activated, '(fill-paragraph)' formats your calls and your - formulas/continuations while making sure they don't go past - 'fill-column'. Repeated refills cycle through different styles - (see the docstrings for more details). By default, the refilled - region blinks. Set 'ess-blink-filling' to nil to prevent this. - - * ESS[R]: Fix occasional missing error location fontification in - inferior buffers. - - * ESS[R]: ess-developer now correctly assigned the environment of new - functions to the package namespace. - - * ESS[Julia]: ?[topic] now works in the *julia* buffer. Note that - support for editing Julia code now depends on 'julia-mode.el' from - the Julia project. If you install ESS from the official - tarball/zip file, 'julia-mode.el' is already included. Otherwise, - if you install ESS by running 'make', then the latest version of - 'julia-mode.el' is downloaded (and so you need an active internet - connection to install) during the installation process. - Alternatively, if you run ESS without running 'make', then ensure - that you have the 'julia-mode.el', which you can get easily from - MELPA for example. - - * iESS: For naming inferior processes, ESS can use 'projectile''s - project root and it does so when - 'ess-gen-proc-buffer-name-function' is set to - 'ess-gen-proc-buffer-name:projectile-or-simple' as by default, or - to another value beginning with - 'ess-gen-proc-buffer-name:projectile-*'. - - Changes and New Features in 15.03-1: - * ESS[R]: An indentation bug has been fixed (github issue 163) - * ESS[R]: On windows, if 'ess-prefer-higher-bit' is non-nil (the - default), then R-newest will try to run a 64 bit (rather than 32 - bit) version of R. - - Changes and New Features in 15.03: - * ESS[R]: Full native support for 'company-mode'. - * ESS[R]: More efficient caching algorithm for R completion. - * ESS: New offset variable 'ess-close-paren-offset' to control the - indentation of the closing parentheses. - * ESS[R]: Ask for CRAN mirror only once per emacs session. - * ESS[R]: Detect 'library' and 'require' calls for better completion - caching. - * Buffer display is now customizable ('ess-show-buffer-action'). - * Use 'y-or-n-p' instead of 'yes-or-no-p' throughout. - * More support for ODS in ess-sas-graph-view. - * Makefiles are now both UNIX and GNU friendly. - * ESS[R]: Simplify directory lookup in 'ess-developer' (#137). - * Make closed paren indentation consistent - - Bug Fixes in 15.03: - * Fix open brace indentation bug (#27 in ess/R-ESS-bugs.R). - * Fix git version lookup - * Don't check directory modtime in R dialect. - * Declare all ess macros for edebug. - * Add 'ess-smart-comma' to eldoc message functions. - * Inform users when retrieving RDA aliases. - * Line ending in '~' is also a continuation line. - * Filing roxy paragraphs works as expected now. - * In 'ess-developer-add-package', remove incorrect 'wait' argument - from 'ess-get-words-from-vector' call. - * Fix #96, #117, #120, #125, #134, #137. - * Fix ess-quit-r. Call base::q() even if it is masked. - * Fix 'ess-show-buffer' to always display the buffer in another - window. - * Makefile: Fix cd bug for directories with spaces in them - * 'ess-kill-buffer-and-go' modified to not restart R - - Changes / Selected Bug Fixes in 14.09: - * ESS[Julia]: Executable is changed to 'julia'. - * ESS[Julia]: Completion and help system was adjusted to Julia - v.0.3.0. Julia v.0.2.x is no more supported. - * ESS[R]: Running R with 'gdb' debugger now works as expected - * iESS: Inferior ESS buffers are now derived from 'comint-mode' - * ESS[R]: 'ess-execute-screen-options' uses correct screen width in - terminal sessions - * ESS: 'ess-build-tags-for-directory' works when no TAGS file name - was provided - * ESS: 'ess-offset-statement-continued' is now respected everywhere - except inside of the 'if' test condition. - * ESS: New variable 'ess-offset-statement-first-continued' for - indentation of the first line in multiline statements. - * ESSR: Starting ',' in multiline statements indentation is now - ignored to achieve a more pleasant alignment. - * ESSR: Improved behavior of 'RET' in roxygen blocks. - * ESS[R]: command cleaning with 'C-u C-u C-y' was broken with lines - containing " + " - * ESS[R]: fixed "empty watch window bug" - * ESS[R]: don't ask for help location on ac-quick-help (request of - github #81) - * ESS[R]: "importClassesFrom" and "importMethodsFrom" were added to - the list of two-parameter roxygen commands - * ESS[R]: fix vignetes display and hyperlinks (were broken in - 13.09-1) - * ESS[Julia]: recognize function names ending with ! - * ESS[Julia]: fix indentation of "for" comprehension syntax within - brackets. - - Changes / Selected Bug Fixes in 13.09-1: - * ess-remote and TRAMP: R support code is now downloaded in binary - form instead of being injected from local machine. The R code is - stored in '~/.config/ESSR/' directory on the remote machine - * TRAMP: PAGER environment variable is now correctly set to - 'inferior-ess-pager' - * retrieval of help topics on remote machines is fixed - * org-babel: source references of R code executed from org files - correctly point to source references in original org files (version - 8.2.1 or higher of org-mode is required for this feature) - * 'ess-execute' is now bound to 'C-c C-e C-e' in 'ess-extra-map'. - * completion works again in 'ess-execute' - * ESS[R]: 'head' and 'tail' methods were replaced by '.ess_htsummary' - in 'ess-R-describe-object-at-point-commands' - * ESS[roxygen]: evaluation commands now work in roxygen blocks. - Leading comments are automatically removed before the evaluation - * ESS[transcript]: 'Clean Region' now works with multiline - statements; 'ess-transcript-clean-region' etc. correctly treat - multiline statements, i.e., no longer forgets the lines typically - preceded by '+' - * ESS[SAS]: Three features/fixes with special thanks to Matthew - Fidler https://github.com/emacs-ess/ESS/pulls/mlf176f2 - (https://github.com/emacs-ess/ESS/pulls/mlf176f2). Turn on SAS log - mode when appropriate. Indent comments and CARDS statement more - appropriately. - * ESS[SAS]: 'ess-sas-edit-keys-toggle' default returns to 'nil' - * ESS[R]: support for 'prettify-symbols-mode': contribution from - Rudiger Sonderfeld - * ESS[SWV]: knitr now evaluates in the current frame - * ESS[developer]: ess-developer doesn't kill open DESCRIPTION files - anymore - * ESS[roxygen]: 'ess-roxy-preview-HTML' is now on 'C-c C-o C-w' and - 'ess-roxy-preview-text' is now on 'C-c C-o C-t' - * ESS: installation with 'make install' was simplified and should - work out of the box on most *nix systems - * ESS installation instructions simplified - * fixed font-lock bug introduced in 13.09 that was causing very slow - process output - - Changes/New Features in 13.09: - * font-lock in process buffers doesn't "spill" over prompts. Missing - closing string delimiters should not cause wrong fontification of - the following command input. - * ESS[julia]: full features M-TAB completion and auto-complete - support, which now works for modules, structures and data types. - * ESS[julia]: a much better eldoc showing arguments of methods and - data type constructors - * ESS-developer: - - ESS-developer work-flow pattern has been streamlined: - ESS-developer is now automatically activated on per-file basis - if the file is part of a developed package - 'ess-developer-packages'. The old behavior (activation on - per-process basis) is still available on 'M-x ess-developer' - in a process buffer. - - integration with 'devtools' package. New command - 'ess-developer-load-package' calls 'load_all' on the package - containing current file. 'ess-developer-add-package' now - offers IDO menu completions with available loading methods, - currently 'library', and 'load_all'. Loading command can be - customized with 'ess-developer-load-on-add-commands'. - * 'TAB' now indents region if region is active (a contribution of - Matthew Fidler in pull #41) - * 'M-x ess-version' now reports full loading path and recognizes git - and ELPA versions. - * warning and error keyword are now highlighted with - 'font-lock-warning-face' as they should be, (for quite some time - these keywords have been hijacked by compilation mode - fontification). - * eldoc: Eldoc now recognizes multiple processes. If current process - is busy, or current buffer is not associated with a process, eldoc - picks its completions from the first available free process. - * org-babel: evaluation is now org-friendly - * help: new help buffers now try to reuse ess-help buffers. This - behavior is controlled by 'ess-help-reuse-window' custom variable. - * help: ?foo pops IDO menu on multiple help files (so far it worked - only for 'C-c C-v') - * remote evaluation is considerably faster now on slow connections - * ESS[R] tracebug R source references regular expressions are - (mostly) language agnostic. - * 'ess-function-call-face' inherits from - 'font-lock-function-name-face' rather than - 'font-lock-builtin-face'. - * 'ess-inject-source' now accepts 'function-and-buffer' option. - * Documentation: The "New Features" section (and 'NEWS') now - represent recent changes: within the last year or so. All changes - can be found in the new news.html (news.html) (or 'NEWS' and - 'ONEWS'). - * ESS[R] 'ess-rep-regexp' should no longer inf.loop (rarely!), and - hence 'M-x ess-fix-miscellaneous' should neither. - - Changes/New Features in 13.05: - * ESS[gretl]: Support for 'gretl' (both editing and sub-process - interaction). A contribution of Ahmadou Dicko. - * ESS: process output display is 4-10 times faster due to new caching - and only occasional emacs re-display (for the moment this - functionality is available only when 'ess-tracebug' is active). - * ESS: 'C-c `' is now bound to 'ess-show-traceback' and 'C-c ~' is - bound to 'ess-show-call-stack'. - * ESS[R]: ESS stores function in 'ESSR' environment to avoid kludging - users' global environment and accidental deletion. - * ESS[R]: new variable 'ess-swv-processing-command' to control - weaving and tangling. - * ESS[R]: 'ess-default-style' has been changed (from 'DEFAULT') to - 'RRR'. Use something like '(setq ess-default-style 'DEFAULT)' or - '(setq ess-indent-level 2)' in your '~/.emacs' equivalent _before_ - loading ESS, if you do not like this new "incompatible" default - style. - * ESS[julia]: ESS stores its functions in 'ESS' module. - * ESS[julia]: Eldoc is now supported in julia modes - * ESS[julia]: Adjusted error reference detection and interactive help - to julia internal changes - * ESS[R]: 'ess-use-tracebug''s default has been changed to 't'. Set - it to nil if you want to keep the previous behavior. - * ESS[tracebug]: Electric debug keys have been removed [breaking - change] The functionality was replaced with 'ess-debug-minor-mode' - and 'ess-debug-minor-mode-map'. - * ESS[tracebug]: 'ess-tracebug-map' is an alias to 'ess-dev-map' 'C-c - C-t'. - * ESS[tracebug]: 'ess-bp-toggle-state' ('C-c C-t o') can now be used - during the debug session to toggle breakpoints on the fly - (suggestion by Ross Boylan). - * ESS[tracebug]: 'ess-debug-flag-for-debugging' and - 'ess-debug-unflag-for-debugging' work correctly from the debugging - contexts. These commands also recognize non-exported functions for - the packages listed in 'ess-developer-packages' ('C-c C-t C-a'). - - * ESS[R]: Eldoc (activated by 'ess-use-eldoc') has become more - sophisticated, and hence also more intruding in the interface - between the Statistics softare, e.g., R, and the user. - - Note that you can turn off ElDoc, by placing '(setq ess-use-eldoc - nil)' in your '~/.emacs' file, prior to loading ESS, - - * ESS[SAS]: long over-looked 'SAS-mode-hook' appears! - * ESS[SAS]: 'ess-sas-edit-keys-toggle' now defaults to 't' since - 'sas-indent-line' is still broken, i.e. 'TAB' is now bound to - 'ess-sas-tab-to-tab-stop' by default - - Changes/Bug Fixes in 12.09-2: - * ESS: new 'ess-switch-to-end-of-proc-buffer' variable that controls - whether 'C-c C-z' switches to the end of process buffer. The - default is 't'. You can use prefix argument to 'C-c C-z' to toggle - this variable. - * ESS: fix in 'ess-eval-linewise' that was causing emacs to hang - during R debugging with 'ess-eval-visibly' equal to 't'. - * ESS: fix in 'ess-eval-linewise' that was causing emacs to recenter - the prompt in visible window - * ESS[tracebug]: A better handling of "Selection" prompts and debug - related singlekey commands. - * ESS: fix a bug in 'ess-switch-process' that was causing '*new*' - selection to fail. - * ESS[R]: Solve missing 'ess-local-process-name' bug in R-dired. - * ESS[SWV]: 'ess-swv-PDF' doesn't ask for a command to run if there - is only one command in 'ess-swv-pdflatex-commands'. - * ESS[SWV]: 'ess-swv-weave' gained an universal argument to allow for - an interactive choice between available weavers (sweave, knitr). - * ESS: 'ess-eval-*-and-step' functions go to next empty line at eob, - instead of staying at the last line. - - Changes/New Features in 12.09-1: - * ESS _Breaking Changes in Keys_: - - - New keymaps: 'ess-doc-map' bound to 'C-c C-d'; 'ess-extra-map' - bound to 'C-c C-e'; 'ess-dump-object-into-edit-buffer' was - moved on 'C-c C-e C-d' - - roxygen map was moved on 'C-c C-o' and 'ess-roxy-update-entry' - now resides on 'C-c C-o C-o' - - ess-handy-commands is not bound anymore - - 'ess-dev-map' (including 'ess-tracebug' and 'ess-developer') - moved on 'C-c C-t' - - 'C-c C-y' is deprecated in favor of 'C-c C-z C-z' - * ESS[R] new command 'ess-describe-object-at-point' bound to 'C-c C-d - C-e' (repeat 'C-e' or 'e' to cycle). It was inspired by Erik - Iverson's 'ess-R-object-tooltip'. Customize - 'ess-describe-at-point-method' to use tooltip instead of an - electric buffer. - * ESS: New command 'ess-build-tags-for-directory' bound to 'C-c C-e - C-t' for building dialect specific tag tables. After building tags - use 'M-.' to navigate to function and objects definitions. By - default 'C-c C-e C-t' builds tags based on imenu regular - expressions and also include other common languages '.c, .o, .cpp' - etc. But it relies on external 'find' and 'etags' commands. If - 'ess-build-tags-command' is defined (for 'R'), the inferior process - is asked to build tags instead. - * ESS: 'ess-switch-process' offers '*new*' alternative to start a new - process instead of switching to one of the currently running - processes. - * ESS: Switching between processes ('C-c C-s') uses buffer names - instead of the internal process names. Use 'M-x rename-buffer' - command to conveniently rename your process buffers. - * ESS: Process buffers can be automatically named on process creation - according to user specified scheme. Default schemes are *proc*, - *proc:dir* and *proc:abbr-long-dir* where 'proc' stands for the - internal process name and 'dir' stands for the directory where the - process was started in. The default is *proc*. For customization - see 'ess-gen-proc-buffer-name-function'. - * ESS: 'ess-eval-visibly-p' is deprecated in favor of - 'ess-eval-visibly'. - * ESS: New evaluation pattern 'nowait'. In addition to old 'nil' and - 't' values, 'ess-eval-visibly' accepts 'nowait' for a visible - evaluation with no waiting for the process. See 'ess-eval-visibly' - for details on evaluation patterns. - * ESS: New "Process" menu entry with process related commands and - configuration - * iESS: Process buffer is now automatically shown on errors - * ESS: New 'ess-switch-to-inferior-or-script-buffer' command bound to - 'C-c C-z' in both script and process buffers. If invoked form - process buffer it switches to the most recent buffer of the same - dialect. It is a single key command. - * ESSR-help: On multiple help pages with the same name, 'C-c C-v' now - asks for user resolution directly in emacs. - * ESS[R] ess-roxy: new variable 'ess-roxy-re' for fontification of - cases where the number of leading '#' differs from 'ess-roxy-str'. - * ESS[R] Eldoc was considerably enhanced. It now finds hidden - default S3 methods and displays non-default methods' arguments - after trailing ||. - * ESS[R]: New 'ess-display-demos' command bound to 'C-c C-d o' and - 'C-c C-d C-o' - * ESS: New 'ess-help-web-search' command bound to 'C-c C-d w' and - 'C-c C-d C-w' to facilitate interactive search of web resources. - Implemented for 'R', 'Stata' and 'Julia'. See also - 'ess-help-web-search-command'. - * ESS: ess-pdf-viewer-pref accepts now command line arguments - * ESS[Rnw]: Add knitr support. Customize 'ess-swv-processor' for the - default processor. - * ESS[Rnw]: More thorough renaming of remaining 'noweb-*' to - 'ess-noweb-*'. - * ESS[Rnw] new commands 'ess-eval-chunk-and-step' and - 'ess-eval-chunk' bound to 'M-n C-c' and 'M-n C-M-x' to mirror - standard ess commands in C-c map. - * ESS[R] Auto-completion: new variable 'ess-ac-R-argument-suffix' to - customize the insertion of trailing "=". Defaults to " = ". - * ESS[Julia]: Added index, apropos and web-search to julia. - * ESS help: More evaluation commands were added to ess-help mode - ('C-c C-c', 'C-M-x' etc) - - Bug Fixes in 12.09-1: - * iESShelp: Multiple help pages with the same name are properly - handled on 'C-c C-v' - * iESSremote: Evaluation with ESS remote no longer freezes emacs. - * iESS: 'comint-previous-prompt' 'C-c C-p' no longer stops on - secondary prompt "+". - * iESS[R], iESS(Sqpe) [S] on Windows: The 'options("editor")' is now - initialized to 'emacsclient' instead of the previous 'gnuclient'. - The user may need to add the line '(server-start)' to the emacs - initialization file. 'emacsclient' has been included with emacs - since GNU Emacs 22.1. - * ESS[Rnw] Fixed "connection to R" bug (in 12.09 only). - * ESS[Rnw] Explicit 'ess-swv-stangle' and 'ess-swv-sweave' functions. - * ESS[Rnw] Fixed completion and smart underscore problems cause by - unmatched "\"' - * ESS[R] is more careful with the 'R' code injection. It now happens - only once at the start of the session. - * ESS[R]: Fixed auto-scrolling the comint buffer on evaluation. - * ESS[Julia]: Solve several indentation and word navigation problems. - * ESS[Julia]: Help system works again. - - Changes/New Features in 12.09: - - * Due to XEmacs lacking some features that ESS requires, ESS support - of XEmacs ends with ESS 12.04-4. This decision will be re-visited - in the future as XEmacs continues to sync with GNU Emacs. - - * ESS[R]: On Windows, there is now a new customizable variable - (currently called 'ess-directory-containing-R') to tell ESS where - to look for the 'Rterm.exe' executables. The name of the variable - and the values it can take are both in beta and subject to change. - Prior to this variable, ESS searched only in the default - installation directory. Setting this variable now tells ESS how to - find 'Rterm.exe' executables when they are installed somewhere - else. - - * ESS[julia]: _new_ mode for editing julia code ('*.jl'). Start with - 'M-x julia'. - - Full interaction interface, imenu and basic error referencing are - available. - - * ESS[R] noweb: 'noweb-mode' and 'noweb-font-lock-mode' have been - renamed to 'ess-noweb-mode' and 'ess-noweb-font-lock-mode' to avoid - conflicts with the "real" 'noweb-mode'. - - * ESS[R] noweb: The long standing font-lock bug has been solved in - 'ess-noweb' interface. - - * ESS: Basic evaluation keys are now bound to 'ess-eval-region-*-' - functions: - - - 'C-M-x' is bound to 'ess-eval-region-or-function-or-paragraph' - - 'C-c C-c' is bound to - 'ess-eval-region-or-function-or-paragraph-and-step' - - 'C-RET' is bound to 'ess-eval-region-or-line-and-step' - - Each of these functions first evaluates the region whenever the - region is active. - - * ESS: 'C-M-a'/'C-M-e' now step to beginning/end of paragraph if no - function has been detected. - - * ESS: 'ess-eval-*-and-step' family of functions are now smarter, and - don't step to end of buffer or end of chunk code ('@') when at the - end of the code. - - * ESS: 'ess-handy-commands' function is bound to 'C-c h' - - * ESS: ESS is now _blinking_ the evaluated region. Set - 'ess-blink-region' to nil to deactivate; 'ess-blink-delay' gives - the duration of the blink. Evaluated region is "blinked" in - 'highlight' face. - - * ESS[R-help] New key 'a' for "apropos()" in help buffers. Also - available through 'C-c h'. - - * ESS[R-help] All R commands of type foo?bar and foo??bar are - recognized and redirected into appropriate *ESS-help* buffers. - - * ESS[R]: New customization interface for _font-lock_. - - ESS font-lock operates with predefined keywords. Default keywords - are listed in 'ess-R-font-lock-keywords' and - 'inferior-R-font-lock-keywords', which see. The user can easily - customize those by adding new keywords. These variables can also - be interactively accessed and saved through 'ESS/Font-lock' - submenu. - - Several new fontification keywords have been added. Most notably - the keywords for highlighting of function calls, numbers and - operators. - - * ESS[R]: auto-complete is now activated by default whenever - auto-complete package is detected. Set 'ess-use-auto-complete' to - nil to deactivate. - * ESS[R]: R AC sources are no longer auto-starting at 0 characters - but at the default 'ac-auto-start' characters. - * ESS no longer redefines default ac-sources, but only appends - 'ac-source-filename' to it. - * ESS: 'ac-source-R' now concatenates " = " to function arguments. - - * ESS: Menus for ESS and iESS have been reorganized and enriched with - _Tracebug_ and _Developer_ submenus. - - * ESS[R]: 'ess-developer' and 'ess-tracebug' commands are available - by default in 'ess-dev-map' which is bound to 'C-c d' in ESS and - iESS maps. - - * ESS[R]: 'eldoc' truncates long lines whenever - 'eldoc-echo-area-use-multiline-p' is non-nil (the default). Set - this variable to t if you insist on multiline eldoc. See also - 'ess-eldoc-abbreviation-style'. - - * ESS[R]: completion code pre-caches arguments of heavy generics such - as 'plot' and 'print' to eliminated the undesirable delay on first - request. - - * iESS: Prompts in inferior buffers are now highlighted uniformly - with 'comint-highlight-prompt' face. - - * ESS[R]: R process no longer wait for the completion of input in - inferior buffer. Thus, long running commands like 'Sys.sleep(5)' - no longer stall emacs. - - * ESS: [R, S, Stata, Julia] have specialized 'ess-X-post-run-hook's, - which are run at the end of subprocess initialization. - - * ESS[Stata]: All interactive evaluation commands work as expected. - On-line comments are removed before the evaluation and multiline - comments are skipped on 'C-c C-c' and other interactive commands. - - * ESS no longer auto-connects to a subprocess with a different - dialect than the current buffer's one. - - * ESS: 'ess-arg-function-offset-new-line' is now a list for all the - ESS indentation styles, which results in the following indentation - after an open "(": - - a <- some.function(other.function( - arg1, - arg2) - - * ESS[SAS]: Improved MS RTF support for GNU Emacs; try - 'ess-sas-rtf-portrait' and 'ess-sas-rtf-landscape'. - - Changes/Bug Fixes in 12.04-3: - * ESS: basic support for package.el compatibility - * ESS[R]: correct indentation of & and | continuation lines - * 'M-x ess-version' shows the svn revision even after 'make install' - * ESS[SAS]: improved XEmacs support - * iESS[R]: better finding of previous prompt - * ESS[Stata]: adjusted prompt for mata mode - * ESS[R]: resolved name clashes with cl.el - * ESS[R]: removed dependence on obsolete package assoc - * New 'make' target 'lisp', to build the lisp-only part, i.e., not - building the docs. - - Changes/New Features in 12.04-1: - * iESS[Stata]: New interactive help invocation. - * iESS[Stata]: New custom variable 'inferior-STA-start-file'. - * iESS[Stata]: 'inferior-STA-program-name' is now "stata" and can be - customized. - * ESS[Stata] New sections in stata help files Syntax('s-S'), - Remarks('r'), Title('t'). - - Bug Fixes in 12.04-1: - * ESS[R]: Better 'ess-tracebug' error handling. - * ESS[R]: Corrected 'ess-eldoc' help string filtering and improved - argument caching. - * ESS[R]: Indentation of non-block if/else/for/while lines fixed. - * 'M-x ess-version' should work better. - * ESS: Filename completion now again works inside strings. - * iESS[Stata]: Fixed prompt detection issue. - * ESS[Rd]: R is autostarted also from here, when needed. - - Changes/New Features in 12.04: - * ESS: Reverting new behavior of 12.03, 'TAB' in 'ess-mode' no longer - completes by default. If you want smart 'TAB' completion in R and - S scripts, similarly to iESS behavior, set the variable - 'ess-tab-complete-in-script' to 't'. Also see - 'ess-first-tab-never-complete' for how to customize where first - 'TAB' is allowed to complete. - * ESS: completion is consistently bound to 'M-TAB' (aka 'M-C-i') in - both Emacs23 and Emacs24. - * ESS: The variable 'ess-arg-function-offset-new-line' introduced in - ESS(12.03) now accepts a list with the first element a number to - indicate that the offset should be computed from the indent of the - previous line. For example setting it to '(2) results in: - - a <- some.function( - arg1, - arg2) - - Changes/New Features in 12.03: - * ESS indentation: new offset variable - 'ess-arg-function-offset-new-line' controlling for the indentation - of lines immediately following open '('. This is useful to shift - backwards function arguments after a long function call expression: - - a <- some.function( - arg1, - arg2) - - instead of the old - - a <- some.function( - arg1, - arg2) - - If '(' is not followed by new line the behavior is unchanged: - - a <- some.function(arg1, - arg2) - - This variable should be set as part of indentation style lists, or - in ess-mode hook. - * ESS[R]: 'C-c .' sets (indentation) style. - * ESS: In ESS buffers 'yank'('C-y') command accepts double argument - 'C-u C-u' to paste commands only. It deletes any lines not - beginning with a prompt, and then removes the prompt from those - lines that remain. Useful to paste code from emails, - documentation, inferior ESS buffers or transcript files. - * Documentation: ESS user manual has been rearranged and completed - with several new chapters and sections to reflect newly added - features ("Completion", "Developing with ESS", "ESS tracebug", "ESS - developer", "ESS ElDoc", "IDO Completion" and "Evaluating Code") - * RefCard: Reference card was updated to include new features. - * Eldoc: Eldoc was rewritten and is activated by default. See - 'ess-use-eldoc', 'ess-eldoc-show-on-symbol', - 'ess-eldoc-abbreviation-style' variables for how to change the - default behavior. _Note:_ 'skeleton-pair-insert-maybe' prohibits - eldoc display, on '(' insertion. - * ESS[R]: Eldoc shows arguments of a generic function whenever found. - * ESS: 'TAB' in 'ess-mode' now indents and completes, if there is - nothing to indent. Set 'ess-first-tab-never-completes-p' to 't' to - make 'TAB' never complete on first invocation. Completion - mechanism is similar to the completion in the 'inferior-ess-mode' - - a filename expansion is tried, if not found ESS completes the - symbol by querying the process. - * ESS for emacs version 24 or higher: ESS is fully compatible with - the emacs 24 completion scheme, i.e. all the completion is done by - 'completion-at-point'. Also in accordance with emacs conventions, - ESS doesn't bind 'M-TAB' for emacs 24 or higher. 'M-TAB' calls the - default 'complete-symbol'. - - * ESS[R]: Out of the box integration with 'Auto Completion' mode - http://cx4a.org/software/auto-complete - (http://cx4a.org/software/auto-complete) . Three AC sources - 'ac-source-R-args', 'ac-source-R-objects' and 'ac-source-R' are - provided. The last one combines the previous two and makes them - play nicely together. Set 'ess-use-auto-complete' to 't' to start - using it. Refer to documentation string of 'ac-use-auto-complete' - for further information. - * ESS[R]: New unified and fast argument completion system, comprised - of 'ess-funname.start', 'ess-function-arguments', - 'ess-get-object-at-point'. Eldoc and auto-completion integration - are using this system. - * ESS: 'ess-switch-to-end-of-ESS'('C-c C-z'), and - 'ess-switch-to-ESS'('C-c C-y'): Automatically start the process - whenever needed. - * ESS[R]: 'roxy' knows about previewing text version of the - documentation. Bound to 'C-c C-e t'. - * ESS[R]: Solved the "nil filename" bug in roxygen support. - * ESS[R]: 'ess-tracebug' is now part of ESS: - - New Features: - - - Source injection: Tracebug now can inject source references on - the fly during code evaluation, i.e. you don't have to source - your file, but just evaluate your code in normal fashion. - Variable 'ess-tracebug-inject-source-p' controls this behavior - - if t, always inject source reference, if ''function', inject - only for functions (this is the default), if 'nil', never - inject. - - During the source injection the value of 'ess-eval-visibly' is - ignored. - - Org-mode support: Visual debugger is now aware of the - temporary org source editing buffer ('C-c '') and jumps - through this buffers if still alive, or in original org buffer - otherwise. - - New keys in watch mode: '?' and 'd' - - Two new hooks: ess-tracebug-enter-hook and - ess-tracebug-exit-hook - - * ESS[R]: New package 'ess-developer' to evaluate 'R' code directly - in the package environment and namespace. It can be toggled on and - off with 'C-c d t'. When 'ess-developer' is on all ESS evaluation - commands are redefined to evaluate code in appropriate - environments. Add package names to the list of your development - packages with 'C-d a', and remove with 'C-d r'. Source the current - file with 'C-d s'.Evaluation function which depend on - '`ess-eval-region'' ask for the package to source the code into, - 'ess-eval-function' and alternatives search for the function name - in the development packages' environment and namespace and insert - the definition accordingly. See the documentation section - "Developing with ESS/ESS developer" for more details. - - * ESS[R] help system: - - New Features: - - - 'q' quits window instead of calling - 'ess-switch-to-end-of-ESS'. This is consistent with emacs - behavior help and other special buffers (_breaking change_). - - 'k' kills window without asking for the name (pointed by Sam - Steingold) - - Help map inherits from 'special-mode-map' as sugested by Sam - Steingold. - - Package index: new function 'ess-display-index' bound to 'i' - in help mode map. - - Package vignettes: new function 'ess-display-vignettes' bound - to 'v' in help mode map. - - Display help in HTML browser: new function - 'ess-display-help-in-browser' bound to 'w' in help mode map. - It depends on 'R''s 'browser' option. - - New custom variable 'ess-help-pop-to-buffer': if non-nil ESS - help buffers are given focus on display. The default is 't' - (_breaking change_). - - New menu entries for the above functions. - - Bogus help buffers are no longer generated by default, i.e. - buffers of the form "No documentation for 'foo' in specified - packages and libraries: you could try '??foo' ". - 'ess-help-kill-bogus-buffers' now defaults to 't'. Beware, - there may be instances where the default is unsatisfactory - such as debugging and/or during R development. Thanks to Ross - Boylan for making the suggestion, Sam Steingold for reminding - us of this variable and Martin Maechler for the warning. - * ESS now uses 'IDO' completing read functionality for all the - interactive requests. It uses ido completion mechanism whenever - available, and falls back on classical completing-read otherwise. - You can set 'ess-use-ido' to nil if you don't want the IDO - completion. See the documentation string of 'ess-use-ido' for more - information about 'IDO' and ESS configuration. - - * ESS[S]: "','" is bound to ess-smart-comma: If comma is invoked at - the process marker of an ESS inferior buffer, request and execute a - command from '`ess-handy-commands'' list. If - 'ess-R-smart-operators' is t '`ess-smart-comma' also inserts " " - after comma. - * ESS[S], notably 'R': Variable '`ess-handy-commands'' stores an - alist of useful commands which are called by 'ess-smart-comma' in - the inferior buffer. - - Currently containing: - - change-directory - 'ess-change-directory' - help-index - 'ess-display-index' - help-object - 'ess-display-help-on-object' - vignettes - 'ess-display-vignettes' - objects[ls] - 'ess-execute-objects' - search - 'ess-execute-search' - set-width - 'ess-execute-screen-options' - install.packages - 'ess-install.packages' - library - 'ess-library' - setRepos - 'ess-setRepositories' - sos - 'ess-sos' - - Handy commands: 'ess-library', 'ess-install.packages', etc - ask - for item with completion and execute the correspond command. - 'ess-sos' is a interface to 'findFn' function in package 'sos'. If - package 'sos' is not found, ask user for interactive install. - - * ESS: New dynamic mode line indicator: Process status is - automatically reflected in all mode-lines of associated with the - process buffers. Particularly useful for displaying debug status - of 'ess-tracebug' and developer status of 'ess-developer' in all - associated buffers. - - * ESS: New 'ess-completing-read' mechanism: ESS uses 'ido' - completions whenever possible. Variable 'ess-use-ido' controls - whether to use ido completion or not. Active by default. - - * ESS now supports comint fields for output and input detection. - This feature is not used by default, but might be useful in the - future. - - * ESS[S]: New custom variable 'inferior-ess-S-prompt' to customize - prompt detection regular expression in the inferior ESS buffers. - You can customize this variable to enhance comint navigation - ('comint-previous-prompt' and 'comint-next-prompt') the inferior - buffers. - - * ESS[R]: Internal 'R' completion retrieval - ('ess-R-complete-object-name') was rewritten and is faster now. - - * ESS is using process plist to store process specific variables, as - opposed to buffer local variables as it was using before. The use - of buffer local variables to store process variables is - discouraged. - - * ESS: new functions to manipulate process plists: 'ess-process-get' - and 'ess-process-set'. - - * ESS: Internal process waiting mechanism was completely rewritten. - ESS no more relies on prompt regular expressions for the prompt - detection. The only requirement on the primary process prompt is - to end in '> '. This could be overwritten by setting - 'inferor-ess-primary-prompt'. - - * ESS[S], notably 'R': Saved command history: ESS-HISTORY-FILE now - accepts 't' (default), 'nil', or a file name. By setting it to - 'nil' no command line history is saved anymore. - ESS-HISTORY-DIRECTORY now allows to have the history all saved in - one "central" file. - * ESS[R]: more Roxygen improvements. - * ESS[R]: 'C-c .' to set (indentation) style. - - * ESS[R]: Functions with non-standard names (for example - 'aaa-bbb:cc') are properly handled by font-lock and evaluation - routines. - * ESS[R]:Several regexp bugs (described in etc/R-ESS-bugs.el) were - fixed in 'ess-get-words-from-vector' and 'ess-command'. - - Changes/New Features in 5.14: - * ESS[BUGS/JAGS]: Batch BUGS is back! For recent OpenBUGS versions, - 3.0.8+, a batch BUGS script is once again available, but for Linux - only. Therefore, since it seems that BUGS and JAGS must co-exist - (rather than a transition from BUGS to JAGS), .bug files are now in - ESS[BUGS] mode and .jag files are in ESS[JAGS] mode. ESS[BUGS] now - works like ESS[JAGS] rather than the original mode ESS[BUGS] mode - which was difficult to maintain. Although, ESS[BUGS] appears to - work, there still may be some features missing as well as bugs. - - * ESS[R]: New customizable variable 'ess-swv-plug-into-AUCTeX-p' - Commands to Sweave current file and LaTeX the result are now - available to AUCTeX users, if this variable is set to 't'. - - * ESS[S]: 'C-c C-c' ('ess-eval-function-or-paragraph-and-step') is - now skipping over comments as the other paragraph functions do. It - (and similar functions) should no longer wrongly find 'function()' - beginnings inside comments or strings. - - * ESS[SAS]: improved by better support for GNU Emacs - - Changes/New Features in 5.13: - * ESS[R]: On Windows, for R 2.12.0 and later, the Rterm executables - (in subdirectories i386 / x64) now are found as well as for earlier - R versions. - * ESS[S+]: on Windows, both 32- and 64-bit versions of S+ ("S-PLUS") - are found now and made available on the menu. - * ESS[R]: When prompting for a starting directory, the R version is - (always?) correct now. - * ESS[R]: on non-Windows platforms, the 'use-dialog-box' variable is - no longer temporarily changed (to 'nil' for R-x.y.z version - functions and to 't' for 'R' itself), but rather the user - customization is obeyed. - * ESS[R]: more Roxygen improvements. - * 'Rd-preview-help' now generates preview buffers with navigation - facilities the same as regular help buffers. - * ESS: New functions and keys C-c [up] / [down] for evaluating the - buffer "from beginning till here". - - Changes/New Features in 5.12: - * ESS[SAS] Font-locking: update of PROCs keywords (up to SAS 9.22); - error/warnings. - * ESS[R]: Roxygen improvements: S4 classes; also optionally keep - spaces when filling arguments - * ESS[Rd]: support new keywords: section-name \subsection plus a - dozen "new" keywords; should match R 2.12.x now. - * 'ess-display-help-on-object' ('C-c C-v') now _caches_ the list of - topics, thus speeding up the improvement feature introduced in 5.9. - - Changes/New Features in 5.11: - * Filename completion within buffers now adds only trailing - characters to complete the filename, rather than expanding to an - absolute file path. This filename completion is bound to the TAB - key. - - * 'M-n P' in Sweave buffers now prompts for the command to run - instead of using 'pdflatex' unconditionally, offering completion - from customizable collection 'ess-swv-pdflatex-commands', the first - of which is taken as default and that defaults to 'texi2pdf'. - * 'M-RET' is now also bound in S language (R and S+) buffers to - 'ess-use-this-dir'. It sends 'setwd(..)' to the S process to set - the working directory to the one of the source file. - - Changes/New Features in 5.10: - * 'M-RET' in *S* buffers is now bound to 'ess-dirs'. This function - will set Emacs's current directory to be the same as the *S* - process. This is useful if you use 'setwd()' within a *S* process. - - Changes/New Features in 5.9: - * Toolbar: The toolbar now has an icon for starting Splus. - * Indentation: New documentation and code has been added to make it - easier to change how ESS indents code. In particular, see - 'ess-default-style', 'ess-own-style-list' and the documention - subsection "Changing indentation styles". - * 'ess-display-help-on-object' ('C-c C-v') now offers completion - candidates for help file aliases, in addition to object names. - * Font locking: is now turned on even without 'window-system' is - 'nil', whenever ESS-FONT-LOCK-MODE is non-nil, i.e., by default. - * ESS script editing: ess-eval-deactivate-mark default is now t, as - suggested by Leo Alekseyev and subsequent "unanimous" ESS-help - discussion. - * ESS[R]: Editing support for "#!" (Rscript / littler) editing, - thanks to Jeffrey Arnold. - * ESS[R]: Now finds all R versions, both 64-bit and 32-bit, on some - 64-bit Windows machines. Please report back to ess-core success or - failure on your 64-bit Windows machine. - * ESS Manual now more visually pleasing; - - * ESS[R]: Roxygen on XEmacs no longer font locks for now (as it - required missing features and hence broke ESS startup, there). - * ESS[R]: Roxygen has a sub-menu on the [ESS] menu. - * ESS[R]: Function 'ess-rutils-htmldocs' in 'ess-rutils.el' offers an - alternative to 'help.start()' for navigating R documentation, using - the 'browse-url' Emacs function. - - Changes/New Features in 5.8: - * ESS[R]: New 'ess-rutils.el' with utilities for listing, loading, - installing, and updating packages, as well as object manipulation - (listing, viewing, and deleting). It also provides an alternative - to 'RSiteSearch()' that uses the 'browse-url' function, so results - can be viewed in an Emacs web browser. - * ESS[R]: much more extensive Roxygen interface, via ess-roxy.el from - Henning Redestig. Ess-roxy supports filling of roxygen fields, - generation and updating roxygen templates, completion of roxygen - tags, basic navigation (marking and moving between entries), - folding using hs-minor-mode and preview of the Rd file. - * Emacs lisp files have got better names (partly, for now). - - Changes/New Features in 5.7: - * ESS[R]: loading a source file ('C-c C-l') now works in Windows, - similarly to other platforms; (further; it had accidentally been - broken in ESS 5.6 on all platforms) - - Changes/New Features in 5.6: - * ESS[R]: help() calls have to differ from old default, with newer - versions of R; currently via .help.ESS <- function(...) hack. - - Changes/New Features in 5.4: - * ESS[SAS]: The long overdue change from 'make-regexp' to - 'regexp-opt' for font-locking is complete. The new 'regexp-opt' is - now the default since it is better than the old code in many ways - (and especially more maintainable). However, there are certainly - some special cases missed (bug reports and patches welcome!). - Setting 'ess-sas-run-regexp-opt' to 'nil' will result in the old - code being used. - * ESS[BUGS] and ESS[JAGS]: typing '=' now results in '<-'. - * ESS[R] function arguments "show" '(ess-r-args-show)' now uses the - new '(tooltip-show-at-point)' contributed by Erik Iverson. - * Toolbar icons now also work in (beta) Emacs 23. - * ESS[S]: New function 'ess-change-directory' for setting both emacs' - current directory and the directory of an *R* or *S* buffer. - * ESS[S] when transient-mark-mode is true, the mark is now kept, - rather than deactivated, thanks to a patch from David Reitter. - - Changes/New Features in 5.3.11: - * ESS[SAS]: work around bug in Emacs 22.2 & 22.3 which fails to set - case-fold fontification automatically. - * Rd mode: support new keyword 'Rdversion' - * ESS[R]: now again works with Emacs 21.x - - Changes/New Features in 5.3.10: - * Fixed noweb-mode bug accidentally introduced into 5.3.9 - * In noweb-mode, e.g., Rnw-mode, electric "<" also inserts closing - "@". Further, the code chunk boundaries are better kept - up-to-date, such that code[R] <-> text[LaTeX] minor mode switching - should happen more reliably. - * In noweb-mode, fix a buglet in rare [Enter] or [Tab] behavior; - further, by default disable the former '[[' .. ']]' - code-protection-when-filling behavior which has been found to be - buggy. - - Changes/New Features in 5.3.9: - * ESS[SAS]: evince PDF viewer now supported as well; search order: - evince, Xpdf, Adobe/Acrobat Reader - * ESS[R]: added support for Roxygen, potentially to be extended. - * ESS[S] (and R): inferior ('*R*') and transcript modes no longer - fontify language keywords (such as 'for', 'in', etc). - * iESS[Stata]: Customize the 'ess-sta-delimiter-friendly' setting to - 't' to convert embedded semi-colons to newlines for Stata - processing. - * Sweave fix for embedded blanks in PDF reader and PDF files - * Several fixes for Major Mode Convention violations in 'ess-mode' - and 'noweb-mode'. - * ESS[JAGS]: 'M-x comment-region' now available! - * ESS[S] The 'ess-swv-*' commands (and keybindings) are now in a - submenu of the "Noweb" menu, when editing Sweave files. - - Changes/New Features in 5.3.8: - * ESS[JAGS]: more separation from ESS[BUGS] (as much as is currently - planned); now 'C-c C-c' on an empty '.jmd' creates a template as it - should; symbolic links are created for CODA output so BOA is happy: - from 'index.txt' to '.ind' and 'chain#.txt' to '#.out' - * ESS[SAS]: buffer-local 'ess-sas-submit-command' and - 'ess-sas-submit-command-options' now recognized by - 'ess-sas-submit-region' - * ESS[S]: When trying to evaluate code in an S language buffer and - there is no associated process, now start R automatically instead - of signalling an error. Also, restart R if there is an associated - process which is not running. However, do not start R just via the - "electric" '(' ('ess-r-args-auto-show'). - * ESS[S]: For (one-line) functions withOUT '{ .. }' bodys, the end - of function is now correctly found more often. This notably - improves 'C-c C-c' ('ess-eval-function-or-paragraph-and-step'). - * ESS[JAGS]: cleanup/re-organization of elisp code; symbolic links - for CODA output are now only created by the new JAGS 'system' - command in version 1.0.3; specify whether this command is available - via 'ess-jags-system'; if not present, then no links are created so - that the '*shell*' buffer does not become unresponsive during the - batch run - - Changes/New Features in 5.3.7: - * ESS: 'ess-default-style' now *is* customizable, i.e., changing its - value in '~/.emacs' now does have the desired effect. - * ESS: 'ess-font-lock-mode' is a new variable (default: t) which - controls whether font-locking is enabled in ESS buffers. - * ESS[R]: for XEmacs on Windows; another tweak to find R versions - * ESS[SAS]: font-locking updated for ODS and SAS Bayesian Procedures; - a more consistent handling of SAS options by - 'ess-sas-submit-command-options' which is buffer-local; portable - snooze for MS Windows via customize-able 'ess-sleep-for' (floats - welcome); Xpdf now supported as a PDF viewer - * ESS[Rnw]: now also works with "emacs -nw" and Emacs 22. - * ESS[JAGS]: now requires JAGS 1.0 (see the new ESS for JAGS help - section for more information): both need work; suggestions welcome - * ESS[R]: [TAB] completion now uses the R-internal completion - mechanism (for R >= 2.5.0). - * ESS[R] ([S]): interpretation of "_" as assignment has been removed - in 'ess-continued-statement-p' for R and S. - * several internal code cleanups. - * ESS[R]: An experimental version of a new command 'Rgui' on MS - Windows to send lines directly from emacs to 'Rgui' is available in - file 'lisp/essd-rgui.el'. Preliminary documentation is in file - 'doc/rgui-doc.txt'. - - Changes/New Features in 5.3.6: - * ESS: for XEmacs, using "gnuclient" (without a "-q") works for - things like fix() after M-x gnuserv-start has been done. - * ESS[R]: M-x R-newest should now work in more situations on MS - Windows, e.g., when R has been installed in a non-default - "ProgramFiles" directory tree. In these cases, there's no need to - specify the name (and full path) of the R program anymore. - * ESS[R]: For XEmacs, startup (with new tooltip code) works again. - - Changes/New Features in 5.3.5: - * ESS[R] a new defun is available, 'M-x R-newest', which will start - the newest version of R that it can find on your system. - * ESS[R] add Sven Hartenstein's "R function arguments tips" - functionality, via new file '../lisp/essd-r-args.el'. Note that - this includes an "electric "("" behavior inside 'R-mode' which is - _active by default_ and can be customized via - 'ess-r-args-electric-paren'; i.e., use '(setq - ess-r-args-electric-paren nil)' to turn it off. Further, - 'ess-r-args-show-as' allows to switch to the "tooltip" mode. - * ESS: functions 'ess-get-pdf-viewer' and *-ps-viewer; built on new - customizable variables 'ess-pdf-viewer-pref' and - 'ess-ps-viewer-pref'; currently used in 'ess-swv-PDF' and '*-PS'. - * ESS[R] Improved 'ess-swv-PDF' to run pdf viewer only if pdflatex - was ok - * ESS[R] Improved 'ess-swv-weave' to start R automatically if none is - running. - * ESS: Do no longer ask _which_ ESS process to use if there is only - one. - - Changes/New Features in 5.3.4: - * ESS[R] now better work with options(error=recover); and the new - default of CHM help files on windows. - * ESS[R] some more cleanup in the "sweave" functions - * miscellaneous fixes - - Changes/New Features in 5.3.3: - * ESS[S] fix buglet (5.3.2 only) which left command prompt in - "execute buffer" and hence help files. - * new customizable variable 'ess-display-buffer-reuse-frames' set to - true (which changes default behavior) such that execution or help - *frames* are reused. - - Changes/New Features in 5.3.2: - * Classic BUGS now supported by '(require 'essd-bugs)' with ESS[BUGS] - and JAGS by '(require 'essd-jags)' with ESS[JAGS]. But, only one - of them can be used at a time since they don't play nice together. - Also, 'C-c C-c' is now bound to the function 'ess-bugs-next-action' - ('F12' has been retired). And finally, note that 'essl-bug.el' is - deprecated and the replacement is 'essl-bugs.el'. - * ESS[R] Improved some of the "Sweave-make" functions (yet scarcely - documented) in 'ess-swv.el'. - * ESS[S] No longer mess with .Last.value (nor in other "languages"). - - Changes/New Features in 5.3.1: - * See the docs for 2 ways to install ESS for XEmacs - 1. by uncommenting the XEmacs part of Section 1 of 'Makeconf' and - performing 'make install' - 2. by unpacking either 'ess-5.3.1.tgz' or 'ess-5.3.1.zip' into - 'PREFIX/lib/xemacs/site-packages' on unix or - 'PREFIX\XEmacs\site-packages' on windows - * ESS[R]: fixed bugs so that Rterm.exe can be found by XEmacs - * ESS[S]: 'ess-toggle-S-assign-key' is slightly changed; in - particular, the default 'ess-assign-key' is now 'C-x ='. - * ESS[R]: 'M-x R-site-search' is a new (slightly experimental) - utility similar to R's 'RSiteSearch(..)' but with the advantage of - using Emacs' preferred browser, see 'browse-url-browser-function' - - Changes/New Features in 5.3.0: - * ESS[BUGS]: sanely re-format statistical output, '.bog', from - scientific notation to numbers rounded with 4 decimal places with - 'M-x ess-bugs-sci-round-to-4-dp'. - * The keys for navigating among section headings in help buffers - worked, but only for one language per session; they should now work - for multiple languages. (They were also broken on Windows - machines.) - * ESS[S] long standing buglets in the internal logic for loading lisp - code on Windows. Particularly fixed behavior in help mode with - S-plus GUI. - * New variable, 'ess-use-inferior-program-name-in-buffer-name', which - enables using the executable name instead of the dialect name for - R. Feature request. - * ESS[S] 'ess-execute-screen-options' now also works correctly when - there is more than one window *side-by-side* in the same frame and - runs in the correct buffer also when there is more than one S - buffer. - * iESS[S] new functions 'ess-eval-paragraph-and-step' and - 'ess-eval-function-or-paragraph-and-step' are bound to keys 'C-c - C-p' and 'C-c C-c' respectively and to the menu in ESS-mode; also - bound in the help mode (for evaluating examples). - * ESS[S] new function 'ess-toggle-S-assign-key' allows to assign the - " <- " insertion to an arbitrary key. - - Changes/New Features in 5.2.12: - * ESS[SAS]: 'M-;' fixed, but the XEmacs function 'comment-dwim' may - be broken, if so, use 'M-x comment-region' and 'M-x - uncomment-region' instead; only valid PROCs are fontified which is - very helpful finding syntax errors (currently supported: BASE, ETS, - FSP, GRAPH, IML, INSIGHT and STAT); the "feature" where 'F'-keys - take you to an empty buffer when the requested destination is a - file that does not exist has been fixed, now the request results in - a no-op. Further, sas-mode now also works in simple terminals. - * Rterm/Cygwin combination works under Microsoft Windows. - * ESS[R]: internal calls use baseenv() instead of NULL and define - 'baseenv' where needed. - * New experimental support for installing ESS. See the file - 'lisp/ess-install.el'. - - Changes/New Features in 5.2.11: - * ESS Info entry and 'dir' handled more effectively for GNU Emacs - users - * ESS[SAS]: temporary files created for batch submission of a region - are now named based on the current file; see 'ess-sas-file-root' - for details; all 'lag' and 'dif' functions now fontified correctly - * iESS[SAS]: fixed a few nagging bugs, however, still does not appear - to work at this time; please let us know if you have any ideas. - * ESS[S]: Support for running other versions of Splus has been added - for unix. Two new variables, 'ess-s-versions' and - 'ess-s-versions-list', are used to tell ESS what other versions of - Splus you would like to run. - - Changes/New Features in 5.2.10: - * ESS[R]: ess-r-versions can no longer be customized (since the - customization was not taking effect unless customizations were - loaded before ESS). Its value has been changed so that it will also - find R executables beginning "R-devel" and "R-patched". If you - wish to change this variable, it must be set in your '.emacs' - before ESS is loaded. - * Installation with GNU Make enhanced: unix and unix-like operating - systems will now be able to install ESS for all users in either a - GNU Emacs site-lisp or an XEmacs package configuration by editing - 'lisp/ess-site.el' and 'Makeconf' accordingly, then issuing 'make - install' - * ESS[S]: Filename completion (inside strings) now also works in - XEmacs for R and S-plus. - - Changes/New Features in 5.2.9: - * ESS[R] for Windows: the \ directory character bug with respect to - ess-load-file has been eradicated. - * iESS[SAS]: 'C-c C-r' and 'C-c C-b' once again work as intended and - documented. - * ESS[S]: M-x ess-fix-EQ-assign is a bit more agressive. - * ESS[S]: Imenu now also shows setAs(), etc. - * ESS[R]: R function pattern enhanced with underlying code such that - 'M-C-a' ('ess-beginning-of-function') etc now work for many more - cases, including S4 method definitions. - * iESS[R]: myOwnhelp(1) no longer wrongly triggers help(1). - * ESS[R]: Improved detection of bogus help buffers: valid help - buffers containing with the string "no documentation"(e.g. - contour) were being treated as bogus. - * ESS[R]: In R help buffers, if 'options("help.try.all.packages" = - TRUE)' then '?rlm' will list which packages rlm is defined in. - This help buffer is not bogus, but instead is now relabelled - "*help[R](rlm in packages)*". - * ESS[STA]: add "//" as comment starting character to syntax-table. - - Changes/New Features in 5.2.8: - * iESS: [Tab] completes *file* names "inside string" as in earlier - (<= 5.2.3) ESS versions. - - Changes/New Features in 5.2.7: - * If you use Custom to change the variable ess-toolbar-items, the new - toolbar is used in all subsequent ESS buffers. - * ESS[SAS]: new feature: if ess-sas-log-max >0 and your .log grows to - more than ess-sas-log-max bytes, just the first ess-sas-log-max - bytes are refreshed; this is helpful when your .sas program - generates lots of error messages and gets too big for emacs to - display - * ESS[R/S]: 'M-;' in R/S editing modes will now indent with either - one or two hashes depending on context. - * ESS[R]: David Whiting's Sweave extensions (to 'noweb') are now - available (from ess-swv.el loaded by default). - - Changes/New Features in 5.2.6: - * Removed non-ASCII characters in a few files. - * ESS[R]: now works better when UTF-8 locale is active; in - particular, you get correct directional quotes in R's startup - message for R-devel (unstable development version of R 2.1.0) when - using environment variables LANGUAGE=en@quot LC_ALL=en_US.UTF-8 - * ESS[SAS]: toggling of .log mode improved ('F10'); toggling of .lst - mode now also available ('C-F10'); killing all buffers associated - with .sas program no longer bound to 'C-F10' since its a bit - overzealous. - * S-Plus 7 for Windows is now recognized. - * ESS[S] (incl. R): in auto-fill mode, strings are not wrapped - anymore. - * ESS[S] (incl. R): font-lock now correctly differs between R and S, - e.g., for "_"; both now fontify warning(.) and S does terminate() - additionally. - * Support for 'bell' aka 'beep' aka 'ding' aka 'alarm' in all - inferior modes: When \a is output "to the the console" at the - beginning of a line, the bell is rung. - - Changes/New Features in 5.2.5: - * ESS[R]: 'C-c C-q' or 'Quit S' from the menu now should work (again - and less klunkily) and do not append '-exited' to the buffer name. - Further, the behavior of '(ess-cleanup)', called from ess-quit, now - depends on the new customizable variable - 'ess-S-quit-kill-buffers-p' which defaults to 'nil'. Consequently, - the question _"Delete all buffers associated with ..?"_ will not - be asked anymore by default. - * ESS[SAS] - ess-ebcdic-to-ascii-search-and-replace will now work - with the 'recode' application as well which is available on many - platforms - * ESS[S] (incl. R): Name completion for slots of S4 objects now - works! - - Changes/New Features in 5.2.4: - * The documentation now includes an overview of how to use the emacs - TAGS facility for S functions. (The distribution also used to - contain a directory 'etc/other/Tags' where a ~1990 version of - 'etags.c' was distributed; this is no longer relevant and so has - been deleted.) - * ESS[SAS] - When you are working with EBCDIC files on an ASCII - platform, .log NOTEs may display as gibberish since the EBCDIC - characters are not converted to ASCII prior to their display. So, - the function ess-ebcdic-to-ascii-search-and-replace is provided for - convenience and is bound to 'C-F11'. This function requires the - 'dd' command (only available on unix or unix-like platforms). - * ESS: Completion of object names is now always done dynamically - rather than allowing the option of using a pre-computed database - (by 'ess-create-object-name-db') since modern computers seem fast - enough for dynamic completion. (We expect few users, if any, have - been using the pre-computed database method.) - * ESS: object completion in iESS buffers running on Windows was very - slow (for GNU Emacs, but not XEmacs) and has now been fixed. - Further, it was more or less broken for all versions of S-plus 6.x, - and has been fixed to work everywhere but with the Windows' GUI of - S-plus. The list of objects now shows unique names also when an - object appears more than once in the search path. - * ESS[R]: Completion of object names now also includes those starting - with ".". - - Changes/New Features in 5.2.3: - * ESS: When new inferior ESS processes are created, by default they - will replace the current buffer (this restores behavior from pre - 5.2.0). If you wish new ESS processes to start in another window - of the current frame, set inferior-ess-same-window to nil. - * New variables inferior-Splus-args and inferior-R-args provide a way - to pass command line arguments to starting S and R processes. - - Changes/New Features in 5.2.2: - * bug-fixes for 5.2.1 (require 'executable), html docs, etc. - * ess-lisp-directory/../doc/info added to Info-directory-list if - ess-info not found by info - * ESS[R]: If you have other versions of R on your exec-path, such as - "R-1.8.1" with Unix or "rw1081" with Windows, ESS will find them - and create appropriate functions, such as 'M-x R-1.8.1' or 'M-x - rw1081', for calling them. By default only Unix programs beginning - "R-1" and "R-2" and Windows programs parallel to the version of R - in your exec-path will be found, but see ess-r-versions and - ess-rterm-versions for ways to find other versions of R. - * ESS[R]: Other versions of R, such as "R-1.8.1" on Unix and "rw1081" - on Windows, are added to the "ESS / Start Process / Other" menu. - * ESS[S]: If you have other versions of S-Plus on your Windows - computer, such as S-Plus 6.1 or S-Plus 4.5, ESS will find them and - create appropriate functions, such as 'M-x splus61', for calling - the console version (Sqpe) inside an emacs buffer. By default only - programs installed in the default location will be found, but see - ess-SHOME-versions for ways to find other versions of S-Plus. - * ESS[S]: Other versions of Sqpe on Windows, such as "splus61", are - added to the "ESS / Start Process / Other" menu. - * ESS[R]: (bug fix) ess-quit (bound to 'C-c C-q') should now quit the - inferior R process, when issued from either the inferior buffer, or - from a .R buffer. - - Changes/New Features in 5.2.1: - * ESS[S] (R and S-plus): now have toolbar support with icons to - evaluate code in the inferior process or to switch there. This - code is experimental and likely to change as XEmacs/Emacs issues - get resolved. The toolbar should be enabled if your Emacs displays - images, but can be disabled with the variable ess-use-toolbar. - Thanks to David Smith from Insightful for the S-plus logo. - * ESS[SAS]: ess-sas-graph-view ('F12') enhanced; you can specify - external file viewers for each graphics file type via the alist - ess-sas-graph-view-viewer-alist; also .jpg/.gif are now handled by - image-mode on XEmacs, if available, otherwise by graphics - primitives as before - - Changes/New Features in 5.2.0: - * ESS[BUGS]: new info documentation! now supports interactive - processing thanks to Aki Vehtari (mailto:Aki.Vehtari@hut.fi); new - architecture-independent unix support as well as support for BUGS - v. 0.5 - * ESS[SAS]: convert .log to .sas with ess-sas-transcript; info - documentation improved; Local Variable bug fixes; SAS/IML - statements/functions now highlighted; files edited remotely by - ange-ftp/EFS/tramp are recognized and pressing SUBMIT opens a - buffer on the remote host via the local variable - ess-sas-shell-buffer-remote-init which defaults to "ssh"; changed - the definition of the variable ess-sas-edit-keys-toggle to boolean - rather than 0/1; added the function ess-electric-run-semicolon - which automatically reverse indents lines containing only "run;"; - 'C-F1' creates MS RTF portrait from the current buffer; 'C-F2' - creates MS RTF landscape from the current buffer; 'C-F9' opens a - SAS DATASET with PROC INSIGHT rather than PROC FSVIEW; "inferior" - aliases for SAS batch: 'C-c C-r' for submit region, 'C-c C-b' for - submit buffer, 'C-c C-x' for goto .log; 'C-c C-y' for goto .lst - * ESS[S]: Pressing underscore ("_") once inserts " <- " (as before); - pressing underscore twice inserts a literal underscore. To stop - this smart behaviour, add "(ess-toggle-underscore nil)" to your - .emacs after ess-site has been loaded; - ess-dump-filename-template-proto (new name!) now can be customized - successfully (for S language dialects); Support for Imenu has been - improved; set ess-imenu-use-S to non-nil to get an "Imenu-S" item - on your menubar; ess-help: Now using nice underlines (instead of - 'nuke-* ^H_') - * ESS[R]: After (require 'essa-r), 'M-x ess-r-var' allows to load - numbers from any Emacs buffer into an existing *R* process; 'M-x - ess-rdired' gives a "directory editor" of R objects; fixed - ess-retr-lastvalue-command, i.e. .Last.value bug (thanks to David - Brahm) - * ESS: Support for creating new window frames has been added to ESS. - Inferior ESS processes can be created in dedicated frames by - setting inferior-ess-own-frame to t. ESS help buffers can also - open in new frames; see the documentation for ess-help-own-frame - for details. (Thanks to Kevin Rodgers for contributing code.) - - Changes/New Features in 5.1.24: - * The version number is now correct even inside ESS/Emacs - - Changes/New Features in 5.1.23: - * Minor more Makefile clean up. - - Changes/New Features in 5.1.22: - * Besides info documentation, PDF and HTML documentation are also - provided (instead of built using "make") and available on the web - as well; see ESS web page (https://ess.r-project.org/) and StatLib - (http://lib.stat.cmu.edu/general/ESS/doc) - * Now that info documentation is available, the README.* files are no - longer supported. However, they are still distributed for what - it's worth. - * ESS is now an XEmacs package! See XEmacs Installation HOWTO - (https://www.xemacs.org/Install/index.html) for details - (specifically, items 10-15). - * ESS[SAS]: more user-friendly enhancements for remote SAS batch jobs - with Kermit file transfers (LOG and OUTPUT function key features - now supported). Multiple shells now supported so you can run SAS - on different computers from different buffers by setting the - buffer-local variable ess-sas-shell-buffer to unique buffer names. - * Major re-vamping of Makefile/Makeconf. - - Changes/New Features in 5.1.21: - * ESS[SAS]: info documentation now available!, see ESS->Help for SAS; - 'F12' opens GSASFILE nearest point for viewing either within emacs, - when available, or via an external viewer; more syntax highlighting - keywords; more enhancements for remote SAS batch jobs with Kermit; - new framework for remote SAS interactive jobs, see ess-remote - * ESS[S]: info documentation now available!, see ESS->Help for the S - family - * Makefile: tag now independent of rel; info files made by - doc/Makefile and installed in new info sub-directory - - Changes/New Features in 5.1.20: - * New 'options()$STERM' in the S dialects (S, S-Plus, R). The S - program can determine the environment in which it is currently - running. ESS sets the option to 'iESS' or 'ddeESS' when it starts - an S language process. We recommend other specific values for S - language processes that ESS does not start. - * New 'ess-mouse-me' function, assigned to S-mouse-3 by default. - User may click on a word or region and then choose from the menu to - display the item, or a summary, or a plot, etc. This feature is - still under development. - * GNU Emacs 21.1 is now supported (fixed for S dialects, SAS & BUGS), - (some from Stephen Eglen). - * XEmacs 21.x is now supported (fixed w32-using-nt bug) - * XEmacs on Win (NT) is better supported. - * Workaround for bug in Sqpe+6 (S-PLUS 6 for Win). - * should now work even when imenu is not available (for old - XEmacsen). - * ESS[SAS]: XEmacs-Imenu fix; 'C-TAB' is globalized along with your - function-key definitions, if specified; you can specify your SAS - library definitions outside of autoexec.sas for ess-sas-data-view - with SAS code placed in the variable ess-sas-data-view-libname, - also the dataset name is defaulted to the nearest permanent dataset - to point; Speedbar support now works for permanent datasets, please - ignore first./last.; new font-locking is now the default with more - improvements for font-locking PROCs, macro statements, * ; and %* ; - comments; you can toggle sas-log-mode with 'F10' which will - font-lock your .log (if it isn't too big); submit remote .sas files - accessed with ange-ftp, EFS or Tramp (Kermit is experimental) by - setting ess-sas-submit-method to 'sh; ess-sas-submit-command and - ess-sas-submit-command-options are buffer-local so you can have - local file variable sections at the end of your .sas files to - request different executables or specify special options and the - local file variables are re-read at submit instead of only at file - open so that if you make a change it is picked up immediately; - * ESS[BUGS]: font-lock with 'in' fixed. - * for STATA: font-lock bug fixed. - * for Rd mode: 'C-c C-v' and 'switch-process' in menu. further, 'C-c - C-f' prefix (Rd-font) for inserting or surrounding a word by things - such as \code{.}, \code{\link{.}}, \emph{.} etc. - * new functions (ess-directory-function) and (ess-narrow-to-defun) - ess-directory <-> default-directory logic (Jeff Mincy). - * Re-organized Makefile and fixed a few bugs. - - Changes/New Features in 5.1.19: - * S+6 now supported (Tony Rossini (Unix) and Rich Heiberger - (Windows)) - * New BUGS support through ESS[BUGS] mode (Rodney Sparapani) - Templates assist you in writing .bug and .cmd code (.cmd and .log - are replaced by .bmd and .bog to avoid emacs extension collisions). - Substitution" parameters facilitate "automagic" generation of - data...in" and "init...in" filenames, "const N=" from your data - file and "monitor()/stats()" commands. Activated by pressing - 'F12'. - * Fixes for 'ess-smart-underscore' SAS breakage (Rich Heiberger) - * You can change between PC and Unix, local and global SAS - function-key definitions interactively (Rich Heiberger) - * 'C-Submit' a highlighted region to SAS batch (Rodney Sparapani) - * New and improved SAS syntax highlighting (Rodney Sparapani) To get - the new functionality, set ess-sas-run-make-regexp to nil. Also - available in .log files via 'F10'. - * Open a permanent SAS dataset for viewing via 'F9' (Rodney - Sparapani) You must have the library defined in autoexec.sas for it - to work. - * User-friendly defaults for 'sas-program', - 'ess-sas-batch-pre-command' and 'ess-sas-batch-post-command' as - well Customize support for these and other ESS[SAS] variables - (Rodney Sparapani) - * 'ess-sas-suffix-2' now defaults to .dat via 'F11' (Rodney - Sparapani) - * Emacs/XEmacs, Unix/Windows issues collectively handled in - ess-emcs.el - * defadvice solves problem of missing *ESS* (thanks to Jeff Mincy) - * Improved manual a bit by including things that were only in - 'README'. - - Changes/New Features in 5.1.18: - * New 'ess-smart-underscore' function, now assigned to "_" by - default. Inserts 'ess-S-assign' (customizable " <- "), unless - inside string and comments where plain "_" is used instead. (MM) - * Fixes for longstanding interactive SAS breakage (RMH) - - Changes/New Features in 5.1.17: - * Documentation for Windows Installation (Rich Heiberger) - * removal of ess-vars, finalization of customize support (in the - sense that there is no more use of ess-vars, but that we need to - fix ess-cust) (AJ Rossini) - * Many small (and large) fixes/contributions (MMaechler) - * addition of the "S-equal" variable and provide 'M-x - ess-add-MM-keys' a way to remap "_" to 'ess-S-assign', typically " - <- ", but customizable. (MMaechler) - - Changes/New Features in 5.1.16: - * BUG FIXES - * Better SAS support - - Changes/New Features in 5.1.15: - * BUG FIXES - - Changes/New Features in 5.1.14: - * Yet more fixes to SAS mode, (Rich Heiberger and Rodney Sparapani) - * Customize support (for most Emacsen which support it) (AJRossini) - * ARC and ViSta support out of the box, and fixes for XLispStat - (AJRossini) - - Changes/New Features in 5.1.13: - * Version numbering finally all depending on the ./VERSION file, - thanks to Martin Maechler. - * Yet more fixes to SAS mode, thanks to Rich Heiberger. - - Changes/New Features in 5.1.12: - * Splus 5.1 stabilized, thanks to Martin Maechler, Bill Venables, - Chuck Taylor, and others. - * More fixes to SAS mode, thanks to Rodney Sparapani and Rich - Heiberger. - - Changes/New Features in 5.1.11: - * More fixes to Stata mode, thanks to Brendan Halpin - (mailto:brendan@essex.ac.uk). - * fixed bugs in ESS-elsewhere, thanks to many testers - * README.SPLUS4WIN has DETAILED instructions for S-PLUS 2000, thanks - to David Brahm (mailto:brahm@alum.mit.edu). - * Fixes to SAS mode, thanks to Rodney Sparapani - - Changes/New Features in 5.1.10: - * More fixes to Stata mode - * primitive generic version of ESS-elsewhere - * Small fixes to SAS/Stata. - - Changes/New Features in 5.1.9: - * Stata mode works - * Literate Data Analysis using Noweb works - - Changes/New Features in 5.1.8: - * Bug fixes - * R documentation mode defaults changed - - Changes/New Features in 5.1.2: - * able to use inferior iESS mode to communicate directly with a - running S-Plus 4.x process using the Microsoft DDE protocol. We - use the familiar (from Unix ESS) 'C-c C-n' and related key - sequences to send lines from the S-mode file to the inferior S - process. We continue to edit S input files in ESS[S] mode and - transcripts of previous S sessions in ESS Transcript mode. All - three modes know the S language, syntax, and indentation patterns - and provide the syntactic highlighting that eases the programming - tasks. - - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20191014.1343/readme.info b/elpa/ess-20191014.1343/readme.info deleted file mode 100644 index 589dcea9..00000000 --- a/elpa/ess-20191014.1343/readme.info +++ /dev/null @@ -1,742 +0,0 @@ -This is readme.info, produced by makeinfo version 6.5 from readme.texi. - - -File: readme.info, Node: General Information - -1 General Information: README -***************************** - -This is the README file for the distribution of ESS version -18.10.3snapshot - - ESS is a GNU Emacs package for interactive statistical programming -and data analysis. Languages supported: the S family (S, S-PLUS and R), -SAS, BUGS/JAGS and Stata. ESS grew out of the desire for bug fixes and -extensions to S-mode and SAS-mode as well as a consistent union of their -features in one package. - - Installation instructions are provided in sections for both Unix and -Windows; see below. - - The current development team is led by Martin Maechler since August -2004. Former project leader A.J. (Tony) Rossini -() did the initial port to XEmacs and has been -the primary coder. Martin Maechler () and -Kurt Hornik () have assisted with the S -family and XLispStat. Stephen Eglen () has worked -mostly on R support. Richard M. Heiberger () has -assisted with S/S-PLUS development for Windows. Richard and Rodney A. -Sparapani () have done much of the work improving SAS -batch and interactive support. Rodney has also extended ESS to support -BUGS/JAGS and has an interest in improving Stata support. - - We are grateful to the previous developers of S-mode (Doug Bates, Ed -Kademan, Frank Ritter, David M. Smith), SAS-mode (Tom Cook) and -Stata-mode (Thomas Lumley). - -* Menu: - -* License:: -* Installation:: -* Starting up:: -* Current Features:: -* New Features:: -* Reporting Bugs:: -* Mailing Lists:: -* Authors:: - - -File: readme.info, Node: License, Next: Installation, Prev: General Information, Up: General Information - -1.1 License -=========== - -The source and documentation of ESS is free software. You can -redistribute it and/or modify it under the terms of the GNU General -Public License as published by the Free Software Foundation; either -version 2, or (at your option) any later version. - - ESS is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License in -the file COPYING in the same directory as this file for more details. - - -File: readme.info, Node: Installation, Next: Starting up, Prev: License, Up: General Information - -1.2 Installation -================ - -ESS supports GNU Emacs versions 25.1 and newer. - - ESS is most likely to work with current/recent versions of the -following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. - - To build the PDF documentation, you will need a version of TeX Live -or texinfo that includes texi2dvi. - - There are two main methods used for installing ESS. You may install -from a third-party repository or from source code. Once you install it, -you must also activate or load ESS in each Emacs session, though -installation from a third-party repository likely takes care of that for -you. See *note Activating and Loading ESS:: for more details. - -* Menu: - -* Installing from a third-party repository:: -* Installing from source:: -* Activating and Loading ESS:: -* Check Installation:: - - -File: readme.info, Node: Installing from a third-party repository, Next: Installing from source - -1.3 Installing from a third-party repository -============================================ - -ESS is packaged by many third party repositories. Many GNU/Linux -distributions package it, usually with the name "emacs-ess" or similar. - - ESS is also available through Milkypostman’s Emacs Lisp Package -Archive (MELPA), a popular repository for Emacs packages. Instructions -on how to do so are found on MELPA's website (https://melpa.org/). -MELPA also hosts MELPA-stable with stable ESS builds. You may choose -between MELPA with the latest and greatest features (and bugs) or -MELPA-stable, which may lag a bit behind but should be more stable. - - After installing, users should make sure ESS is activated or loaded -in each Emacs session. See *note Activating and Loading ESS::. -Depending on install method, this may be taken care of automatically. - - -File: readme.info, Node: Installing from source, Next: Activating and Loading ESS, Prev: Installing from a third-party repository - -1.4 Installing from source -========================== - -Stable versions of ESS are available at the ESS web page -(https://ess.r-project.org) as a .tgz file or .zip file. ESS releases -are GPG-signed, you should check the signature by downloading the -accompanying '.sig' file and doing: - - gpg --verify ess-18.10.tgz.sig - - Alternatively, you may download the git repository. ESS is currently -hosted on GitHub: . 'git clone -https://github.com/emacs-ess/ESS.git' will download it to a new -directory 'ESS' in the current working directory. - - We will refer to the location of the ESS source files as -'/path/to/ESS/' hereafter. - - After installing, users should make sure they activate or load ESS in -each Emacs session, see *note Activating and Loading ESS:: - - Optionally, compile elisp files, build the documentation, and the -autoloads: - cd /path/to/ESS/ - make - Without this step the documentation, reference card, and autoloads -will not be available. Uncompiled ESS will also run slower. - - Optionally, you may make ESS available to all users of a machine by -installing it site-wide. To do so, run 'make install'. You might need -administrative privileges: - - make install - - The files are installed into '/usr/share/emacs' directory. For this -step to run correctly on macOS, you will need to adjust the 'PREFIX' -path in 'Makeconf'. The necessary code and instructions are commented -in that file. - - -File: readme.info, Node: Activating and Loading ESS, Next: Check Installation, Prev: Installing from source - -1.5 Activating and Loading ESS -============================== - -After installing ESS, you must activate or load it each Emacs session. -ESS can be autoloaded, and if you used a third-party repository (such as -your Linux distribution or MELPA) to install, you can likely skip this -section and proceed directly to *note Check Installation:: - - Otherwise, you may need to add the path to ESS to 'load-path' with: - - (add-to-list 'load-path "/path/to/ESS/lisp") - - You then need to decide whether to take advantage of deferred loading -(which will result in a faster Emacs startup time) or require ESS when -Emacs is loaded. To autoload ESS when needed (note that if installed -from source, you must have run 'make'): - - (load "ess-autoloads") - - To require ESS on startup, you can either put - - (require 'ess-site) - - or - - (require 'ess-r-mode) - - In your configuration file, depending on whether you want all ESS -features or only R related features. - - -File: readme.info, Node: Check Installation, Prev: Activating and Loading ESS - -1.6 Check Installation -====================== - -Restart Emacs and check that ESS was loaded from a correct location with -'M-x ess-version'. - - -File: readme.info, Node: Starting up, Next: Current Features, Prev: Installation, Up: General Information - -1.7 Starting an ESS process -=========================== - -To start an S session on Unix or on Windows when you use the Cygwin bash -shell, simply type 'M-x S RET'. - - To start an S session on Windows when you use the MSDOS prompt shell, -simply type 'M-x S+6-msdos RET'. - - -File: readme.info, Node: Current Features, Next: New Features, Prev: Starting up, Up: General Information - -1.8 Current Features -==================== - - * Languages Supported: - * S family (R, S, and S+ AKA S-PLUS) - * SAS - * BUGS/JAGS - * Stata - * Julia - * Editing source code (S family, SAS, BUGS/JAGS, Stata, Julia) - * Syntactic indentation and highlighting of source code - * Partial evaluation of code - * Loading and error-checking of code - * Source code revision maintenance - * Batch execution (SAS, BUGS/JAGS) - * Use of imenu to provide links to appropriate functions - * Interacting with the process (S family, SAS, Stata, Julia) - * Command-line editing - * Searchable Command history - * Command-line completion of S family object names and file - names - * Quick access to object lists and search lists - * Transcript recording - * Interface to the help system - * Transcript manipulation (S family, Stata) - * Recording and saving transcript files - * Manipulating and editing saved transcripts - * Re-evaluating commands from transcript files - * Interaction with Help Pages and other Documentation (R) - * Fast Navigation - * Sending Examples to running ESS process. - * Fast Transfer to Further Help Pages - * Help File Editing (R) - * Syntactic indentation and highlighting of source code. - * Sending Examples to running ESS process. - * Previewing - - -File: readme.info, Node: New Features, Next: Reporting Bugs, Prev: Current Features, Up: General Information - -1.9 New Features -================ - -Changes and New Features in 19.04 (unreleased): - - * ESS[R]: There is a new menu entry for reloading the R process. It - is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same - process name and start arguments that were used to start the - process. - - * iESS: Process runners now return the inferior buffer. Note that - callers of inferior runners should not assume that the current - buffer has been set to the inferior buffer. Instead, use - 'with-current-buffer' with the return value of the inferior. - - * iESS[SAS]: The SAS keymap was only set in iESS buffers called - '*SAS*'. This is now fixed. - - * ESS[R]: Fixed longstanding indentation issues involving '::' and - ':::' operators. - - * Implement a more reliable check for the process busy state. - Background actions such as completion and directory synchronization - should not block the process and should not cause printing of the - extraneous output to the interpreter. - - * Activate 'goto-address-mode' for url and email highlighting in - inferior buffers. - - * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. - Users who liked the previous behavior (i.e. underscore inserting - "<-") should bind 'ess-insert-assign' to the underscore in their - Emacs initialization file. For example, '(define-key - ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key - inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it - in all ESS R buffers. - - * ESS major modes are now defined using 'define-derived-mode'. This - makes ESS major modes respect modern conventions such as having - -mode-hook and -mode-map. Users are encouraged - to place customizations under the appropriate mode. - - * New option ess-auto-width controls setting the width option on - window changes. Users can change it to 'frame, 'window, or an - integer. See the documentation for details. - 'ess-auto-width-visible' controls visibility. - - * ESS now respects 'display-buffer-alist'. Users can now use - 'display-buffer-alist' to manage how and where windows appear. See - *Note (ess)Controlling buffer display:: for more information and - examples. - - * 'ess-roxy-mode' can now be enabled in non-R buffers. This is - primarily intended to support roxygen documentation for cpp - buffers. Preview functionality is not supported outside R buffers. - - * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. - - * 'ess-style' now has effects when set as a file or directory local - variable. - - * 'ess-default-style' is now obsolete, use 'ess-style' instead. - - * Options for 'ess-gen-proc-buffer-name-function' have been renamed. - ess-gen-proc-buffer-name:projectile-or-simple was renamed to - ess-gen-proc-buffer-name:project-or-simple and - ess-gen-proc-buffer-name:projectile-or-directory was renamed to - ess-gen-proc-buffer-name:project-or-directory. As the name - suggests, these now rely on project.el (included with Emacs) rather - than projectile.el, which is a third-party package. - - * ESS[R]: devtools commands ask about saving modified buffers before - running. Users can disable the questioning with - 'ess-save-silently'. - - * ESS[R] help pages now provide links to other help topics. This is - similar with what you would see with, for example - 'options(help_type = ``html'')' but works with the plain-text - version as well. This only works with 'options(useFancyQuotes = - TRUE)' (the default). - - * 'ess-rdired' buffers now derive from tabulated-list-mode. They - should look better and be a bit faster overall. The size column - now displays object sizes in bytes. - - * 'ess-rdired' buffers now auto-update. The frequency is governed by - the new option 'ess-rdired-auto-update-interval'. - - * ESS[R]: 'electric-layout-mode' is now supported. This - automatically inserts a newline after an opening curly brace in R - buffers. To enable it, customize 'ess-r-mode-hook'. - - * ESS[R]: imenu now supports assignment with the equals sign. - - * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. - - * ESS removed support for many unused languages. This includes old - versions of S+, ARC, OMG, VST, and XLS. - - The following have been made obsolete or removed, see their -documentation for more detail: - - * Libraries for literate data analysis are obsolete and not loaded by - default. This includes 'ess-noweb', 'ess-swv', and related - functionality like 'Rnw-mode'. Users are encouraged to switch to - one of several other packages that deal with these modes. For - example, polymode , - , or markdown-mode with edit-indirect - . - - * Support for 'auto-complete' is obsolete. The 'auto-complete' - package is unmaintained and so ESS support is now obsolete. Users - are encouraged to switch to 'company-mode' instead. - - * User options for controlling display of buffers. This includes - 'ess-show-buffer-action', 'inferior-ess-same-window', - 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See - above about ESS respecting 'display-buffer-alist'. - - * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. - Use the Emacs-wide setting of 'tab-always-indent' instead. - - * 'inferior-ess-*-start-file' variables. All modes except Stata did - not respect customization of this variable. In order to load a - file on startup, you should put a function on - 'ess-*-post-run-hook'. - - Bug Fixes in 18.10.3: - * More 'Makefile' fixes, notably installing '*.el's. - - Bug Fixes in 18.10.2: - * ESS[R] Fix namespace evaluation in non-installed packages. - Evaluation is directed into GlobalEnv as originally intended. - * 'Makefile' fixes, notably for 'make install' and including full - docs in the tarballs. - - Bug Fixes in 18.10-1: - * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and - 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave - as the old versions of 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step'. - - Changes and New Features in 18.10: - - * This is the last release to support Emacs older than 25.1. Going - forward, only GNU Emacs 25.1 and newer will be supported. Soon - after this release, support for older Emacs versions will be - dropped from the git master branch. Note that MELPA uses the git - master branch to produce ESS snapshots, so if you are using Emacs < - 25.1 from MELPA and are unable to upgrade, you should switch to - MELPA-stable. - - * ESS now displays the language dialect in the mode-line. So, for - example, R buffers will now show ESS[R] rather than ESS[S]. - - * The ESS manual has been updated and revised. - - * The ESS initialization process has been further streamlined. If - you update the autoloads (which installation from 'package-install' - does), you should not need to '(require 'ess-site)' at all, as - autoloads should automatically load ESS when it is needed (e.g. - the first time an R buffer is opened). In order to defer loading - your ESS config, you may want to do something like - '(with-require-after-load "ess" )' in your Emacs - init file. Users of the popular 'use-package' Emacs package can - now do '(use-package ess :defer t)' to take advantage of this - behavior. *Note (ess)Activating and Loading ESS:: for more - information on this feature. - - * ESS now respects Emacs conventions for keybindings. This means - that The 'C-c [letter]' bindings have been removed. This affects - 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in - 'sas-mode-local-map'; 'C-c f', which was bound to - 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', - which was bound to 'ess-handy-commands' in 'Rd-mode-map', - 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' - - * Functions 'ess-eval-line-and-step' and - 'ess-eval-region-or-line-and-step' now behave consistently with - other evaluation function inside a package. - - * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets - the working directory to the root of the current package including - for example C or C++ files within '/src'). - - * ESS[R]: Long + + prompts in the inferior no longer offset output. - - * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This - strips the entire + + sequence. - - * ESS modes now inherit from 'prog-mode'. In the next release, ESS - modes will use 'define-derived-mode' so that each mode will have - (for example) its own hooks and keymaps. - - * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. - Users need to install the 'lintr' package to use it. Customizable - options include 'ess-use-flymake', 'ess-r-flymake-linters', and - 'ess-r-flymake-lintr-cache'. - - * ESS[R]: Gained support for xref in Emacs 25+. *Note (emacs)Xref:: - - * ESS[R]: The startup screen is cleaner. It also displays the - startup directory with an explicit 'setwd()'. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[R]: 'Makevars' files open with 'makefile-mode'. - - * New variable 'ess-write-to-dribble'. This allows users to disable - the dribble ('*ESS*') buffer if they wish. - - * All of the '*-program-name' variables have been renamed to - '*-program'. Users who previously customized e.g. - 'inferior-ess-R-program-name' will need to update their - customization to 'inferior-ess-R-program'. These variables are - treated as risky variables. - - * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It - provides similar functionality but for any keybinding, not just - '_'. For instance if you bind it to ';', repeated invocations - cycle through between assignment and inserting ';'. - - * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the - documentation for details. New user customization option - 'ess-assign-list' controls which assignment operators are cycled. - - * ESS[R] In remote sessions, the ESSR package is now fetched from - GitHub. - - * Commands that send the region to the inferior process now deal with - rectangular regions. See the documentation of 'ess-eval-region' - for details. This only works on Emacs 25.1 and newer. - - * ESS[R]: Improvements to interacting with iESS in non-R files. - Interaction with inferior process in non-R files within packages - (for instance C or C++ files) has been improved. This is a work in - progress. - - * ESS[R]: Changing the working directory is now always reflected in - the process buffer. - - * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in - JAGS mode. - - Many improvements to fontification: - - * Improved customization for faces. ESS now provides custom faces - for (nearly) all faces used and places face customization options - into their own group. Users can customize these options using 'M-x - customize-group RET ess-faces'. - - * Many new keywords were added to 'ess-R-keywords' and - 'ess-R-modifiers'. See the documentation for details. - - * ESS[R]: 'in' is now only fontified when inside a 'for' construct. - This avoids spurious fontification, especially in the output buffer - where 'in' is a common English word. - - * ESS: Font-lock keywords are now generated lazily. That means you - can now add or remove keywords from variables like 'ess-R-keywords' - in your Emacs configuration file after loading ESS (i.e. in the - ':config' section for 'use-package' users). - - * ESS[R]: Fontification of roxygen '@param' keywords now supports - comma-separated parameters. - - * ESS[R]: Certain keywords are only fontified if followed by a - parenthesis. Function-like keywords such as 'if ()' or 'stop()' - are no longer fontified as keyword if not followed by an opening - parenthesis. The same holds for search path modifiers like - 'library()' or 'require()'. - - * ESS[R]: Fixed fontification toggling. Especially certain syntactic - elements such as '%op%' operators and backquoted function - definitions. - - * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. - This command asks with completion for a font-lock group to toggle. - This functionality is equivalent to the font-lock menu. - - Notable bug fixes: - - * 'prettify-symbols-mode' no longer breaks indentation. This is - accomplished by having the pretty symbols occupy the same number of - characters as their non-pretty cousins. You may customize the new - variable 'ess-r-prettify-symbols' to control this behavior. - - * ESS: Inferior process buffers are now always displayed on startup. - Additionally, they don't hang Emacs on failures. - - Obsolete libraries, functions, and variables: - - * The 'ess-r-args.el' library has been obsoleted and will be removed - in the next release. Use 'eldoc-mode' instead, which is on by - default. - - * Functions and options dealing with the smart assign key are - obsolete. The following functions have been made obsolete and will - be removed in the next release of ESS: 'ess-smart-S-assign', - 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', - 'ess-disable-smart-S-assign'. - - The variable 'ess-smart-S-assign-key' is now deprecated and will be - removed in the next release. If you would like to continue using - '_' for inserting assign in future releases, please bind - 'ess-insert-assign' in 'ess-mode-map' the normal way. - - * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. - Use 'ess-s-versions' instead. You may pass arguments by starting - the inferior process with the universal argument. - - Changes and New Features in 17.11: - - * The ESS initialization process has been streamlined. You can now - load the R and Stata modes independently from the rest of ESS. Just - put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your - init file. This is for experienced Emacs users as this requires - setting up autoloads for '.R' files manually. We will keep - maintaining 'ess-site' for easy loading of all ESS features. - - * Reloading and quitting the process is now more robust. If no - process is attached, ESS now switches automatically to one - (prompting you for selection if there are several running). - Reloading and quitting will now work during a debug session or when - R is prompting for input (for instance after a crash). Finally, - the window configuration is saved and restored after reloading to - prevent the buffer of the new process from capturing the cursor. - - * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working - directory of the current process to the current package directory. - - * ESS[R] Lookup for references in inferior buffers has been improved. - New variable 'ess-r-package-source-roots' contains package - sub-directories which are searched recursively during the file - lookup point. Directories in 'ess-tracebug-search-path' are now - also searched recursively. - - * ESS[R] Namespaced evaluation is now automatically enabled only in - the 'R/' directory. This way ESS will not attempt to update - function definitions from a package if you are working from e.g. a - test file. - - Changes and New Features in 16.10: - - * ESS[R]: Syntax highlighting is now more consistent. Backquoted - names are not fontified as strings (since they really are - identifiers). Furthermore they are now correctly recognized when - they are function definitions or function calls. - * ESS[R]: Backquoted names and '%op%' operators are recognized as - sexp. This is useful for code navigation, e.g. with 'C-M-f' and - 'C-M-b'. - * ESS[R]: Integration of outline mode with roxygen examples fields. - You can use outline mode's code folding commands to fold the - examples field. This is especially nice to use with well - documented packages with long examples set. Set - 'ess-roxy-fold-examples' to non-nil to automatically fold the - examples field when you open a buffer. - * ESS[R]: New experimental feature: syntax highlighting in roxygen - examples fields. This is turned off by default. Set - 'ess-roxy-fontify-examples' to non-nil to try it out. - * ESS[R]: New package development command 'ess-r-devtools-ask' bound - to 'C-c C-w C-a'. It asks with completion for any devtools command - that takes 'pkg' as argument. - * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. - Currently only implemented for R. The R method runs - 'inferior-ess-r-reload-hook' on reloading. - * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers - as well. - - Bug fixes in 16.10: - * ESS[R]: Fix broken (un)flagging for debugging inside packages - * ESS[R]: Fixes (and improvements) in Package development - * ESS[R]: Completion no longer produces '...=' inside 'list( )'. - * ESS[R]: Better debugging and tracing in packages. - * ESS[R]: Better detection of symbols at point. - * ESS[R]: No more spurious warnings on deletion of temporary files. - * ESS[julia]: help and completion work (better) - * ESS[julia]: available via 'ess-remote' - - Changes and New Features in 16.04: - - * ESS[R]: 'developer' functionality has been refactored. The new - user interface consists of a single command - 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once - an evaluation environment has been set with, all subsequent ESS - evaluation will source the code into that environment. By default, - for file within R packages the evaluation environment is set to the - package environment. Set 'ess-r-package-auto-set-evaluation-env' - to 'nil' to disable this. - * ESS[R]: New 'ess-r-package-mode' This development mode provides - features to make package development easier. Currently, most of - the commands are based on the 'devtools' packages and are - accessible with 'C-c C-w' prefix. See the documentation of - 'ess-r-package-mode' function for all available commands. With - 'C-u' prefix each command asks for extra arguments to the - underlying devtools function. This mode is automatically enabled - in all files within R packages and is indicated with '[pkg:NAME]' - in the mode-line. - * ESS[R]: Help lookup has been improved. It is now possible to get - help for namespaced objects such as pkg::foobar. Furthermore, ESS - recognizes more reliably when you change 'options('html_type')'. - * ESS[R]: New specialized breakpoints for debugging magrittr pipes - * ESS: ESS now implements a simple message passing interface to - communicate between ESS and inferior process. - - Bug fixes in 16.04: - * ESS[R]: Roxygen blocks with backtics are now correctly filled - * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' - * ESS[R]: Error highlighting now understands 'testthat' type errors - * ESS[Julia]: Added getwd and setwd generic commands - - -File: readme.info, Node: Reporting Bugs, Next: Mailing Lists, Prev: New Features, Up: General Information - -1.10 Reporting Bugs -=================== - -Please send bug reports, suggestions etc. to , -or post them on our github issue tracker -(https://github.com/emacs-ess/ESS/issues) - - The easiest way to do this is within Emacs by typing - - 'M-x ess-submit-bug-report' - - This also gives the maintainers valuable information about your -installation which may help us to identify or even fix the bug. - - If Emacs reports an error, backtraces can help us debug the problem. -Type "M-x set-variable RET debug-on-error RET t RET". Then run the -command that causes the error and you should see a *Backtrace* buffer -containing debug information; send us that buffer. - - Note that comments, suggestions, words of praise and large cash -donations are also more than welcome. - - -File: readme.info, Node: Mailing Lists, Next: Authors, Prev: Reporting Bugs, Up: General Information - -1.11 Mailing Lists -================== - -There is a mailing list for discussions and announcements relating to -ESS. Join the list by sending an e-mail with "subscribe ess-help" (or -"help") in the body to ; contributions -to the list may be mailed to . Rest assured, -this is a fairly low-volume mailing list. - - The purposes of the mailing list include - - * helping users of ESS to get along with it. - * discussing aspects of using ESS. - * suggestions for improvements. - * announcements of new releases of ESS. - * posting small patches to ESS. - - -File: readme.info, Node: Authors, Prev: Mailing Lists, Up: General Information - -1.12 Authors -============ - - * A.J. Rossini (mailto:blindglobe@gmail.com) - * Richard M. Heiberger (mailto:rmh@temple.edu) - * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) - * Martin Maechler (mailto:maechler@stat.math.ethz.ch) - * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) - * Stephen Eglen (mailto:stephen@gnu.org) - * Sebastian P. Luque (mailto:spluque@gmail.com) - * Henning Redestig (mailto:henning.red@googlemail.com) - * Vitalie Spinu (mailto:spinuvit@gmail.com) - * Lionel Henry (mailto:lionel.hry@gmail.com) - * J. Alexander Branham (mailto:alex.branham@gmail.com) - - - -Tag Table: -Node: General Information73 -Node: License1711 -Node: Installation2381 -Node: Installing from a third-party repository3298 -Node: Installing from source4248 -Node: Activating and Loading ESS5843 -Node: Check Installation6920 -Node: Starting up7143 -Node: Current Features7526 -Node: New Features9076 -Node: Reporting Bugs28610 -Node: Mailing Lists29508 -Node: Authors30224 - -End Tag Table diff --git a/elpa/ess-20191014.1343/requires.info b/elpa/ess-20191014.1343/requires.info deleted file mode 100644 index 9bc3ab78..00000000 --- a/elpa/ess-20191014.1343/requires.info +++ /dev/null @@ -1,15 +0,0 @@ -This is requires.info, produced by makeinfo version 6.5 from -requires.texi. - -ESS supports GNU Emacs versions 25.1 and newer. - - ESS is most likely to work with current/recent versions of the -following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. - - To build the PDF documentation, you will need a version of TeX Live -or texinfo that includes texi2dvi. - - -Tag Table: - -End Tag Table diff --git a/elpa/ess-20230419.1527/dir b/elpa/ess-20230419.1527/dir new file mode 100644 index 00000000..02022aa6 --- /dev/null +++ b/elpa/ess-20230419.1527/dir @@ -0,0 +1,19 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, + BUGS/JAGS and Stata). diff --git a/elpa/ess-20230419.1527/ess-autoloads.el b/elpa/ess-20230419.1527/ess-autoloads.el new file mode 100644 index 00000000..82426df6 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-autoloads.el @@ -0,0 +1,538 @@ +;;; ess-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "ess" "ess.el" (0 0 0 0)) +;;; Generated autoloads from ess.el + +(autoload 'ess-version "ess" "\ +Return a string with ESS version information." t nil) + +(autoload 'ess-submit-bug-report "ess" "\ +Submit a bug report to the ESS maintainers." t nil) + +(register-definition-prefixes "ess" '("ess")) + +;;;*** + +;;;### (autoloads nil "ess-bugs-d" "ess-bugs-d.el" (0 0 0 0)) +;;; Generated autoloads from ess-bugs-d.el + +(autoload 'ess-bugs-mode "ess-bugs-d" "\ +Major mode for BUGS. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.[Bb][Uu][Gg]\\'" . ess-bugs-mode)) + +(add-to-list 'auto-mode-alist '("\\.[Bb][Oo][Gg]\\'" . ess-bugs-mode)) + +(add-to-list 'auto-mode-alist '("\\.[Bb][Mm][Dd]\\'" . ess-bugs-mode)) + +(register-definition-prefixes "ess-bugs-d" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-bugs-l" "ess-bugs-l.el" (0 0 0 0)) +;;; Generated autoloads from ess-bugs-l.el + +(register-definition-prefixes "ess-bugs-l" '("ess-bugs-")) + +;;;*** + +;;;### (autoloads nil "ess-custom" "ess-custom.el" (0 0 0 0)) +;;; Generated autoloads from ess-custom.el + +(defvar ess-lisp-directory (file-name-directory (or load-file-name buffer-file-name)) "\ +Directory containing ess-site.el(c) and other ESS Lisp files.") + +(custom-autoload 'ess-lisp-directory "ess-custom" t) + +(add-to-list 'load-path (directory-file-name ess-lisp-directory)) + +(add-to-list 'load-path (directory-file-name (expand-file-name "obsolete" ess-lisp-directory))) + +(put 'ess-indent-offset 'safe-local-variable #'numberp) + +(put 'ess-style 'safe-local-variable #'symbolp) + +(register-definition-prefixes "ess-custom" '("R-" "S+" "S-" "comint-highlight-prompt" "ess-" "inferior-")) + +;;;*** + +;;;### (autoloads nil "ess-gretl" "ess-gretl.el" (0 0 0 0)) +;;; Generated autoloads from ess-gretl.el + +(autoload 'ess-gretl-mode "ess-gretl" "\ +Major mode for editing gretl source. See `ess-mode' for more help. + +\(fn)" t nil) + +(autoload 'gretl "ess-gretl" "\ +Call `gretl', +Optional prefix (C-u) allows to set command line arguments, such as +--vsize. This should be OS agnostic. +If you have certain command line arguments that should always be passed +to gretl, put them in the variable `inferior-gretl-args'. + +\(fn &optional START-ARGS)" t nil) + +(register-definition-prefixes "ess-gretl" '("ess-gretl-" "gretl-" "inferior-gretl-args")) + +;;;*** + +;;;### (autoloads nil "ess-help" "ess-help.el" (0 0 0 0)) +;;; Generated autoloads from ess-help.el + +(register-definition-prefixes "ess-help" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-inf" "ess-inf.el" (0 0 0 0)) +;;; Generated autoloads from ess-inf.el + +(autoload 'ess-load-file "ess-inf" "\ +Load FILENAME into an inferior ESS process. +This handles Tramp when working on a remote. + +\(fn &optional FILENAME)" t nil) + +(register-definition-prefixes "ess-inf" '("ess-" "inferior-ess" "update-ess-process-name-list")) + +;;;*** + +;;;### (autoloads nil "ess-jags-d" "ess-jags-d.el" (0 0 0 0)) +;;; Generated autoloads from ess-jags-d.el + +(autoload 'ess-jags-mode "ess-jags-d" "\ +Major mode for JAGS. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.[Jj][Aa][Gg]\\'" . ess-jags-mode)) + +(register-definition-prefixes "ess-jags-d" '("ess-jags-")) + +;;;*** + +;;;### (autoloads nil "ess-julia" "ess-julia.el" (0 0 0 0)) +;;; Generated autoloads from ess-julia.el + +(autoload 'ess-julia-mode "ess-julia" "\ +Major mode for julia files. + +\(fn)" t nil) + +(autoload 'run-ess-julia "ess-julia" "\ +Start an inferior julia process. +Optional prefix START-ARGS (\\[universal-argument]) allows to set +command line arguments, such as --load=. This should be OS +agnostic. If you have certain command line arguments that should +always be passed to julia, put them in the variable +`inferior-julia-args'. + +\(fn &optional START-ARGS)" t nil) + +(defalias 'julia #'run-ess-julia) + +(register-definition-prefixes "ess-julia" '("ac-source-ess-julia-objects" "company-ess-julia-objects" "ess-" "inferior-")) + +;;;*** + +;;;### (autoloads nil "ess-mode" "ess-mode.el" (0 0 0 0)) +;;; Generated autoloads from ess-mode.el + +(autoload 'ess-mode "ess-mode" "\ +Major mode for editing ESS source. +Optional arg ALIST describes how to customize the editing mode. +Optional arg PROC-NAME is name of associated inferior process. + +\\{ess-mode-map} + +You can send text to the inferior ESS process from other buffers containing +ESS source. + `ess-eval-region' sends the current region to the ESS process. + `ess-eval-buffer' sends the current buffer to the ESS process. + `ess-eval-function' sends the current function to the ESS process. + `ess-eval-line' sends the current line to the ESS process. + `ess-switch-to-ESS' switches the current buffer to the ESS process buffer. + `ess-switch-to-end-of-ESS' switches the current buffer to the ESS process + buffer and puts point at the end of it. + + `ess-eval-region-and-go', `ess-eval-buffer-and-go', + `ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S + process buffer after sending their text. + + `ess-load-file' sources a file of commands to the ESS process. + +\\[ess-indent-command] indents for ESS code. +\\[backward-delete-char-untabify] converts tabs to spaces as it moves back. +Comments are indented in a similar way to Emacs-lisp mode: + `###' beginning of line + `##' the same level of indentation as the code + `#' the same column on the right, or to the right of such a + column if that is not possible.(default value 40). + \\[indent-for-comment] command automatically inserts such a + `#' in the right place, or aligns such a comment if it is + already inserted. +\\[ess-indent-exp] command indents each line of the syntactic unit following point. + +Variables controlling indentation style: + `ess-indent-offset' + Indentation of ESS statements within surrounding block. + The surrounding block's indentation is the indentation of the line on + which the open-brace appears. + `ess-offset-block' + Indentation of blocks opened with curly braces or anonymous parentheses. + `ess-offset-arguments' + Indentation of function arguments or bracket indices. + `ess-offset-arguments-newline' + Indentation of function arguments or bracket indices when the opening + delimiter is immediately followed by a newline. + `ess-offset-continued' + Indentation style for continued statements. + `ess-align-nested-calls' + Functions whose nested calls should be aligned. + `ess-align-arguments-in-calls' + Calls in which arguments should be aligned. + `ess-align-continuations-in-calls' + Whether ignore indentation after an operator in calls + `ess-align-blocks' + Blocks that should always be aligned vertically. + `ess-indent-from-lhs' + Whether function calls given as argument should be indented from the + parameter name. + `ess-indent-from-chain-start' + Whether to indent arguments from the first of several consecutive calls. + `ess-indent-with-fancy-comments' + Non-nil means distinguish between #, ##, and ### for indentation. + +Furthermore, \\[ess-set-style] command enables you to set up predefined ess-mode +indentation style. See `ess-style-alist' for predefined styles. + +\(fn)" t nil) + +(register-definition-prefixes "ess-mode" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-r-completion" "ess-r-completion.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from ess-r-completion.el + +(register-definition-prefixes "ess-r-completion" '("ac-source-R" "company-R-" "ess-")) + +;;;*** + +;;;### (autoloads nil "ess-r-flymake" "ess-r-flymake.el" (0 0 0 0)) +;;; Generated autoloads from ess-r-flymake.el + +(register-definition-prefixes "ess-r-flymake" '("ess-r-")) + +;;;*** + +;;;### (autoloads nil "ess-r-mode" "ess-r-mode.el" (0 0 0 0)) +;;; Generated autoloads from ess-r-mode.el + +(autoload 'run-ess-r "ess-r-mode" "\ +Call 'R', the 'GNU S' system from the R Foundation. +Optional prefix (\\[universal-argument]) allows to set command line arguments, such as +--vsize. This should be OS agnostic. +If you have certain command line arguments that should always be passed +to R, put them in the variable `inferior-R-args'. + +START-ARGS can be a string representing an argument, a list of +such strings, or any other non-nil value. In the latter case, you +will be prompted to enter arguments interactively. + +\(fn &optional START-ARGS)" t nil) + +(autoload 'R "ess-r-mode" "\ + + +\(fn &optional START-ARGS)" t nil) + +(autoload 'ess-r-mode "ess-r-mode" "\ +Major mode for editing R source. See `ess-mode' for more help. + +\(fn)" t nil) + +(defalias 'R-mode #'ess-r-mode) + +(defalias 'r-mode #'ess-r-mode) + +(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . ess-r-mode)) + +(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . ess-r-mode)) + +(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . ess-r-mode)) + +(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . ess-r-mode)) + +(add-to-list 'auto-mode-alist '("CITATION\\'" . ess-r-mode)) + +(autoload 'ess-r-transcript-mode "ess-r-mode" "\ +A Major mode for R transcript files. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.[Rr]out\\'" . ess-r-transcript-mode)) + +(add-to-list 'interpreter-mode-alist '("Rscript" . ess-r-mode)) + +(add-to-list 'interpreter-mode-alist '("r" . ess-r-mode)) + +(add-to-list 'auto-mode-alist '("/Makevars\\(\\.win\\)?\\'" . makefile-mode)) + +(add-to-list 'auto-mode-alist '("DESCRIPTION\\'" . conf-colon-mode)) + +(register-definition-prefixes "ess-r-mode" '("R-" "ess-" "inferior-ess-r-" "r-transcript-mode" "run-ess-r-newest")) + +;;;*** + +;;;### (autoloads nil "ess-r-package" "ess-r-package.el" (0 0 0 0)) +;;; Generated autoloads from ess-r-package.el + +(register-definition-prefixes "ess-r-package" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-r-syntax" "ess-r-syntax.el" (0 0 0 0)) +;;; Generated autoloads from ess-r-syntax.el + +(register-definition-prefixes "ess-r-syntax" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-r-xref" "ess-r-xref.el" (0 0 0 0)) +;;; Generated autoloads from ess-r-xref.el + +(register-definition-prefixes "ess-r-xref" '("ess-r-xref-")) + +;;;*** + +;;;### (autoloads nil "ess-rd" "ess-rd.el" (0 0 0 0)) +;;; Generated autoloads from ess-rd.el + +(autoload 'Rd-mode "ess-rd" "\ +Major mode for editing R documentation source files. + +Type \\[list-abbrevs] to display the built-in abbrevs for Rd +keywords.To automatically turn on the abbrev(iate) features, add +the following to your Emacs configuration file: + + (add-hook \\='Rd-mode-hook #\\='abbrev-mode) + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode)) + +(register-definition-prefixes "ess-rd" '("Rd-")) + +;;;*** + +;;;### (autoloads nil "ess-rdired" "ess-rdired.el" (0 0 0 0)) +;;; Generated autoloads from ess-rdired.el + +(autoload 'ess-rdired "ess-rdired" "\ +Show R objects from the global environment in a separate buffer. +You may interact with these objects, see `ess-rdired-mode' for +details." t nil) + +(register-definition-prefixes "ess-rdired" '("ess-rdired-")) + +;;;*** + +;;;### (autoloads nil "ess-roxy" "ess-roxy.el" (0 0 0 0)) +;;; Generated autoloads from ess-roxy.el + +(autoload 'ess-roxy-mode "ess-roxy" "\ +Minor mode for editing ROxygen documentation. + +This is a minor mode. If called interactively, toggle the +`Ess-Roxy mode' mode. If the prefix argument is positive, enable +the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `ess-roxy-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "ess-roxy" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-s-lang" "ess-s-lang.el" (0 0 0 0)) +;;; Generated autoloads from ess-s-lang.el + +(add-to-list 'auto-mode-alist '("\\.[Ss]t\\'" . S-transcript-mode)) + +(add-to-list 'auto-mode-alist '("\\.Sout\\'" . S-transcript-mode)) + +(register-definition-prefixes "ess-s-lang" '("S+common-cust-alist" "S-" "ess-" "inferior-S-language-start")) + +;;;*** + +;;;### (autoloads nil "ess-sas-a" "ess-sas-a.el" (0 0 0 0)) +;;; Generated autoloads from ess-sas-a.el + +(register-definition-prefixes "ess-sas-a" '("ess-" "sas-program")) + +;;;*** + +;;;### (autoloads nil "ess-sas-d" "ess-sas-d.el" (0 0 0 0)) +;;; Generated autoloads from ess-sas-d.el + +(autoload 'SAS-mode "ess-sas-d" "\ +Major mode for editing SAS source. See `ess-mode' for more help. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode)) + +(register-definition-prefixes "ess-sas-d" '("SAS" "ess-" "inferior-SAS-args")) + +;;;*** + +;;;### (autoloads nil "ess-sas-l" "ess-sas-l.el" (0 0 0 0)) +;;; Generated autoloads from ess-sas-l.el + +(register-definition-prefixes "ess-sas-l" '("SAS-" "backward-page-top-of-window" "beginning-of-sas-" "ess-" "fix-page-breaks" "forward-page-top-of-window" "indent-sas-statement" "next-sas-proc" "sas-" "set-sas-file-" "submit-sas" "switch-to-")) + +;;;*** + +;;;### (autoloads nil "ess-sp6-d" "ess-sp6-d.el" (0 0 0 0)) +;;; Generated autoloads from ess-sp6-d.el + +(autoload 'S+-mode "ess-sp6-d" "\ +Major mode for editing S+ source. See `ess-mode' for more help. + +\(fn &optional PROC-NAME)" t nil) + +(register-definition-prefixes "ess-sp6-d" '("S+" "ess-")) + +;;;*** + +;;;### (autoloads nil "ess-toolbar" "ess-toolbar.el" (0 0 0 0)) +;;; Generated autoloads from ess-toolbar.el + +(register-definition-prefixes "ess-toolbar" '("ess-")) + +;;;*** + +;;;### (autoloads nil "ess-tracebug" "ess-tracebug.el" (0 0 0 0)) +;;; Generated autoloads from ess-tracebug.el + +(register-definition-prefixes "ess-tracebug" '("ess-" "inferior-ess-" "org-")) + +;;;*** + +;;;### (autoloads nil "ess-trns" "ess-trns.el" (0 0 0 0)) +;;; Generated autoloads from ess-trns.el + +(autoload 'ess-transcript-mode "ess-trns" "\ +Major mode for transcript files. + +Type \\[ess-transcript-send-command] to send a command in the +transcript to the current inferior process. \\[ess-transcript-copy-command] +copies the command but does not execute it, allowing you to edit it in +the process buffer first. + +Type \\[ess-transcript-clean-region] to delete all outputs and prompts +in the region, leaving only the commands. + +\(fn)" t nil) + +(register-definition-prefixes "ess-trns" '("ess-transcript-")) + +;;;*** + +;;;### (autoloads nil "ess-utils" "ess-utils.el" (0 0 0 0)) +;;; Generated autoloads from ess-utils.el + +(defvar ess-elisp-trace-mode nil "\ +Non-nil if Ess-Elisp-Trace mode is enabled. +See the `ess-elisp-trace-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `ess-elisp-trace-mode'.") + +(custom-autoload 'ess-elisp-trace-mode "ess-utils" nil) + +(autoload 'ess-elisp-trace-mode "ess-utils" "\ +Toggle tracing of ess-prefixed functions. +Tracing is useful for debugging background ESS behaviour. When +enabled, all functions prefixed in `ess-' and `inferior-ess' are +instrumented with `trace-function'. Tracing is turned off by +calling `untrace-function' on these functions. + +This is a minor mode. If called interactively, toggle the +`Ess-Elisp-Trace mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='ess-elisp-trace-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "ess-utils" '("ess-" "with-ess-process-buffer")) + +;;;*** + +;;;### (autoloads nil "essd-els" "essd-els.el" (0 0 0 0)) +;;; Generated autoloads from essd-els.el + +(autoload 'ess-remote "essd-els" "\ +Execute this command from within a buffer running a process. +It runs `ess-add-ess-process' to add the PROC-NAME to +`ess-process-name-alist' and to make it the +`ess-current-process-name'. It then prompts the user for an ESS +language and sets the editing characteristics appropriately. + +To use this command, first start a process on a remote computer by +manual use of telnet, rlogin, ssh, or some other protocol. Start the +relevant program (\"S\" or \"R\" or \"sas -stdio\") in that buffer. Once +you are talking to S or R or SAS, then do \\[ess-remote] to make +the current buffer an inferior-ess buffer with the right behavior for +the language you are currently working with. With S and R, use C-c +C-n to send lines over. With SAS, use C-c i +`ess-eval-line-and-step-invisibly' to send lines over invisibly. + +DIALECT is the desired ess-dialect. If nil, ask for dialect + +\(fn &optional PROC-NAME DIALECT)" t nil) + +(register-definition-prefixes "essd-els" '("S+elsewhere" "ess-" "inferior-ess-remote-pager")) + +;;;*** + +;;;### (autoloads nil nil ("ess-pkg.el" "ess-site.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; ess-autoloads.el ends here diff --git a/elpa/ess-20230419.1527/ess-bugs-d.el b/elpa/ess-20230419.1527/ess-bugs-d.el new file mode 100644 index 00000000..44605856 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-bugs-d.el @@ -0,0 +1,298 @@ +;;; ess-bugs-d.el --- ESS[BUGS] dialect -*- lexical-binding: t; -*- + +;; Copyright (C) 2008-2022 Free Software Foundation, Inc. + +;; Author: Rodney Sparapani +;; Maintainer: ESS-help + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Code: + +(require 'ess-bugs-l) +(require 'ess-utils) +(require 'ess-inf) +(require 'ess-mode) + +(defvar ess-bugs-command "OpenBUGS" "Default BUGS program in PATH.") +(make-local-variable 'ess-bugs-command) + +(defvar ess-bugs-monitor '("") "Default list of variables to monitor.") +(make-local-variable 'ess-bugs-monitor) + +(defvar ess-bugs-thin 1 "Default thinning parameter.") +(make-local-variable 'ess-bugs-thin) + +(defvar ess-bugs-chains 1 "Default number of chains.") +(make-local-variable 'ess-bugs-chains) + +(defvar ess-bugs-burnin 10000 "Default burn-in.") +(make-local-variable 'ess-bugs-burnin) + +(defvar ess-bugs-update 10000 "Default number of updates after burnin.") +(make-local-variable 'ess-bugs-update) + +(defvar ess-bugs-system nil "Default whether BUGS recognizes the system command.") + +(defvar ess-bugs-font-lock-keywords + (list + ;; .bug files + (cons "#.*\n" font-lock-comment-face) + + (cons "^[ \t]*\\(model\\|var\\)\\>" + font-lock-keyword-face) + + (cons (concat "\\ " ess-bugs-file-root ".bog 2>&1 " + ;; ess-bugs-batch-post-command "' > " ess-bugs-file-root ".bsh") + ;; (comint-send-input) + + ;; (insert "at -f " ess-bugs-file-root ".bsh now") + + ;; (comint-send-input) + + (insert "echo '" + ess-bugs-batch-pre-command " " bugs-command " < " + ess-bugs-file-root ".bmd > " ess-bugs-file-root ".bog 2>&1 " + ess-bugs-batch-post-command "' | at now") + + (comint-send-input) + )) + +(defun ess-bugs-na-bug () + "ESS[BUGS]: Perform Next-Action for .bug" + + (if (equal 0 (buffer-size)) (ess-bugs-switch-to-suffix ".bug") + ;else + (ess-save-and-set-local-variables) + (ess-bugs-switch-to-suffix ".bmd" + ess-bugs-chains ess-bugs-monitor ess-bugs-thin ess-bugs-burnin ess-bugs-update)) + ) + +;;;###autoload +(define-derived-mode ess-bugs-mode ess-mode "ESS[BUGS]" + "Major mode for BUGS." + (setq-local comment-start "#") + (setq font-lock-defaults '(ess-bugs-font-lock-keywords nil t)) + (setq ess-language "S") ; mimic S for ess-smart-underscore + (unless (when (fboundp 'w32-shell-dos-semantics) + (w32-shell-dos-semantics)) + (add-hook 'comint-output-filter-functions #'ess-bugs-exit-notify-sh))) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Bb][Uu][Gg]\\'" . ess-bugs-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Bb][Oo][Gg]\\'" . ess-bugs-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Bb][Mm][Dd]\\'" . ess-bugs-mode)) + +(defun ess-sci-to-dec () + "For BUGS/S family: Express +/-0.000E+/-0 or +/-0.0e+/-00 as a decimal." + (interactive) + (setq buffer-read-only nil) + (save-excursion (goto-char 0) + (save-match-data (let ((ess-temp-replacement-string nil) + (ess-temp-replacement-9 0) + (ess-temp-replacement-diff 0)) + (while (search-forward-regexp "-?[0-9][.][0-9][0-9]?[0-9]?[Ee][+-][0-9][0-9]?" nil t) + (setq ess-temp-replacement-string + (int-to-string (string-to-number (match-string 0)))) + (setq ess-temp-replacement-diff (- (match-end 0) (match-beginning 0))) + (save-match-data + (setq ess-temp-replacement-9 + (string-match "99999999999$" ess-temp-replacement-string)) + + (if (not ess-temp-replacement-9) + (setq ess-temp-replacement-9 + (string-match "000000000001$" ess-temp-replacement-string)))) + + (if ess-temp-replacement-9 + (setq ess-temp-replacement-string + (substring ess-temp-replacement-string 0 ess-temp-replacement-9))) + + (setq ess-temp-replacement-diff + (- ess-temp-replacement-diff (string-width ess-temp-replacement-string))) + + (while (> ess-temp-replacement-diff 0) + (setq ess-temp-replacement-string (concat ess-temp-replacement-string " ")) + (setq ess-temp-replacement-diff (- ess-temp-replacement-diff 1))) + + (replace-match ess-temp-replacement-string)))))) + +(provide 'ess-bugs-d) + +;;; ess-bugs-d.el ends here diff --git a/elpa/ess-20230419.1527/ess-bugs-l.el b/elpa/ess-20230419.1527/ess-bugs-l.el new file mode 100644 index 00000000..5cb707f3 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-bugs-l.el @@ -0,0 +1,290 @@ +;;; ess-bugs-l.el --- ESS[BUGS] languages -*- lexical-binding: t; -*- + +;; Copyright (C) 2006-2020 Free Software Foundation, Inc. + +;; Author: Rodney Sparapani +;; Maintainer: ESS-help + +;; This file is part of GNU Emacs + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Code: + +(require 'shell) +(require 'ess-utils) +(defvar ess-bugs-command) +(defvar ess-bugs-chains) +(defvar ess-jags-command) +(defvar ess-jags-chains) +(defvar ess-bugs-default-bins) + +(declare-function ess-bugs-na-bug "ess-bugs-d") +(declare-function ess-jags-na-bug "ess-jags-d") +(declare-function ess-bugs-na-bmd "ess-bugs-d") +(declare-function ess-jags-na-jmd "ess-jags-d") + +(defgroup ess-bugs nil + "ESS: BUGS." + :group 'ess + :prefix "ess-") + +(defcustom ess-bugs-batch-method + (if (and ess-microsoft-p + (fboundp 'w32-shell-dos-semantics) + (w32-shell-dos-semantics)) + 'dos + 'sh) + "Method used by `ess-bugs-batch'. +The default is based on the value of the Emacs variable `system-type' +and, on Windows machines, the function `w32-shell-dos-semantics'. +\\='sh if *shell* runs a Bourne-like or a C-like Unix shell +\\='dos if *shell* runs a DOS-like Windows shell + +Unix users will get \\='sh by default. + +Windows users running a DOS-like *shell* will get \\='dos by default, +while those running a Unix-like *shell* will get \\='sh by default. + +Users whose default is not \\='sh, but are accessing a remote machine with +`telnet' or `ssh', should have the following in their init file: + (setq-default ess-bugs-batch-method \\='sh)" + :group 'ess-bugs + :type '(choice (const sh :tag "Bourne/C-like Unix Shell") + (const dos :tag "DOS-like Windows shell"))) + +(defcustom ess-bugs-batch-post-command + (if (equal ess-bugs-batch-method 'sh) "&" " ") + "ESS[BUGS]: Modifiers at the end of the batch BUGS command line." + :group 'ess-bugs + :type 'string + ) + +(defcustom ess-bugs-batch-pre-command + (if (equal ess-bugs-batch-method 'sh) "nohup nice time" + (if ess-microsoft-p "start")) + "ESS[BUGS]: Modifiers at the beginning of the batch BUGS command line." + :group 'ess-bugs + :type 'string + ) + + +(defcustom ess-bugs-default-burn-in "500" + "ESS[BUGS]: Burn-in iterations to discard." + :group 'ess-bugs + :type 'string + ) + +(defcustom ess-bugs-default-update "1000" + "ESS[BUGS]: Iterations to store." + :group 'ess-bugs + :type 'string + ) + +(defvar ess-bugs-batch-command ";" + "ESS[BUGS]: The name of the command to run BUGS in batch mode." + ) + +(defvar ess-bugs-file "." + "ESS[BUGS]: BUGS file with PATH.") + +(defvar ess-bugs-file-root "." + "ESS[BUGS]: Root of BUGS file.") + +(defvar ess-bugs-file-suffix "." + "ESS[BUGS]: Suffix of BUGS file.") + +(defvar ess-bugs-file-dir "." + "ESS[BUGS]: Directory of BUGS file.") + +(defvar ess-bugs-file-data "..." + "ESS[BUGS]: BUGS data file.") + +(defcustom ess-bugs-inits-suffix ".in" + "ESS[BUGS]: BUGS init file suffix." + :group 'ess-bugs + :type 'string + ) + +(defcustom ess-bugs-data-suffix ".dat" + "ESS[BUGS]: BUGS data file suffix." + :group 'ess-bugs + :type 'string + ) + +(defcustom ess-bugs-mode-hook nil + "ESS[BUGS]: List of functions to call upon entering mode." + :group 'ess-bugs + :type 'hook) + +(defvar ess-bugs-monitor-vars " " + "ESS[BUGS]: List of BUGS variables to be written out to a file.") + +(defvar ess-bugs-stats-vars " " + "ESS[BUGS]: List of BUGS variables to be summarized with statistics.") + +(defvar ess-bugs-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (quote [f2]) #'ess-revert-wisely) + (define-key map "\C-c\C-c" #'ess-bugs-next-action) + (define-key map "=" #'ess-bugs-hot-arrow) +;; (define-key map "_" #'ess-bugs-hot-arrow) + map) + "ESS[BUGS]: Keymap for mode.") + +(defvar ess-bugs-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?\\ "." table) + (modify-syntax-entry ?# "<" table) + (modify-syntax-entry ?\n ">" table) + (modify-syntax-entry ?\( "()" table) + (modify-syntax-entry ?\) ")(" table) + (modify-syntax-entry ?. "w" table) + table) + "ESS[BUGS]: Syntax table for mode.") + +(defun ess-bugs-file () + "ESS[BUGS]: Set internal variables dealing with BUGS files. +Set `ess-bugs-file', `ess-bugs-file-root', `ess-bugs-file-suffix' +and `ess-bugs-file-dir'." + (let ((ess-bugs-temp-string (buffer-name))) + (setq ess-bugs-file (expand-file-name ess-bugs-temp-string)) + (setq ess-bugs-file-dir + (convert-standard-filename (file-name-directory ess-bugs-file))) + (setq ess-bugs-file-root + (file-name-nondirectory (file-name-sans-extension ess-bugs-file))) + + (if (fboundp 'file-name-extension) + (setq ess-bugs-file-suffix (file-name-extension ess-bugs-temp-string)) + ;;else + (setq ess-bugs-file-suffix (car (last (split-string ess-bugs-temp-string "[.]"))))) + + (setq ess-bugs-file-suffix + (downcase (car (split-string (concat "." ess-bugs-file-suffix) "[<]")))) + + (setq ess-bugs-file (concat ess-bugs-file-dir ess-bugs-file-root ess-bugs-file-suffix)) + ) + ) + +(defun ess-bugs-exit-notify-sh (string) + "ESS[BUGS]: Detect completion or failure of submitted job and notify the user." + (let* ((exit-done "\\[[0-9]+\\] *\\+* *\\(Exit\\|Done\\)[^\r\n]*") + (beg (string-match exit-done string))) + (if beg (message "%s" (substring string beg (match-end 0)))))) + +(defun ess-bugs-hot-arrow () + "ESS[BUGS]: Substitute <- for = key press" + (interactive) + (insert " <- ")) + +(defun ess-bugs-next-action () + "ESS[BUGS/JAGS]: Perform the appropriate next action." + (interactive) + (ess-bugs-file) + + (cond ((equal ".bug" ess-bugs-file-suffix) (ess-bugs-na-bug)) + ((equal ".jag" ess-bugs-file-suffix) (ess-jags-na-bug)) + ((equal ".bmd" ess-bugs-file-suffix) + (ess-save-and-set-local-variables) + (ess-bugs-na-bmd ess-bugs-command ess-bugs-chains)) + ((equal ".jmd" ess-bugs-file-suffix) + (ess-save-and-set-local-variables) + (ess-jags-na-jmd ess-jags-command ess-jags-chains))) + ) + +(defun ess-bugs-sci-to-round-4-dp () + "ESS[BUGS]: round output from +/-0.000E+/-0 to 4 decimal places." + (interactive) + (setq buffer-read-only nil) + (save-excursion (goto-char 0) + (save-match-data (let ((ess-bugs-replacement-string nil) + (ess-bugs-replacement-9 0) + (ess-bugs-replacement-diff 0)) + (while (search-forward-regexp "-?[0-9][.][0-9][0-9][0-9]E[+-][0-9]" nil t) + (setq ess-bugs-replacement-string + (int-to-string (string-to-number (match-string 0)))) + (setq ess-bugs-replacement-diff (- (match-end 0) (match-beginning 0))) + (save-match-data + (setq ess-bugs-replacement-9 + (string-match "99999999999$" ess-bugs-replacement-string)) + + (if (not ess-bugs-replacement-9) + (setq ess-bugs-replacement-9 + (string-match "000000000001$" ess-bugs-replacement-string)))) + + (if ess-bugs-replacement-9 + (setq ess-bugs-replacement-string + (substring ess-bugs-replacement-string 0 ess-bugs-replacement-9))) + + (setq ess-bugs-replacement-diff + (- ess-bugs-replacement-diff (string-width ess-bugs-replacement-string))) + + (while (> ess-bugs-replacement-diff 0) + (setq ess-bugs-replacement-string (concat ess-bugs-replacement-string " ")) + (setq ess-bugs-replacement-diff (- ess-bugs-replacement-diff 1))) + + (replace-match ess-bugs-replacement-string)))))) + +;;; ESS[BUGS-Shell] for running BUGS interactively +(defgroup ess-bugs-shell nil + "ESS: BUGS-Shell." + :group 'ess-bugs + :prefix "ess-") + +(defcustom ess-bugs-shell-buffer-name "BUGS" + "ESS[BUGS-Shell]: The name of the BUGS-Shell buffer." + :group 'ess-bugs-shell + :type 'string) + +(defcustom ess-bugs-shell-command "OpenBUGS" + "ESS[BUGS-Shell]: The name of the command to run BUGS interactively. + +Set to the name of the batch BUGS script that comes with ESS or +to the name of BUGS command. Make sure it is in your PATH or +add path to the command name." + :group 'ess-bugs-shell + :type 'string) + +(defcustom ess-bugs-shell-default-output-file-root "bugs" + "ESS[BUGS-Shell]: Default value for the root of output files." + :group 'ess-bugs-shell + :type 'string) + +(defcustom ess-bugs-shell-mode-hook nil + "ESS[BUGS-Shell]: List of functions to call upon entering mode." + :group 'ess-bugs-shell + :type 'hook) + +(defun ess-bugs-shell () + "Create a buffer with BUGS running as a subprocess." + (interactive) + (pop-to-buffer-same-window (concat "*" ess-bugs-shell-buffer-name "*")) + (make-comint ess-bugs-shell-buffer-name ess-bugs-shell-command nil + ess-bugs-default-bins ess-bugs-shell-default-output-file-root) + (comint-mode) + (setq shell-dirtrackp t + major-mode 'bugs-shell-mode + mode-name "ESS[BUGS-Shell]" + comint-prompt-regexp "^Bugs> *") + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults '(ess-bugs-font-lock-keywords nil t)) + (run-mode-hooks 'ess-bugs-shell-mode-hook) + ) + +(provide 'ess-bugs-l) + +;;; ess-bugs-l.el ends here diff --git a/elpa/ess-20230419.1527/ess-custom.el b/elpa/ess-20230419.1527/ess-custom.el new file mode 100644 index 00000000..f631e04d --- /dev/null +++ b/elpa/ess-20230419.1527/ess-custom.el @@ -0,0 +1,2500 @@ +;;; ess-custom.el --- Customize variables for ESS -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2020 Free Software Foundation, Inc. + +;; Author: Rodney Sparapani +;; Maintainer: ESS-help +;; Keywords: languages + +;; This file is part of GNU Emacs + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; A copy of the GNU General Public License is available at +;; https://www.r-project.org/Licenses/ + + + +;; This file is part of ESS + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; A copy of the GNU General Public License is available at +;; https://www.r-project.org/Licenses/ + + +;;; Commentary: +;; This file holds defcustoms for ESS. It is required by ess-utils.el, +;; which in turn is required by almost every other ESS file. + +;;; Code: +(require 'comint) + +;; FIXME: When Emacs is started from Cygwin shell in Windows, +;; we have (equal window-system 'x) -and should use "--ess" in *d-r.el +(defvar ess-microsoft-p (memq system-type '(ms-dos windows-nt)) + "Value is t if the OS is one of Microsoft's, nil otherwise.") + +;; Customization Groups + +(defgroup ess nil + "ESS: Emacs Speaks Statistics." + :group 'languages + :link '(info-link "(ESS)") + :link '(url-link "https://ess.r-project.org/")) + +(defgroup ess-edit nil + "ESS: editing behavior, including comments/indentation." + :group 'ess + :prefix "ess-") + +(defgroup ess-proc nil + "ESS: process control." + :group 'ess + :prefix "ess-") + +(defgroup ess-command nil + "ESS: Commands for various things." + :group 'ess + :prefix "ess-") + +(defgroup ess-help nil + "ESS: help functions." + :group 'ess + :prefix "ess-") + +(defgroup ess-hooks nil + "ESS: hooks for customization." + :group 'ess + :prefix "ess-") + +(defgroup ess-S nil + "ESS: S Languages." + :group 'ess + :prefix "ess-") + +(defgroup ess-SPLUS nil + "ESS: S-PLUS Dialect of S." + :group 'ess-S + :prefix "ess-") + +(defgroup ess-R nil + "ESS: R Dialect of S." + :group 'ess-S + :prefix "ess-") + +(defgroup ess-Julia nil + "ESS: Julia." + :group 'ess + :prefix "julia-") + +(defgroup ess-sas nil + "ESS: SAS." + :group 'ess + :prefix "ess-") + +(defgroup ess-roxy nil + "Mode for editing in-code Roxygen documentation." + :group 'ess + :group 'convenience + :group 'ess-extras + :prefix "ess-" + :group 'tools) + +(defgroup ess-extras nil + "Extra utilities for ESS." + :group 'ess + :prefix "ess-") + +(defgroup ess-faces nil + "Faces and face options for ESS modes." + :group 'ess + :group 'faces + :prefix "ess-") + + + ; User changeable variables + +;;*;; Options and Initialization + +;;;###autoload +(defcustom ess-lisp-directory + (file-name-directory + (or load-file-name + buffer-file-name)) + "Directory containing ess-site.el(c) and other ESS Lisp files." + :group 'ess + :type 'directory + :package-version '(ess . "19.04")) + +(defcustom ess-etc-directory + ;; Try to detect the `etc' folder only if not already set up by distribution + (let (dir) + (dolist (d '("./etc/" "../../etc/ess/" "../etc/" "../etc/ess/")) + (setq d (expand-file-name d ess-lisp-directory)) + (when (file-directory-p d) + (setq dir d))) + dir) + "Location of the ESS etc/ directory. +The ESS etc directory stores various auxiliary files that are useful +for ESS, such as icons." + :group 'ess + :type 'directory + :package-version '(ess . "19.04")) + +;; Depending on how ESS is loaded the `load-path' might not contain +;; the `lisp' directory. For this reason we need to add it before we +;; start requiring ESS files +;;;###autoload +(add-to-list 'load-path (directory-file-name ess-lisp-directory)) +;; Add ess-lisp-directory/obsolete to load-path; files here will +;; automatically warn that they are obsolete when loaded. +;;;###autoload +(add-to-list 'load-path (directory-file-name (expand-file-name "obsolete" ess-lisp-directory))) + +(unless (file-directory-p ess-etc-directory) + (display-warning 'ess (format "Could not find directory `ess-etc-directory': %s" + ess-etc-directory) :error)) + +;; Menus and pulldowns. + +(defcustom ess-imenu-use-p (fboundp 'imenu) + "Non-nil means use imenu facility. +This value can be overridden by mode-specific variables, such +as `ess-imenu-use-S'." + :group 'ess + :type 'boolean) + +(defcustom ess-imenu-use-S ess-imenu-use-p + "Non-nil means include an Imenu menu item in S buffers." + :group 'ess + :type 'boolean) + +(defcustom ess-auto-width-visible nil + "When non-nil, echo width setting in the inferior buffer. +See `ess-auto-width'. Be warned that ESS can set the width a +lot." + :group 'ess + :type 'boolean + :package-version '(ess . "19.04")) + +(defcustom ess-auto-width nil + "When non-nil, set the width option when the window configuration changes. +When \\='frame, set the width to the frame width. When \\='window, set +the width to the window width. If an integer, set the width to +that integer. If it's a negative integer, set the width to the +window's width minus that number. Anything else is treated as +\\='window." + :group 'ess + :type '(choice (const :tag "Do nothing" :value nil) + (const :tag "Frame width" :value frame) + (const :tag "Window width" :value window) + (integer :tag "Integer value")) + :package-version '(ess . "19.04")) + +(defcustom ess-handy-commands '(("change-directory" . ess-change-directory) + ("install.packages" . ess-install-library) + ("library" . ess-library) + ("objects[ls]" . ess-execute-objects) + ("help-apropos" . ess-display-help-apropos) + ("help-index" . ess-display-package-index) + ("help-object" . ess-display-help-on-object) + ("search" . ess-execute-search) + ("set-width" . ess-execute-screen-options) + ("setRepos" . ess-setRepositories) + ("sos" . ess-sos) + ("vignettes" . ess-display-vignettes) + ) + "An alist of custom ESS commands. +These are available for call by function `ess-handy-commands' and +`ess-smart-comma' function." + :group 'ess + :type 'alist) + +(defvar-local ess--local-handy-commands nil + "Store handy commands locally.") + +(defcustom ess-describe-at-point-method nil + "Whether `ess-describe-object-at-point' should use a tooltip. +If nil display in an electric buffer. If \\='tooltip display in +a tooltip. + +See also `tooltip-hide-delay' and variable `tooltip-delay'." + :group 'ess-utils + :type '(choice (const :tag "buffer" :value nil ) (const tooltip))) + +(defvaralias + 'ess-R-describe-object-at-point-commands + 'ess-r-describe-object-at-point-commands) +(defcustom ess-r-describe-object-at-point-commands + '(("str(%s)") + (".ess_htsummary(%s, hlength = 20, tlength = 20)") + ("summary(%s, maxsum = 20)")) + "A list of commands cycled by `ess-describe-object-at-point'. +%s is substituted with the name at point. + +The value of each element is nil and is not used in current +implementation." + :group 'ess-R + :type 'alist) + +(defcustom ess-S-describe-object-at-point-commands + ess-R-describe-object-at-point-commands + "An alist of commands cycled by `ess-describe-object-at-point'. +%s is substitute with the name at point. The value is not used as + yet." + :group 'S+ + :type 'alist) + + +(defcustom ess-can-eval-in-background t + "If non-nil ESS can perform caching and other background activities. +This allows ESS to call the subprocess on idle time." + :group 'ess + :type 'boolean) + +(defcustom ess-user-full-name (user-full-name) + "The full name of the user." + :group 'ess + :type 'string) + +(defcustom ess-blink-region t + "If t evaluated region is highlighted for a shortwhile. +See also `ess-blink-delay'" + :group 'ess + :type 'boolean) + +(defcustom ess-blink-delay .3 + "Number of seconds to highlight the evaluated region." + :group 'ess + :type 'number) + +(defcustom ess-ask-for-ess-directory t + "When non-nil ask the process directory when ESS process starts. +When set to nil, and the process is invoked with an universal +argument, the directory is prompted for." + :group 'ess + :type 'boolean) + +(defcustom ess-ask-about-transfile nil + "Non-nil means ask about a transcript file before running ESS." + :group 'ess + :type 'boolean) + +(defcustom ess-display-buffer-reuse-frames t + "Non-nil means \\[display-buffer] reuses existing frames. +See `display-buffer-reuse-frames'." + :group 'ess + :type 'boolean) + +(defvar-local ess-language nil + "Determines the language to use for the current buffer. +See also `ess-dialect'.") + +(defvar-local ess-dialect nil + "String version of the dialect being run for the inferior process. +This, plus `ess-language', should be able to determine the exact +version of the statistical package being executed in the particular +buffer.") + +(defvaralias 'ess-directory-function 'ess-startup-directory-function) +(defcustom ess-startup-directory-function nil + "Function to return the directory that ESS is run from. +Value of `ess-startup-directory' has precedence over this function." + :group 'ess + :type '(choice (const nil) function)) + +(defvaralias 'ess-directory 'ess-startup-directory) +(defcustom ess-startup-directory nil + "The directory to run ESS processes from. +If a string it should be a directory from which to start the +process. If a symbol, the symbol's value should be a directory. + +For example, the following setting would always start the process +in the directory of the current file: + + (setq ess-startup-directory 'default-directory) + +If `ess-startup-directory' is nil (the default) and +`ess-startup-directory-function' is non-nil, the value returned +by `ess-startup-directory-function' is used as a directory. + +If `ess-startup-directory-function' is nil, then the current +project as returned by `project-current' is used. For files which +mark an R project see `ess-r-project'. For example you can add +.Rprofile to a sub-directory of a project to mark it as R +sub-project. + +Finally, if not in a project (`project-current' returned nil) the +`default-directory' is used. It is normally the directory of the +current file. + +See also `ess-ask-for-ess-directory'." + :group 'ess + :type '(choice (const nil) directory symbol)) + + +(defcustom ess-history-directory nil + "Directory to pick up `ess-history-file' from. +If this is nil, the history file is relative to the startup +directory of the inferior process (see `ess-startup-directory')." + :group 'ess + :type '(choice (const nil) directory)) + +(defcustom ess-history-file t + "File to pick up history from. nil means *no* history is read or written. +t means something like \".Rhistory\". +If this is a relative file name, it is relative to `ess-history-directory'. +Consequently, if that is set explicitly, you will have one history file +for all projects." + :group 'ess + :type '(choice (const :tag "Off" nil) + (const :tag "On" t) + file)) + +(defcustom ess-plain-first-buffername t + "When non-nil, the first process buffer created does not have a number. +In other words, it is R:foo rather than R:1:foo. Subsequent +processes buffers are always numbered (e.g. R:2:foo." + :group 'ess + :type 'boolean) + + +(define-obsolete-variable-alias + 'ess-use-inferior-program-name-in-buffer-name + 'ess-use-inferior-program-in-buffer-name "ESS 18.10") +(defcustom ess-use-inferior-program-in-buffer-name nil + "For R, use e.g., 'R-2.1.0' or 'R-devel' (the program name) for buffer name. +Avoids the plain dialect name." + :group 'ess + :type 'boolean) + +(defcustom ess-use-ido t + "If t ess will try to use ido completion whenever possible. + +By default ESS uses enables IDO flex matching. See +`ido-enable-flex-matching' for details on flex matching and +`ess-ido-flex-matching' on how to disable it for ESS, if you +don't want it. + +See info node `(ido) Top' for more information about how ido +works." + :group 'ess + :require 'ido + :type 'boolean) + + +(defcustom ess-tab-complete-in-script nil + "If non-nil, TAB tries to complete if it does not indent in script buffers. +See also `ess-first-tab-never-complete'." + :group 'ess + :type 'boolean) +(make-obsolete-variable 'ess-tab-complete-in-script 'tab-always-indent "ESS 19.04" 'set) + +(define-obsolete-variable-alias 'ess-first-tab-never-completes-p + 'ess-first-tab-never-complete "ESS 19.04") +(defcustom ess-first-tab-never-complete 'symbol + "If t, first TAB never tries to complete in `ess-mode'. +If \\='symbol first TAB doesn't try to complete if next char is a +valid symbol constituent. + +If \\='symbol-or-paren don't complete if next char is closed paren +)}] or symbol character. + +If \\='symbol-or-paren-or-punct don't complete if next char is +punctuation +-=% etc, or closed paren or symbol. + +If \\='unless-eol - first TAB completes only at end of line. + +If nil first TAB always tries to complete (this might be too +aggressive and dangerous)." + :group 'ess + :type '(choice (const nil) + (const symbol) + (const symbol-or-paren) + (const symbol-or-paren-or-punct) + (const unless-eol) + (const t))) + +(defcustom ess-use-eldoc t + "If t, activate eldoc in `ess-mode' and `inferior-ess-mode' buffers. +If \\='script-only activate in `ess-mode' buffers only. + +See also `ess-eldoc-show-on-symbol'." + :group 'ess-extras + :type '(choice (const t) (const script-only) (const nil))) + + +(defcustom ess-eldoc-show-on-symbol nil + "If non-nil, show help string whenever the point is on a symbol. +If nil show only when the point is in a function call, i.e. after (." + :group 'ess-extras + :type 'boolean) + +(defcustom ess-eldoc-abbreviation-style 'normal + "Controls how `eldoc' displays information that does not fit on a line. + +A symbol which can be + +- nil: do nothing +- mild: Replace TRUE, FALSE with T,F +- normal: Try mild + shorten the default values longer than 10 + characters. +- strong: Try normal + completely remove default values except + =F,=T,=d where d is a digit. +- aggressive (or t): Try strong + truncate the doc string to fit + into minibuffer. + +The default style is \\='normal. + +Ess-eldoc also honors the value of +`eldoc-echo-area-use-multiline-p'. If this variable is not t (the +default), doc strings are truncated to fit into minibufer. This +allows the use of different abbreviation styles with the +truncation." + :group 'ess + :type '(choice (const nil) (const mild) (const normal) (const strong) (const aggressive) (const t))) + +(defcustom ess-use-flymake t + "If non-nil activate flymake in `ess-mode' buffers. +If \\='process, only check if the buffer has an inferior process." + :group 'ess + :type '(choice (const :tag "Always" t) + (const :tag "With running inferior process" process) + (const :tag "Never" nil)) + :package-version '(ess . "18.10")) + +(defcustom ess-use-auto-complete t + "If non-nil, activate auto-complete support. +If t, activate auto-complete support in `ess-mode' and +`inferior-ess-mode' buffers. If \\='script-only activate in `ess-mode' +buffers only. + +If non-nil add `ac-source-R' and `ac-source-filename' to the +`ac-sources' buffer local variable. + +ESS defines three AC sources `ac-source-R',`ac-source-R-objects' +and `ac-source-R-args'. See auto-complete package +documentation (http://cx4a.org/software/auto-complete/) for how +to install your custom sources." + :group 'ess-extras + :type '(choice (const t) (const script-only) (const nil))) +(make-obsolete-variable 'ess-use-auto-complete "Auto-complete is unmaintained; use company-mode instead" + "ESS 19.04" 'set) + +(defcustom ess-use-company t + "If t, activate company support in `ess-mode' and `inferior-ess-mode' buffers. +If non-nil add `company-R-args' and `company-R-objects' to the +`company-backends'. If \\='script-only activate in `ess-mode' buffers +only." + :group 'ess-extras + :type '(choice (const t) (const script-only) (const nil))) + +(defcustom ess-company-arg-prefix-length nil + "Minimum prefix for ess company function argument completion." + :group 'ess-extras + :type '(choice (const :tag "Default" nil) + integer)) + +(defcustom ess-use-tracebug t + "If t, load `ess-tracebug' when R process starts." + :group 'ess-extras + :type 'boolean) + +(defcustom ess-ido-flex-matching t + "If t, ido for ESS completion uses flex matching. +See `ido-enable-flex-matching' for details. +If you have an old computer, or you load lot of packages, you +might want to set this to nil." + :group 'ess + :type 'boolean) + +(defvar ess--completing-hist nil + "Variable to store completion history. +Used by `ess-completion-read' command.") + +(defvar-local ess-smart-operators () + "List of smart operators to be used in ESS and IESS modes. +Not to be set by users. It is redefined by mode specific +settings, such as `ess-r-smart-operators'.") + +(defvaralias 'ess-R-smart-operators 'ess-r-smart-operators) +(defvar ess-r-smart-operators nil + "If nil, don't use any of smart operators. +If t, use all. If an explicit list of operators, use only those +operators. + +In current version of ESS, it controls the behavior of +`ess-smart-comma' only, but will be enriched in the near future.") + + +(defvar ess-no-skip-regexp "[ \t\n]*\\'" + "If `ess-next-code-line' sees this line, it doesn't jump over. + +Used to avoid annoying jumping by ess-eval.*-and-step to end of +buffer or end chunks etc.") + +(make-obsolete-variable 'ess-smart-S-assign-key nil "ESS 18.10") + +(defcustom ess-assign-list (cons (or (bound-and-true-p ess-S-assign) " <- ") + '(" <<- " " = " " -> " " ->> ")) + "List of assignment operators. +`ess-cycle-assign' uses this list. These strings must +contain spaces on either side." + ;; Note that spaces on either side is not strictly true (as in the + ;; function won't error), but matching <-/<<- is broken without + ;; them. + :type '(repeat string) + :group 'ess + :package-version '(ess "18.10")) +(defvar ess-S-assign) +(make-obsolete-variable 'ess-S-assign 'ess-assign-list "ESS 18.10") + +(defcustom ess-r-prettify-symbols + '(("<-" . (?\s (Br . Bl) ?\s (Bc . Bc) ?←)) + ("->" . (?\s (Br . Bl) ?\s (Bc . Bc) ?→)) + ("->>" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s + (Bl . Bl) ?- (Bc . Br) ?- (Bc . Bc) ?> + (Bc . Bl) ?- (Br . Br) ?>)) + ("<<-" . (?\s (Br . Bl) ?\s (Br . Bl) ?\s + (Bl . Bl) ?< (Bc . Br) ?- (Bc . Bc) ?- + (Bc . Bl) ?< (Br . Br) ?-))) + ;; Setup prettify-symbols-alist to show "pretty" arrows, but make + ;; sure that they arrows use the same amount of spacing as <- and + ;; <<- to ensure indentation does not change when + ;; prettify-symbols-mode is turned on/off. + "Alist of symbols prettifications, see `prettify-symbols-alist'. +This gets appended to `prettify-symbols-alist', so set it to nil +if you want to disable R specific prettification." + :group 'ess-R + :type '(alist :key-type string :value-type symbol) + :package-version '(ess . "18.10")) + +;;*;; Variables concerning editing behavior + +(defcustom ess-filenames-map t + "If non-nil, filenames and objects are the same in an attached directory. +This is not true for DOS and other OS's with limited filename +lengths. Even if this is set incorrectly, the right things will +probably still happen, however." + :group 'ess-edit + :type 'boolean) + +(defcustom ess-keep-dump-files t + "Variable controlling whether to delete dump files after a successful load. +If nil: always delete. If `ask', confirm to delete. If `check', confirm +to delete, except for files created with `ess-dump-object-into-edit-buffer'. +Anything else, never delete. This variable only affects the behavior +of `ess-load-file'. Dump files are never deleted if an error occurs +during the load." + :group 'ess-edit + :type '(choice (const :tag "Check" :value check) + (const :tag "Ask" :value ask) + (const :tag "Always keep" :value t) + (const :tag "Always delete" :value nil))) + +(defcustom ess-delete-dump-files nil + "Non-nil means delete dump files after they are created. +This applies to dump files created with +`ess-dump-object-into-edit-buffer', only. + +Boolean flag which determines what to do with the dump files +generated by \\[ess-dump-object-into-edit-buffer], as follows: + + If non-nil: dump files are deleted after each use, and so appear +only transiently. The one exception to this is when a loading error +occurs, in which case the file is retained until the error is +corrected and the file re-loaded. + + If nil: dump files are not deleted, and backups are kept +as usual. This provides a simple method for keeping an archive of S +functions in text-file form. + +Auto-save is always enabled in dump-file buffers to enable recovery +from crashes. + +This is useful to prevent source files being created for objects +you don't actually modify. Once the buffer is modified and saved +however, the file is not subsequently deleted unless +`ess-keep-dump-files' is nil, and the file is successfully loaded +back into S." + :group 'ess-edit + :type 'boolean) + +(defcustom ess-fill-calls t + "If non-nil, refilling inside a call arranges arguments. +In other words, refilling a paragraph inside a function or +indexing call will arrange the arguments according to +`fill-column' as in: + + fun_call(argument1, argument2, + argument3, argument4) + + +Refilling repeatedly cycles through different styles and +eventually to the original formatting. + + The second style formats according to one argument per line: + + fun_call(argument1, + argument2, + argument3, + argument4) + +When `ess-fill-calls-newlines' is t, the second style becomes: + + fun_call( + argument1, + argument2, + argument3, + argument4 + ) + + +Setting `ess-offset-arguments' to `prev-line' or `prev-call' +activates a third style. It keeps one argument per line except +for the first N arguments. N is controlled with a prefix. For +example, calling \\[fill-paragraph] three times sets N to 1 while +calling \\[fill-paragraph] twice then \\[universal-argument] 2 +\\[fill-paragraph] sets N to 2. Here what the default produces: + + fun_call(argument1, + argument2, + argument3, + argument4, + argument5 + ) + +This style is useful for refilling R6 or ggproto class +definitions. + + +The blinking of the refilled region can be disabled with +`ess-blink-refilling'." + :group 'ess-edit + :type 'boolean) + +(defcustom ess-fill-continuations t + "Controls filling of continuations. +If non-nil, refilling a paragraph inside a continuation of +statements (expressions separated by operators) will arrange all +its elements, never going past `fill-column'. + + lm(outcome ~ pred1 + pred2 + + pred3 + pred4, data) + +Refilling repeatedly cycles through different styles and +eventually to the original formatting. + +The second style lay out the statements according to one +expression per line: + + lm(outcome ~ + pred1 + + pred2 + + pred3 + + pred4, data) + +The blinking of the refilled region can be disabled with +`ess-blink-refilling'." + :group 'ess-edit + :type 'boolean) + +(defcustom ess-fill-calls-newlines nil + "When non-nil, refilling may place newlines before and after delimiters. +When non-nil, the second refilling style produces newlines +after and before the opening and closing delimiters. This is +intended for example for dplyr-style code: + + fun_call( + argument1, + argument2, + argument3, + argument4 + ) + +Note that this setting is temporary and likely to be replaced in +a future ESS version by a more comprehensive and flexible way to +set refill styles." + :group 'ess-edit + :type 'boolean) + +(defcustom ess-blink-refilling t + "When non-nil, refilling blinks the filling region." + :group 'ess-edit + :type 'boolean) + +(define-obsolete-variable-alias 'ess-mode-silently-save 'ess-save-silently "ESS 19.04") +(defcustom ess-save-silently 'auto + "If non-nil, possibly save buffers without asking. +If t, save without asking. If \\='auto, save without asking if +either `compilation-ask-about-save' or variable `auto-save-visited-mode' +is non-nil. Affects `ess-save-file'." + :group 'ess-edit + :type '(choice (const :tag "Do not save without asking." :value nil) + (const :tag "Use compilation-ask-about-save and auto-save-visited-mode." + :value auto) + (const :tag "Save without asking." :value t)) + :package-version '(ess . "19.04")) + +;;*;; Variables controlling editing + +;;;*;;; Edit buffer processing +(defcustom ess-function-template " <- function( )\n{\n\n}\n" + "If non-nil, function template used when editing nonexistent objects. + +The edit buffer will contain the object name in quotes, followed by +this string. Point will be placed after the first parenthesis or +bracket." + :group 'ess-edit + :type 'string) + +;;;*;;; Indentation parameters + +(define-obsolete-variable-alias 'ess-tab-always-indent 'tab-always-indent "ESS 19.04") + +(define-obsolete-variable-alias 'ess-indent-level 'ess-indent-offset "15.09") +(defvar ess-indent-offset 2 + "Main indentation offset that is commonly inherited by other offsets. +See `ess-style-alist' for all available offsets.") +;;;###autoload +(put 'ess-indent-offset 'safe-local-variable #'numberp) + + +(defvar ess-offset-arguments 'open-delim + "Indent for arguments of function calls or indexing brackets. +This variables has an effect only when the ( or [ are not +directly followed by a new line. See +`ess-offset-arguments-newline' for indentation after closing +newline. + +When set to `open-delim', arguments are indented relative to the +opening parenthesis of the closest function call: + + object <- call(argument, other_call(argument, + other_argument)) + + +When set to `prev-call', arguments are indented relative to the +closest function call: + + object <- call(argument, other_call(argument, + other_argument)) + + +When set to `prev-line', arguments are indented relative to the +preceding line: + + object <- call(argument, other_call(argument, + other_argument)) + +This setting can also be set to a list containing the the offset +type and the offset size, such as `'(prev-call 2)'. Otherwise, +`ess-indent-offset' is used as a default. See `ess-style-alist' +for other offsets controlling indentation.") + +(define-obsolete-variable-alias 'ess-arg-function-offset-new-line 'ess-offset-arguments-newline "15.09") +(defvar ess-offset-arguments-newline 'prev-call + "Indent of arguments when ( or [ is followed by a new line. + +When set to `open-delim', arguments on a new line are indented +relative to the opening parenthesis of the closest function call: + + object <- call(argument, other_call( + argument, + other_argument + )) + + +When set to `prev-call', arguments on a new line are indented relative to +the closest function call: + + object <- call(argument, other_call( + argument, + other_argument + )) + +You can control the details of indentation at `prev-call' with +`ess-indent-from-lhs' and `ess-indent-from-chain-start'. + + +When set to `prev-line', arguments on a new line are indented +relative to the preceding line: + + object <- call(argument, other_call( + argument, + other_argument + )) + +This setting can also be set to a list containing the the offset +type and the offset size, such as `'(prev-call 2)'. Otherwise, +`ess-indent-offset' is used as a default. See `ess-style-alist' +for other offsets controlling indentation.") + +(defvar ess-offset-block 'prev-line + "Controls indentation for blocks. +A block is usually declared with braces but a statement wrapped +in anonymous parentheses is also considered a block. This offset +can be either `prev-call', `prev-line' or `open-delim'. + +When set to `open-delim', blocks are indented relative to the +opening parenthesis of the closest function call: + + call(argument, other_call(parameter = { + stuff + }, { + stuff + })) + + call(argument, lapply(data, function(x) { + body + })) + + +When set to `prev-call', blocks are indented relative to the +closest function call: + + call(argument, other_call(parameter = { + stuff + }, { + stuff + })) + + call(argument, lapply(data, function(x) { + body + })) + +You can control the details of indentation at `prev-call' with +`ess-indent-from-lhs' and `ess-indent-from-chain-start'. + + +When set to `prev-line', blocks are indented relative to the +preceding line: + + call(argument, other_call(parameter = { + stuff + }, { + stuff + })) + + call(argument, lapply(data, function(x) { + body + })) + +This setting can also be set to a list containing the the offset +type and the offset size, such as `'(prev-call 2)'. Otherwise, +`ess-indent-offset' is used as a default. See `ess-style-alist' +for other offsets controlling indentation.") + +(define-obsolete-variable-alias 'ess-first-continued-statement-offset 'ess-offset-continued "15.09") +(define-obsolete-variable-alias 'ess-continued-statement-offset 'ess-offset-continued "15.09") +(defvar ess-offset-continued 'straight + "This setting controls indentation of continued statements. +That is, consecutive statements separated by operators. + +When set to \\='straight, continued statements are indented as follows: + + object %>% + some_function() %>% + other_function() + +When set to \\='cascade: + + object %>% + some_function() %>% + other_function() + +The \\='straight and \\='cascade settings are actually equivalent to +\\='(straight . t) and \\='(cascade . t), where t represents the +base indent size. More generally, you can supply \\='(straight . N) +to control the size of indentation. + +See `ess-style-alist' for for an overview of ESS indentation.") + +(defvar ess-align-nested-calls '("ifelse") + "List of strings for which `ess-offset-arguments-newline' is ignored. +These calls will be vertically aligned instead. For example, if +`ifelse' is a member of the list, nested ifelse calls are +indented like this: + + object <- ifelse(condition1, out1, + ifelse(condition2, out2, out3)) + +See `ess-style-alist' for for an overview of ESS indentation.") + +(defvar ess-align-arguments-in-calls '("function[ \t]*(") + "A list of regexes where `ess-offset-arguments' is ignored. +List of regexes specifying the calls where `ess-offset-arguments' +should have no effect on function declarations. The arguments of +those calls will be aligned from the opening parenthesis. + +By default, function declarations are overridden. If for example +`ess-offset-arguments' is set to `prev-line', then function calls +are normally indented as in: + + some_function(argument1, + argument2, argument3 + ) + +However, the parameters of function declarations will be +vertically aligned: + + fun <- function(argument1, + argument2 + argument3) { + body + } + +See `ess-style-alist' for further details.") + +(defvar ess-align-continuations-in-calls t + "Whether continuations inside calls are indented from the opening delimiter. +This produces the following indentation: + + 10 + (1 + 2 + + 3 + 4) + object[variable1 + + variable2] + + if (test1 || test2 || + test3 || test4) { + any(test5 & + test6) + } + +instead of + + 10 + (1 + 2 + + 3 + 4) + object[variable1 + + variable2] + + if (test1 || test2 || + test3 || test4) { + any(test5 & + test6) + } + +Definition operators (`<-', `=', `:=' and `~') still trigger an +indentation in all cases. Also, operators at top level and in +curly brackets are not affected by this setting and always induce +an offset: + + { + var1 + + var2 + } + +See `ess-style-alist' for for an overview of ESS indentation.") + +(defvar ess-align-blocks '(control-flow) + "List of block types for which `ess-offset-blocks' is ignored. +The overridden blocks are vertically aligned. The list can +contain either or both of the symbols `control-flow' and +`fun-decl'. + +With `control-flow', if, else for and while blocks will always be +aligned vertically. With `fun-decl', the body of a function +declaration will always be aligned with the call to +`function'.") + +(define-obsolete-variable-alias 'ess-arg-function-offset 'ess-indent-from-lhs "15.09") +(defvar ess-indent-from-lhs '(arguments fun-decl-opening) + "List of elements that are indented from the left side of an assignment. +The list accepts the symbol `arguments' and `fun-decl-opening'. + +For arguments, this setting only has an effect for offsets set to +`prev-call'. When set, this indentation is produced: + + some_function(parameter = other_function( + argument + )) + + object <- some_function( + argument1, + argument2 + ) + +instead of: + + some_function(parameter = other_function( + argument + )) + + object <- some_function( + argument1, + argument2 + ) + + +`fun-decl-opening' refers to the opening curly following a function +declaration. Setting it produces: + + object <- + function(argument) + { + body + } + +instead of: + + object <- + function(argument) + { + body + } + +This is useful when (a) you have a long function name and want to +break a line after `<-' so that you have room to lay out the +arguments within `fill-column' characters; (b) you still want to +align the function body from the LHS to save horizontal space. + +See `ess-style-alist' for for an overview of ESS indentation.") + +(defvar ess-indent-from-chain-start t + "When non-nil, chained calls are treated as if they were one call. +Indentation will start from the first one. This setting only has +an effect for offsets set to `prev-call' or block offsets set to +`opening-delim'. + +If nil: + + some_function(other_function( + argument + )) + +If t: + + some_function(other_function( + argument + )) + +See `ess-style-alist' for for an overview of ESS indentation.") + +;;added rmh 2Nov97 at request of Terry Therneau +(define-obsolete-variable-alias 'ess-fancy-comments 'ess-indent-with-fancy-comments "15.09") +(defcustom ess-indent-with-fancy-comments t + "Non-nil means distinguish between #, ##, and ### for indentation. +See `ess-style-alist' for for an overview of ESS indentation." + :type 'boolean + :group 'ess-edit) + +;;;*;;; Editing styles + +(defvar ess-style-alist + `((BSD + (ess-indent-offset . 8) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . prev-call) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + (C++ + (ess-indent-offset . 4) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . prev-call) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . (arguments)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + ;; CLB added rmh 2Nov97 at request of Terry Therneau + (CLB + (ess-indent-offset . ,(default-value 'ess-indent-offset)) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . (straight 4)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + (GNU + (ess-indent-offset . ,(default-value 'ess-indent-offset)) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . (prev-call 4)) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + (K&R + (ess-indent-offset . 5) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . prev-call) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + ;; added ajr 17.Feb'04 to match "common R" use (== DEFAULT apart from offset = 4) + (RRR + (ess-indent-offset . 4) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + (RRR+ + (ess-indent-offset . 4) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . open-delim) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . (arguments)) + (ess-indent-from-chain-start . nil) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments))) + + (RStudio + (ess-indent-offset . ,(default-value 'ess-indent-offset)) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . prev-line) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . nil) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . nil) + (ess-align-blocks . nil) + (ess-indent-from-lhs . (arguments)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . nil)) + + (RStudio- + (ess-indent-offset . ,(default-value 'ess-indent-offset)) + (ess-offset-arguments . prev-line) + (ess-offset-arguments-newline . prev-line) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . nil) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . nil) + (ess-align-blocks . nil) + (ess-indent-from-lhs . (arguments)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . nil)) + + (DEFAULT + (ess-indent-offset . ,(default-value 'ess-indent-offset)) + (ess-offset-arguments . ,(default-value 'ess-offset-arguments)) + (ess-offset-arguments-newline . ,(default-value 'ess-offset-arguments-newline)) + (ess-offset-block . ,(default-value 'ess-offset-block)) + (ess-offset-continued . ,(default-value 'ess-offset-continued)) + (ess-align-nested-calls . ,(default-value 'ess-align-nested-calls)) + (ess-align-arguments-in-calls . ,(default-value 'ess-align-arguments-in-calls)) + (ess-align-continuations-in-calls . ,(default-value 'ess-align-continuations-in-calls)) + (ess-align-blocks . ,(default-value 'ess-align-blocks)) + (ess-indent-from-lhs . ,(default-value 'ess-indent-from-lhs)) + (ess-indent-from-chain-start . ,(default-value 'ess-indent-from-chain-start)) + (ess-indent-with-fancy-comments . ,(default-value 'ess-indent-with-fancy-comments)))) + + "Predefined formatting styles for ESS code. +Use `ess-set-style' to apply a style in all R buffers. The values of +all styles except OWN are fixed. To change the value of variables +in the OWN group, customize the variable `ess-own-style-list'. +DEFAULT style picks default (aka global) values from ESS +indentation variables. In addition, ESS provides many indentation +styles, the most important being the RRR and the RStudio +variants. + +RRR is the common R style that adheres closely to R internal +standards. RRR+ is the same except it also aligns blocks in +function calls with the opening delimiter, producing more +indentation. The C++ style (named like this for historical +reasons rather than any resemblance to existing C++ indentation +schemes) is halfway between these two styles and indent block +arguments from the start of the surrounding function's name. + +The RStudio style closely mimics the indentation of the RStudio +editor. RStudio- is the same except it does not align arguments +in function calls, which corresponds to the settings of some +RStudio users. + +ESS indentation is fully specified by the following offsets and +variables. See the documentation of these variables for examples. + +Offsets: + + - `ess-indent-offset': main offset inherited by other settings + + - `ess-offset-arguments': offset type for function and bracket + arguments + + - `ess-offset-arguments-newline': offset type of arguments + when ( or [ is followed by a new line. + + - `ess-offset-block': offset type for brace and anonymous + parenthesis blocks + + - `ess-offset-continued': offset type for continuation lines in + multiline statements + + +Overrides (implies vertical alignment): + + - `ess-align-nested-calls': functions whose nested calls + should be aligned. + + - `ess-align-arguments-in-calls': calls where + `ess-offset-arguments' should be ignored + + - `ess-align-continuations-in-calls': whether to ignore + `ess-offset-continued' in calls. + + - `ess-align-blocks': whether to ignore `ess-offset-blocks' for + function declarations or control flow statements. + + +Control variables: + + - `ess-indent-from-lhs': whether to indent arguments from + left-hand side of an assignment or parameter declaration. + + - `ess-indent-from-chain-start': whether to indent arguments from + the first of several consecutive calls. + + - `ess-indent-with-fancy-comments': whether to indent #, ## and + ### comments distinctly.") + +(defun ess-add-style (key entries) + "Add a new style to `ess-style-list'. +The new style has KEY and ENTRIES. Remove any existing entry with +the same KEY before adding the new one." + (setq ess-style-alist (assq-delete-all key ess-style-alist)) + (add-to-list 'ess-style-alist (cons key entries))) + +(defcustom ess-own-style-list (cdr (assoc 'RRR ess-style-alist)) + "Indentation variables for your own style. +Set `ess-style' to 'OWN to use these values. To change +these values, use the customize interface. See the documentation +of each variable for its meaning." + :group 'ess-edit + :type 'alist + :initialize #'custom-initialize-set + :set (lambda (symbol value) + (set symbol value) + (ess-add-style 'OWN value))) + +;;;###autoload +(put 'ess-style 'safe-local-variable #'symbolp) + +(define-obsolete-variable-alias 'ess-default-style 'ess-style "ESS 19.04") +(defcustom ess-style 'RRR + "Current ESS indentation style, see `ess-style-alist' for more. +See the variable `ess-style-alist' for how these groups (RRR, +DEFAULT, GNU, BSD, ...) map onto different settings for +variables. OWN style is defined in `ess-own-style-list' and you +can customize it to your needs. DEFAULT style picks default (aka +global) values from ESS indentation variables. + +Prefer `ess-set-style' to set the current style. This variable +has an effect if set before a buffer is visited (e.g. in your +Emacs initialization file) or as a file or directory local +variable (see Info node `(Emacs) File Variables'." + :type '(choice (const OWN) + (const GNU) + (const BSD) + (const C++) + (const CLB) + (const K&R) + (const RRR) + (const RRR+) + (const RStudio) + (const RStudio-) + (const DEFAULT)) + :group 'ess-edit + :safe #'symbolp) + +;;*;; Variables controlling behavior of dump files + +(defcustom ess-source-directory + (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") temporary-file-directory) + "Directory in which to place dump files. +This can be a string (an absolute directory name ending in a slash) or +a lambda expression of no arguments which will return a suitable string +value. The lambda expression is evaluated with the process buffer as the +current buffer. + +This always dumps to a sub-directory (\".Src\") of the current ess +working directory (i.e. first elt of search list)." + :group 'ess-edit + :type 'directory + :package-version '(ess . "18.10")) + +(defvar ess-dump-filename-template nil + "Internal. Initialized by dialects.") + +(defcustom ess-dump-filename-template-proto (concat (user-login-name) ".%s.S") + "Prototype template for filenames of dumped objects. +The ending `S' is replaced by the current \\[ess-suffix], to give +`ess-dump-filename-template' when an inferior ESS process starts. + +By default, gives filenames like `user.foofun.S', so as not to clash with +other users if you are using a shared directory. Other alternatives: +\"%s.S\" ; Don't bother uniquifying if using your own directory(ies) +\"dumpdir\"; Always dump to a specific filename. This makes it impossible +to edit more than one object at a time, though. + (make-temp-name \"scr.\") ; Another way to uniquify" + ;; MM: The last 3-4 lines above suck (I don't understand them) -- FIXME -- + + :group 'ess-edit + :type 'string) + +(defcustom ess-pre-run-hook nil + "Hook to call before starting up ESS. +Good for setting up your directory." + :group 'ess-hooks + :type 'hook) + +(defcustom ess-post-run-hook nil + "Hook to call just after the ESS process starts up. +Currently this should not be used to interact with the inferior +process because this hook runs too early, before the inferior +mode had a chance to properly start up the process. To interact +with the process, you must use a mode-specific hook like +'ess-r-post-run-hook'." + :group 'ess-hooks + :type 'hook) + +(defcustom ess-send-input-hook nil + "Hook called just before line input is sent to the process." + :group 'ess-hooks + :type 'hook) + +;; ---- ./ess-roxy.el : ------------ + +(defcustom ess-roxy-package "roxygen2" + "The name of the R package to use for Roxygen." + :group 'ess-roxy + :type 'string) + +(defcustom ess-roxy-tags-noparam '("export" "noRd") + "The tags used in roxygen fields that can be used alone. +Used to decide highlighting and tag completion." + :group 'ess-roxy + :type '(repeat string)) + +(defcustom ess-roxy-tags-param '("author" "aliases" "concept" "details" + "examples" "format" "keywords" + "method" "exportMethod" + "name" "note" "param" + "include" "references" "return" + "seealso" "source" "docType" + "title" "TODO" "usage" "import" + "exportClass" "exportPattern" "S3method" + "inherit" "inheritParams" "inheritSection" + "importFrom" "importClassesFrom" + "importMethodsFrom" "useDynLib" + "rawNamespace" + "rdname" "section" "slot" "description" + "md" "eval" "family") + "The tags used in roxygen fields that require a parameter. +Used to decide highlighting and tag completion." + :group 'ess-roxy + :type '(repeat string)) + +(defcustom ess-roxy-template-alist + (list (cons "description" ".. content for \\description{} (no empty lines) ..") + (cons "details" ".. content for \\details{} ..") + (cons "title" "") + (cons "param" "") + (cons "return" "") + (cons "author" ess-user-full-name)) + "The tags and defaults to insert when creating empty templates. +Param is a place holder for where to enter +parameters. Description and details do not use @ tags, but are +instead placed at the beginning of the entry (and should +therefore also be at the beginning of this template to give +syntactically correct roxygen entries)" + :group 'ess-roxy + :type '(alist :key-type string :value-type string)) + +(defcustom ess-roxy-fill-param-p nil + "When non-nil `ess-roxy-update-entry' fills (wraps) parameters." + :group 'ess-roxy + :type '(choice (const :tag "Off" nil) + (const :tag "On" t))) + +(defcustom ess-roxy-hide-show-p nil + "Non-nil means ess-roxy uses function `hs-minor-mode' for block hiding with TAB." + :group 'ess-roxy + :type '(choice (const :tag "Off" nil) + (const :tag "On" t))) + +(defcustom ess-roxy-start-hidden-p nil + "Non-nil means all blocks should be hidden from start." + :group 'ess-roxy + :type '(choice (const :tag "Off" nil) + (const :tag "On" t))) + +(defcustom ess-roxy-str "##'" + "Prefix string to insert before each line in new roxygen blocks. +In existing roxygen blocks, the prefix is taken from the line at +point" + :group 'ess-roxy + :type 'string) + +(defvar ess-roxy-insert-prefix-on-newline t + "When non-nil, `ess-roxy-newline' inserts the roxy prefix on newlines.") + + ; System variables + +;; SJE -- this should not be defcustom - user does not set it. +(defvaralias 'ess-current-process-name 'ess-local-process-name) +(defvar-local ess-local-process-name nil + "The name of the ESS process associated with the current buffer.") +(put 'ess-local-process-name 'risky-local-variable t) +(put 'ess-local-process-name 'permanent-local t) + +(defcustom ess-switch-to-end-of-proc-buffer t + "If non-nil, \\\\[ess-switch-to-inferior-or-script-buffer] goes to the end of the process buffer." + :group 'ess + :type 'boolean) + +(defcustom ess-gen-proc-buffer-name-function 'ess-gen-proc-buffer-name:project-or-simple + "Function used for generation of the buffer name of the new ESS processes. +It should accept one argument PROC-NAME, a string specifying +internal process name (R, R:2, etc). + +Provided default options are: + +`ess-gen-proc-buffer-name:simple' + *proc* + +`ess-gen-proc-buffer-name:directory' + *proc:dir* +`ess-gen-proc-buffer-name:abbr-long-directory' + *proc:abbr-long-dir* +`ess-gen-proc-buffer-name:project-or-simple' + *proc:project-root* or *proc* +`ess-gen-proc-buffer-name:project-or-directory' + *proc:project-root* or *proc:dir* + +Strategies based on projects default to built-in strategies if +there is no project root in the current directory." + :group 'ess + :type '(choice (const :tag "*proc*" ess-gen-proc-buffer-name:simple) + (const :tag "*proc:dir*" ess-gen-proc-buffer-name:directory) + (const :tag "*proc:abbr-long-dir*" ess-gen-proc-buffer-name:abbr-long-directory) + (const :tag "*proc:project-root* or *proc*" ess-gen-proc-buffer-name:project-or-simple) + (const :tag "*proc:project-root* or *proc:dir*" ess-gen-proc-buffer-name:project-or-directory) + function) + :package-version '(ess . "19.04")) + + +(defcustom ess-kermit-command "gkermit -T" + "Kermit command invoked by `ess-kermit-get' and `ess-kermit-send'." + :group 'ess + :type 'string) + +(defcustom ess-kermit-prefix "#" + "String files must begin with to use kermit file transfer." + :group 'ess + :type 'string) + +(defcustom ess-kermit-remote-directory "." + "Buffer local variable that designates remote directory of file." + :group 'ess + :type 'string) +(make-variable-buffer-local 'ess-kermit-remote-directory) + +;;*;; Regular expressions + +(defcustom ess-dumped-missing-re + "\\(<-\nDumped\n\\'\\)\\|\\(<-\\(\\s \\|\n\\)*\\'\\)" + "Regex determines if dumped objects are replaced by `ess-function-template'. + +If a dumped object's buffer matches this re, then it is replaced +by `ess-function-template'." + :group 'ess + :type 'regexp) + +(defcustom ess-dump-error-re + (if (string= ess-language "S") "\nDumped\n\\'" + "[Ee]rror") + "Regexp used to detect an error when loading a file." + :group 'ess + :type 'regexp) + + + ; ess-inf: variables for inferior-ess. + +(defvar inferior-ess-own-frame nil + "Non-nil means that inferior ESS buffers should start in their own frame. +This variable is deprecated. +please add an entry to `display-buffer-alist' instead. See Info +node `(ess)Customizing startup'. For example: + +\(add-to-list \\='display-buffer-alist + \\='(\"*R\" + (display-buffer-reuse-window display-buffer-pop-up-frame)))") +(make-obsolete-variable 'inferior-ess-own-frame 'display-buffer-alist "ESS 19.04") +(make-obsolete-variable 'inferior-ess-frame-alist "It is ignored. Use `display-buffer-alist' and `pop-up-frame-alist' instead." "ESS 19.04") +(make-obsolete-variable 'inferior-ess-same-window 'display-buffer-alist "ESS 19.04") + +(defcustom inferior-ess-jit-lock-chunk-size 10000 + "Default for (buffer local) `jit-lock-chunk-size' in inferior ESS buffers." + :group 'ess-proc + :type 'integer) + + +(defvaralias 'inferior-R-program 'inferior-ess-r-program) +(define-obsolete-variable-alias 'inferior-R-program-name + 'inferior-ess-r-program "ESS 18.10") +(define-obsolete-variable-alias 'inferior-ess-r-program-name + 'inferior-ess-r-program "ESS 18.10") +(defcustom inferior-ess-r-program (if ess-microsoft-p + "Rterm" + "R") + "Program name for invoking an inferior ESS with \\[R]." + :group 'ess-R + :type '(choice (string) file)) + +(defcustom inferior-R-args "" + "String of arguments used when starting R. +See also `ess-R-readline'." + :group 'ess-R + :type 'string) + +(defcustom ess-R-readline nil + "When non-nil, use readline in R. +nil indicates that \"--no-readline \" should be used as argument +when starting R. This may very slightly speedup interaction. On +the other hand, readline is necessary for expansion of +\"~username/\" in paths. Note that readline interprets +tabs (tabular characters) in R source files as asking for file +name completion. This can mess up evaluation completely." + :group 'ess-R + :type 'boolean) + +(defvaralias 'inferior-R-objects-command 'inferior-ess-r-objects-command) +(defcustom inferior-ess-r-objects-command "print(objects(pos=%d, all.names=TRUE), max=1e6)\n" + "Format string for R command to get a list of objects at position %d. +Used in e.g., \\[ess-execute-objects] or \\[ess-display-help-on-object]." + :group 'ess-command + :type 'string) + +(defvar ess-getwd-command nil + "Command string retrieving the working directory from the process.") + +(defvar ess-setwd-command nil + "Command string to set working directory. +Should contain a formatting %s to be replaced by a +path (as in `setwd(%s)\\n'.") + +(defcustom ess-program-files ;; 32 bit version + (if (and ess-microsoft-p + (fboundp 'w32-short-file-name)) + (if (getenv "ProgramW6432") + (w32-short-file-name (getenv "ProgramFiles(x86)"));; always 32 on 64 bit OS + (w32-short-file-name (getenv "ProgramFiles"))) ;; always 32 on 32 bit OS + nil) + "Name for 32-bit programs. + +Safe (no embedded blanks) 8.3 name for 32-bit programs that works +across internationalization." + :group 'ess + :type '(choice (string) (const nil))) + +(defcustom ess-program-files-64 ;; 64 bit version + (when (and ess-microsoft-p (fboundp 'w32-short-file-name) (getenv "ProgramW6432")) + (w32-short-file-name (getenv "ProgramW6432"))) + "Name for 64-bit programs. + +Safe (no embedded blanks) 8.3 name for 64-bit programs that works +across internationalization." + :group 'ess + :type '(choice (string) (const nil))) + +(defcustom ess-directory-containing-R nil + "When non-nil, a directory containing R. +nil means the search for all occurrences of R on the machine will +use the default location of the R directory + (inside \"c:/Program Files\" in English locale Windows systems). +Non-nil values mean use the specified location as the +directory in which \"R/\" is located. For example, setting +`ess-directory-containing-R' to \"c:\" will tell ESS to search +for R versions with path names of the form \"c:/R/R-x.y.z\". + +Currently only used when `ess-microsoft-p'. If you change the +value of this variable, you need to restart Emacs for it to take +effect. It also needs to be set before you load ess-site as its +value is used once only when ESS is loaded." + :group 'ess + :type '(choice (directory) (const nil))) + +(defcustom ess-rterm-version-paths nil + "Stores the full path file names of Rterm versions computed via \\[ess-find-rterm]. +If you have versions of R in locations other than in +../../R-*/bin/Rterm.exe or ../../rw*/bin/Rterm.exe, relative to +the directory in the variable `exec-path' containing your default +location of Rterm, you will need to redefine this variable with a +`custom-set-variables' statement in your site-start.el or .emacs +file." + :group 'ess-R + :type '(repeat string)) + +(define-obsolete-variable-alias 'inferior-S3-program-name + 'inferior-S3-program "ESS 18.10") +(defcustom inferior-S3-program "/disk05/s/S" + "Program name for invoking an inferior ESS with S3()." + :group 'ess-S + :type 'string) + +(define-obsolete-variable-alias + 'inferior-S-elsewhere-program-name + 'inferior-S-elsewhere-program "ESS 18.10") +(defcustom inferior-S-elsewhere-program "sh" + "Program name to invoke an inferior ESS with S on a different computer." + :group 'ess-proc + :type 'string) + +(defvaralias 'S+6-dialect-name 'S+-dialect-name) +(defcustom S+-dialect-name "S+" + "Name of `dialect' for S-PLUS 6.x and later. +Easily changeable in a user's `.emacs'." + :group 'ess-SPLUS + :type 'string) + +(define-obsolete-variable-alias 'inferior-S+-program-name + 'inferior-S+-program "ESS 18.10") +(defcustom inferior-S+-program + (if ess-microsoft-p + (concat ess-program-files "/TIBCO/splus82/cmd/Splus.exe") + "Splus") + "Program name to invoke S+. +On Unix/Linux, use the Splus executable. On Windows, the default +value is correct for a default installation of S-Plus 8.1 and +with bash as the shell. For any other version or location, +change this value in ess-site.el or site-start.el. Use the 8.3 +version of the path name. Use double backslashes if you use the +msdos shell." + :group 'ess-SPLUS + :type '(choice (string) (file))) + +(defvaralias 'inferior-S+6-start-args 'inferior-S+-start-args) +(defvaralias 'inferior-Splus-args 'inferior-S+-start-args) +(defcustom inferior-S+-start-args "" + "String of arguments used when starting S. +These arguments are currently passed only to S+6 and higher." + :group 'ess-SPLUS + :type 'string) + +(defcustom inferior-Splus-objects-command "objects(where=%d)\n" + "Format string for R command to get a list of objects at position %d. +Used in e.g., \\[ess-execute-objects] or \\[ess-display-help-on-object]." + :group 'ess-command + :type 'string) + +(defcustom ess-S-quit-kill-buffers-p nil + "Controls whether S buffers should also be killed once a process is killed. +This is used only when an iESS process is killed using \\[ess-quit]. +Possible values: +nil - do not kill any S buffers associated with the process. +t - kill S buffers associated with the process. +ask - ask the user whether the S buffers should be killed." + :group 'ess-S + :type '(choice (const nil) (const t) (const ask))) + +(define-obsolete-variable-alias 'inferior-SAS-program-name + 'inferior-SAS-program "ESS 18.10") +(defcustom inferior-SAS-program "sas" + "Program name for invoking an inferior ESS with SAS()." + :group 'ess-sas + :type '(choice (string) (file))) + +(defvaralias 'R-editor 'ess-r-editor) +(defcustom ess-r-editor "emacsclient" + "Editor called by R process with `edit()' command." + :group 'ess + :type 'string) + +(defvaralias 'R-pager 'ess-r-pager) +(defcustom ess-r-pager 'nil ; Usually nil is correct as ESS and page() cooperate. + "Pager called by R process with `page()' command." + :group 'ess + :type '(choice (const nil) string)) + +(defcustom S-editor "emacsclient" + "Editor called by S process with `edit()' command." + :group 'ess + :type 'string) + +(defcustom S-pager + (if ess-microsoft-p "emacsclientw.exe" "emacsclient") + "Pager called by S process with `page()' command." + :group 'ess + :type 'string) + +(defvar-local ess-editor nil + "Editor command. + +Editor by which the process sends information to an Emacs buffer +for editing and then to be returned to the process.") + +(defvar-local ess-pager nil + "Pager by which the process sends information to an Emacs buffer.") + +(defvar-local inferior-ess-language-start nil + "Initialization commands sent to the ESS process.") + +(define-obsolete-variable-alias 'inferior-ess-program-name + 'inferior-ess-program "ESS 18.10") +(defvar-local inferior-ess-program nil + "Default program name for invoking `inferior-ess'. +The other variables ...-program should be changed, for the +corresponding program.") + +(make-obsolete-variable 'inferior-ess-start-args + "Use the language specific variables like `inferior-R-args'" + "ESS 19.04") +(defvar inferior-ess-start-args "" + "String of arguments passed to the ESS process. +If you wish to pass arguments to a process, see e.g. `inferior-R-args'.") + +(defcustom inferior-ess-pager (if ess-microsoft-p "console" "cat") + "Pager to use for reporting help files and similar things." + :group 'ess-proc + :type 'string) + +(defvar-local inferior-ess-primary-prompt "> " + "Regular expression used by `ess-mode' to detect the primary prompt.") + +(defvar-local inferior-ess-secondary-prompt nil + "Regular expression used by `ess-mode' to detect the secondary prompt. +This is issued by S to continue an incomplete expression. +Set to nil if language doesn't support secondary prompt.") + +(defvar ess-traceback-command nil + "Command to generate error traceback.") + +;; Need this to recognize prompts of the form + + + > > > +;; and "+ . + ", but not "Abcd. " +(defvar inferior-S-prompt "[]a-zA-Z0-9.[]*[+ ]*> \\(?:[>+.] \\)*" + "Regexp used in S and R inferior and transcript buffers for prompt navigation. +Must not be anchored to BOL.") + +;;*;; Variables controlling interaction with the ESS process + +(defcustom ess-execute-in-process-buffer nil + "Non-nil means the ess-execute- commands output to the process buffer. +Otherwise, they get their own temporary buffer." + :group 'ess-proc + :type 'boolean) + +(defcustom ess-eval-empty nil + "Non-nil means `ess-eval-line*' will send empty lines to the ESS process." + :group 'ess-proc + :type 'boolean) + +(defvaralias 'ess-eval-visibly-p 'ess-eval-visibly) + +(defcustom ess-eval-visibly 'nowait + "Non-nil means ess-eval- commands display commands in the process buffer. +If \\='nowait, ESS shows input commands in the process buffer, but +doesn't wait for the process. Thus all the output is printed +after the input lines. + +If t, ESS waits after each line of the command for the process +output. This results in a nice sequence of input and output but +stalls Emacs on long output (like Sys.sleep(5) in R). + +If nil, ESS doesn't print input commands and doesn't wait for the +process. + +This variable also affect the evaluation of input code in +iESS. The effect is similar to the above. If t then ess waits for +the process output, otherwise not." + :group 'ess-proc + :package-version '(ess . "19.04") + :type '(choice (const t) (const nowait) (const nil))) + +(defcustom ess-eval-deactivate-mark (fboundp 'deactivate-mark); was nil till 2010-03-22 + "Non-nil means that after ess-eval- commands the mark is deactivated." + :group 'ess-proc + :type 'boolean) + +(defcustom ess-use-R-completion t + "Non-nil means use R-builtin completion mechanism when available." + :group 'ess-proc + :type 'boolean) + +(defcustom ess-sleep-for-shell (if ess-microsoft-p 5 1) + "Pause before sending output to the shell." + :group 'ess-proc + :type 'number) + + ; System variables +;; VS[06-04-2016]: fixme: move all inf vars into ess-inf.el. + +;;*;; Variables relating to multiple processes + +(defvar-local ess--mode-line-process-indicator '("" ess-local-process-name) + "List of ESS mode-line indicators. +Local in process buffers and must start with a string. Changes of +this variable are automatically reflected in mode-lines of the +process and all associated with it buffers. + +Each symbol must evaluate to one of the standard mode line +objects. See info node `(elisp)Mode Line Data'). Add a symbol +with `add-to-list' and remove with `delq'. Note that the symbols +which are part of this list should better have +\\='risky-local-variable property set to t, otherwise the text +properties are not displayed. + +External utilities such as `ess-tracebug' and `ess-developer' +customize this variable to indicate changes in the process +status.") +(put 'ess--mode-line-process-indicator 'risky-local-variable t) + +(defvar-local ess--local-mode-line-process-indicator '("") + "List of local process indicators. +See `ess--mode-line-process-indicator' for how to set it. + +This is an internal variable used by tools like `ess-developer' +and `ess-tracebug'.") +(put 'ess--local-mode-line-process-indicator 'risky-local-variable t) + +;;*;; Inferior ESS commands + +(defvar-local ess-load-command "source('%s')\n" + "Dialect specific format-string for building the ess command to load a file. + +This format string should use %s to substitute a file name and should +result in an ESS expression that will command the inferior ESS to load +that file.") + +(defvar-local ess-eval-command nil + "Dialect specific format-string for building the command to evaluate a string. + +It is usually faster to send a string to remote processes than a +file. The latter involves Tramp and can be quite slow. When +possible, a dialect should implement that command and use it +preferentially. + +This format string should use %s as a placeholder for the string +to be evaluated and, optionally, %f for the file name to be +reported in the error references. + +The resulting command should not echo code or print any +transitory output. See also `ess-eval-visibly-command' and +`ess-eval-visibly-noecho-command'.") + +(defvar-local ess-build-eval-message-function nil + "Dialect-specific function for formatting an evaluation message.") + +(defcustom inferior-ess-dump-command "dump(\"%s\",file=\"%s\")\n" + "Format-string for building the ess command to dump an object into a file. +Use first %s to substitute an object name. +Use second %s to substitute the dump file name." + :group 'ess-command + :type 'string) + +(defvar-local inferior-ess-help-command "help(\"%s\")\n" + "Format-string for building the ESS command to ask for help on an object. +This format string should use %s to substitute an object name.") + +(defcustom inferior-ess-r-help-command ".ess.help('%s')\n" + "Format-string for building the R command to ask for help on an object. +This format string should use %s to substitute an object name. +If set, changes will take effect when next R session is started." + :group 'ess-command + :type 'string) + +(defvar-local inferior-ess-exit-command "q()\n" + "Format-string for building the ess command to exit. +This format string should use %s to substitute an object name.") + +(defvar-local inferior-ess-search-list-command nil + "`ess-language' command that prints out the search list; +i.e. the list of directories and (recursive) objects that `ess-language' uses +when it searches for objects. + +Really set in -customize-alist in ess[dl]-*.el") + +(defcustom inferior-ess-safe-names-command + "tryCatch(base::print(base::names(%s), max=1e6), error=function(e){})\n" + "Format string for ESS command to extract names from an object *safely*. + +%s is replaced by an \"object name\" -- usually a list or data +frame, but in R also e.g., `package:stats'." + :group 'ess-command + :type 'string) + +;;*;; Regular expressions +(defvar-local inferior-ess-prompt nil + "The regular expression used for recognizing prompts. + +It is always used in transcript mode. In inferior ess mode it is +used only if `comint-use-prompt-regexp' is t. + +If not set in language's customize-alist it is constructed at run time +from `inferior-ess-primary-prompt' and `inferior-ess-secondary-prompt'.") + + +(defvar-local ess-change-sp-regexp "" + "The regexp for matching the S/R/.. commands that change the search path.") + +(defvar ess-S+-change-sp-regexp + "\\(attach(\\([^)]\\|$\\)\\|detach(\\|collection(\\|library(\\|module(\\|source(\\)" + "The regexp for matching the S-plus commands that change the search path.") + +(defvaralias 'ess-R-change-sp-regexp 'ess-r-change-sp-regexp) +(defvar ess-r-change-sp-regexp + "\\(attach(\\([^)]\\|$\\)\\|detach(\\|library(\\|require(\\|source(\\)" + "The regexp for matching the R commands that change the search path.") + +;;*;; Process-dependent variables + +(defvar-local ess-sl-modtime-alist nil + "Alist of modification times for all ess directories accessed this session.") + +(defvar-local ess-prev-load-dir/file nil + "Cached value for `ess-load-file'. + +This symbol saves the (directory . file) pair used in the last +`ess-load-file' command. Used for determining the default in the next one.") + +(defvar-local ess-object-list nil + ;; This is a list of the currently known object names. It is + ;; current only for one command entry; it exists under the + ;; assumption that the list of objects doesn't change while entering + ;; a command. + "Cache of object names.") + +(defvar-local ess-help-topics-list nil + ;; List of currently known help topics. + "Cache of help topics.") + +;;*;; Miscellaneous system variables + +;; SJE: Wed 29 Dec 2004 - following 3 ess-object* variables can be removed +;; soon if no-one needs the completion code. +(defvar ess-object-name-db-file "ess-namedb" + "File containing definitions for `ess-object-name-db'.") + +(defvar ess-object-name-db-file-loaded '() + "List of programs whose name-db file has been loaded.") + +(defvar-local ess-object-name-db nil + "Alist of lists of object names, with directory names as keys. +The file ess-namedb.el is loaded (if it exists) to define this variable. +See also function `ess-create-object-name-db'.") + +;;;*;;; Font-lock support + +;; "Reserved Words" -- part 1 -- +(defvar ess-RS-constants + '("TRUE" "FALSE" "NA" "NULL" "Inf" "NaN")) +(defvar ess-R-constants + (append ess-RS-constants + '("NA_integer_" "NA_real_" "NA_complex_" "NA_character_"))) +(defvar ess-S-constants + (append ess-RS-constants + '("T" "F"))) + +(defvar ess-R-keywords + '("if" "else" "repeat" "while" "function" "for" "in" "next" "break" + "switch" "function" "return" "on.exit" "stop" ".Defunct" "tryCatch" + "withRestarts" "invokeRestart" + "recover" "browser") + "Reserved words or special functions in the R language.") + +(defvar ess-S-keywords + (append ess-R-keywords '("terminate"))) + +;; only some of these keywords "look like functions but are not": +(defvar ess-S-non-functions + '("if" "for" "function" "while")) + +;; first the common ones +(define-obsolete-variable-alias 'ess-S-modifyiers 'ess-S-modifiers "18.10") +(defvar ess-S-modifiers + '("library" "attach" "detach" "source" "module" + "message" "warning")) + +(define-obsolete-variable-alias 'ess-R-modifyiers 'ess-R-modifiers "18.10") +(defvar ess-R-modifiers + '("library" "attach" "detach" "source" "require" + "setwd" "options" "par" "load" "rm" + "message" "warning" ".Deprecated" + "signalCondition" "withCallingHandlers")) + +(defvar ess-R-message-prefixes + '("Error:" "Error in" + "Warning:" "Warning in" + "Warning messages")) +(defvar ess-S-message-prefixes + (append ess-R-message-prefixes + '("Syntax error:" "Dumped"))) + +(defvar ess-R-assign-ops + ;; don't want "=" here which is not only for assign + '("<<-" "<-" "->" "->>")) +(defvar ess-S-assign-ops ess-R-assign-ops) + +(defvar ess-R-function-name-regexp + (concat "\\(" "\\sw+" "\\)" + "[ \t]*" "\\(<-\\)" + "[ \t\n]*" "function\\b")) + +(defvar ess-S-function-name-regexp + ess-R-function-name-regexp) + +(defvar ess-font-lock-keywords nil + "A name of the dialect specific font-lock keywords in the current buffer. +See `ess-R-font-lock-keywords' for an example. This is an +internal variable.") + +(defvar ess-fl-keyword:fun-calls + (cons "\\(\\sw+\\)[\t ]*(" '(1 ess-function-call-face keep)) + "Font lock for function calls.") + +(defvar ess-fl-keyword:numbers + (cons "\\b\\.?[0-9]+[.eEL]?[0-9]*\\b" 'ess-numbers-face) + "Font lock for numbers.") + +(defvar ess-fl-keyword:delimiters + (cons "\\s(\\|\\s)" 'ess-paren-face) + "Font lock for parenthesis.") + +(defvar ess-fl-keyword:= + (cons "=" 'ess-paren-face) + "Font lock for equal sign (=).") + +(defvar ess-fl-keyword:operators + (cons "[-=+*> +;; Created: 01-10-2012 (ESS 12.09) + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; start the inferior with M-x gretl. + +;;; Code: + +(require 'compile); for compilation-* below +(require 'ess-r-mode) + + +(add-to-list 'auto-mode-alist '("\\.inp\\'" . ess-gretl-mode)) + + +(defvar gretl-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?_ "w" table) ; underscores in words + (modify-syntax-entry ?@ "w" table) + (modify-syntax-entry ?# "<" table) ; # single-line comment start + (modify-syntax-entry ?\n ">" table) ; \n single-line comment end + (modify-syntax-entry ?\{ "(} " table) + (modify-syntax-entry ?\} "){ " table) + (modify-syntax-entry ?\[ "(] " table) + (modify-syntax-entry ?\] ")[ " table) + (modify-syntax-entry ?\( "() " table) + (modify-syntax-entry ?\) ")( " table) + (modify-syntax-entry ?\r " " table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?* "." table) + (modify-syntax-entry ?/ "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?| "." table) + (modify-syntax-entry ?! "." table) + (modify-syntax-entry ?\\ "\\" table) + (modify-syntax-entry ?\' "." table) + (modify-syntax-entry ?\` "w" table) + (modify-syntax-entry ?\" "\"" table) + (modify-syntax-entry ?. "w" table) + (modify-syntax-entry ?_ "w" table) + (modify-syntax-entry ?\% "." table) + (modify-syntax-entry ?\# "<" table) + (modify-syntax-entry ?\n ">" table) + table) + "Syntax table for `ess-gretl-mode'.") + +;; syntax table that holds within strings +(defvar ess-gretl-mode-string-syntax-table + (let ((table (make-syntax-table))) + table) + "Syntax table for `ess-gretl-mode' that holds within strings.") + +(defcustom gretl-continuation-offset 4 + "Extra indentation applied to Gretl continuation lines." + :type 'integer + :group 'ess-gretl) + +(defvar gretl-continuation-regexp + "[^#%\n]*\\(\\\\\\|\\.\\.\\.\\)\\s-*\\(\\s<.*\\)?$") + +(defcustom gretl-continuation-string "\\" + "Character string used for Gretl continuation lines. Normally \\." + :type 'string + :group 'ess-gretl) + +;; (defconst gretl-string-regex +;; "\"[^\"]*?\\(\\(\\\\\\\\\\)*\\\\\"[^\"]*?\\)*\"") + +(defconst gretl-function-header-regexp + (concat "^\\s-*\\<\\(function\\)\\>" + "\\([^=;\n]*=[ \t]*\\|[ \t]*\\)\\(\\w+\\)\\>") + "Regexp to match a Gretl function header. +The string `function' and its name are given by the first and third +parenthetical grouping.") + +;; (defconst ess-function-call-regexp +;; "\\s\"?\\(\\(\\sw\\|\\s_\\)+\\(<-\\)?\\)\\s\"?*\\s-*(" +;; "Regexp for function names") + +(defvar gretl-command-words + '("add" "adf" "anova" "append" "ar" "ar1" "arbond" "arch" + "arima" "biprobit" "break" "boxplot" "chow" "clear" "coeffsum" "coint" + "coint2" "corr" "corrgm" "cusum" "data" "dataset" "delete" "diff" + "difftest" "discrete" "dpanel" "dummify" "duration" "elif" "else" "end" + "endif" "endloop" "eqnprint" "equation" "estimate" "fcast" "foreign" "fractint" + "freq" "function" "funcerr" "garch" "genr" "gmm" "gnuplot" "graphpg" + "hausman" "heckit" "help" "hsk" "hurst" "if" "include" "info" + "intreg" "kalman" "kpss" "labels" "lad" "lags" "ldiff" "leverage" + "levinlin" "logistic" "logit" "logs" "loop" "mahal" "makepkg" "meantest" + "mle" "modeltab" "modprint" "modtest" "mpols" "negbin" "nls" "normtest" + "nulldata" "ols" "omit" "open" "orthdev" "outfile" "panel" "pca" + "pergm" "textplot" "poisson" "print" "printf" "probit" "pvalue" "quantreg" + "qlrtest" "qqplot" "quit" "rename" "reset" "restrict" "rmplot" "run" + "runs" "scatters" "sdiff" "set" "setinfo" "setobs" "setmiss" "shell" + "smpl" "spearman" "sprintf" "square" "sscanf" "store" "summary" "system" + "tabprint" "tobit" "tsls" "var" "varlist" "vartest" "vecm" "vif" + "wls" "xcorrgm" "xtab" "debug" "return" "catch" "for" "foreach" + "while" "const" "3sls" "liml" "fiml" + "sur" "params" "deriv" "orthog" "weights" "series" "scalar") + "Commands in Gretl (these names are also reserved).") + +(defvar gretl-genr-functions + '("abs" "sin" "cos" "tan" "asin" "acos" "atan" "sinh" + "cosh" "tanh" "asinh" "acosh" "atanh" "log" "ln" "log10" + "log2" "exp" "sqrt" "diff" "ldiff" "sdiff" "lags" "int" + "round" "ceil" "floor" "sort" "dsort" "sortby" "ranking" "orthdev" + "nobs" "firstobs" "lastobs" "uniform" "normal" "cum" "missing" "ok" + "misszero" "lrvar" "quantile" "median" "gini" "zeromiss" "sum" "mean" + "min" "max" "sd" "var" "sst" "cnorm" "dnorm" "qnorm" + "gammafun" "lngamma" "digamma" "resample" "pnobs" "pmin" "pmax" "pmean" + "psd" "hpfilt" "bkfilt" "bwfilt" "fracdiff" "boxcox" "cov" "corr" + "movavg" "I" "zeros" "ones" "seq" "replace" "muniform" "mnormal" + "sumc" "sumr" "meanc" "meanr" "sdc" "minc" "maxc" "minr" + "maxr" "iminc" "imaxc" "iminr" "imaxr" "fft" "ffti" "cmult" + "cdiv" "mcov" "mcorr" "mxtab" "cdemean" "cholesky" "psdroot" "inv" + "invpd" "ginv" "diag" "transp" "vec" "vech" "unvech" "upper" + "lower" "rows" "cols" "det" "ldet" "tr" "onenorm" "infnorm" + "rcond" "rank" "qform" "mlag" "qrdecomp" "eigensym" "eigengen" "nullspace" + "princomp" "mexp" "fdjac" "BFGSmax" "obsnum" "isseries" "isscalar" "islist" + "isstring" "isnull" "nelem" "pdf" "cdf" "invcdf" "pvalue" "critical" + "randgen" "urcpval" "values" "mshape" "svd" "mols" "mpols" "mrls" + "mread" "mwrite" "selifc" "selifr" "polroots" "dummify" "wmean" "wvar" + "wsd" "xpx" "filter" "kfilter" "ksmooth" "ksimul" "trimr" "getenv" + "argname" "obslabel" "readfile" "grab" "strstr" "strncmp" "strlen" "sscanf" + "varname" "varnum" "tolower" "colnames" "rownames" "ljungbox" "msortby" "lincomb" + "imhof" "toepsolv" "diagcat" "xmin" "xmax" "corrgm" "mcovg" "fcstats" + "bessel" "fraclag" "mreverse" "deseas" "pergm" "irr" "npv" "logistic" + "weekday" "kdensity" "monthlen" "epochday" "setnote" "invmills" "polyfit" "chowlin" + "varsimul" "strsplit" "inlist" "errmsg" "isconst" "irf" "inbundle") + "Builtin functions for Gretl's genr command.") + + +(defvar gretl-option-flags + '("addstats" "all" "anova" "append" + "arch" "arma-init" "asymptotic" "auto" + "autocorr" "auxiliary" "balanced" "bartlett" + "between" "bootstrap" "both" "breusch-pagan" + "byobs" "by" "c" "close" + "coded" "cols" "column" "comfac" + "complete" "conditional" "contiguous" "continue" + "continuous" "control" "covariance" "cross" + "cross-section" "crt" "csv" "ct" + "ctt" "cubes-only" "dat" "database" + "dataset" "db" "degrees" "dhansen" + "difference" "diffuse" "discrete" "dpdstyle" + "drop-empty" "drop-first" "drop-last" "dummy" + "dynamic" "equal" "exit" "exponential" + "fcp" "fixed-effects" "from-file" "full" + "func" "gamma" "geomean" "gls" + "gmm" "gnu-R" "gnu-octave" "gph" + "gzipped" "hausman-reg" "hessian" "hilu" + "impulse-responses" "input" "inst" "integrate" + "intervals" "inverse-fit" "iterate" "jackknife" + "jbera" "jitter" "jmulti" "kendall" + "lags" "lagselect" "lbfgs" "lillie" + "liml" "linear-fit" "list" "loess-fit" + "log" "loglogistic" "lognormal" "logs" + "matrix" "matrix-diff" "medians" "ml" + "model1" "multi" "multinomial" "nc" + "next" "no-corc" "no-dates" "no-df-corr" + "no-gradient-check" "no-header" "no-missing" "no-scaling" + "no-stats" "normal" "normality" "notches" + "numerical" "odbc" "omit-obs" "one-scale" + "opg" "orthdev" "other" "out-of-sample" + "output" "overwrite" "p-values" "panel" + "panel-vars" "plot" "pooled" "preserve" + "print-final" "progress-bar" "progressive" "pwe" + "quadratic-fit" "quiet" "quit" "radians" + "random" "random-effects" "rank-sum" "raw" + "rc" "replace" "restrict" "restructure" + "reverse" "robust" "rolling" "row" + "rtf" "save" "save-all" "save-ehat" + "save-xbeta" "scalars" "seasonals" "send-data" + "sign" "signed-rank" "silent" "simple" + "simple-print" "single-yaxis" "skip-df" "spearman" + "special-time-series" "squares" "squares-only" "stacked-cross-section" + "stacked-time-series" "static" "stdresid" "suppress-fitted" + "swilk" "system" "t-ratios" "tall" + "test-down" "tex" "time-dummies" "time-series" + "to-file" "to_file" "traditional" "trend" + "two-step" "unequal-vars" "uniform" "unit-weights" + "variance-decomp" "vcv" "verbose" "wald" + "weibull" "weights" "white" "white-nocross" + "with-impulses" "with-lines" "write" "www" + "x-12-arima" "y-diff-only" "z-scores" "zeros") + "Gretl option flags.") + +(defvar gretl-internal-vars + '("Fstat" "T" "ahat" "aic" "bic" "chisq" "coeff_ci" + "coeff" "compan" "datatype" "df" "dwpval" "ec" "ehat" + "error" "ess" "fcast" "fcerr" "gmmcrit" "hausman" "hqc" + "h" "jalpha" "jbeta" "jvbeta" "kalman_llt" "kalman_lnl" "kalman_s2" + "kalman_t" "kalman_uhat" "llt" "lnl" "mnlprobs" "ncoeff" "nobs" + "nscan" "nvars" "obs" "pd" "pvalue" "rho" "rlnl" + "rsq" "s00" "s01" "s11" "sample" "sargan" "sigma" + "stderr" "stopwatch" "sysA" "sysB" "sysGamma" "t1" "t2" + "test" "trsq" "uhat" "unit" "vcv" "version" "vma" + "windows" "xlist" "xtxinv" "yhat" ) + "Model- and dataset-related variables.") + +(defconst gretl-block-start-keywords + (list "loop" "foreign" "function" "gmm" "if" "system" "mle" "nls" "restrict")) + +(defconst gretl-block-other-keywords + (list "else" "elif")) + +(defconst gretl-block-end-keywords + (list "end" "endif" "endloop")) + +(defvar gretl-keywords + (append gretl-block-start-keywords + gretl-block-other-keywords + gretl-block-end-keywords + '("break")) + "Reserved words in Gretl.") + + +(defun gretl-at-keyword (kw-list) + ; not a keyword if used as a field name, X.word, or quoted, :word + (and (or (= (point) 1) + (and (not (equal (char-before (point)) ?.)) + (not (equal (char-before (point)) ?:)))) + (not (ess-inside-string-or-comment-p (point))) + (not (ess-inside-brackets-p (point))) + (member (current-word) kw-list))) + + +(defconst gretl-font-lock-keywords + (list + ;; Fontify all builtin keywords. + (cons (concat "\\<\\(" (regexp-opt gretl-keywords) "\\)\\>") + 'font-lock-keyword-face) + ;; Fontify all option flags. + (cons (concat "[ \t]--\\(" (regexp-opt gretl-option-flags) "\\)") + 'font-lock-constant-face) + ;; Fontify all command words. + (cons (concat "\\<\\(" (regexp-opt gretl-command-words) "\\)\\>") + 'font-lock-builtin-face) + ;; Fontify all builtin operators. + (cons "\\(&\\||\\|<=\\|>=\\|==\\|<\\|>\\|!=\\|!\\)" + (if (boundp 'font-lock-builtin-face) + 'font-lock-builtin-face + 'font-lock-preprocessor-face)) + ;; Fontify all internal variables. + (cons (concat "\\$\\(" (regexp-opt gretl-internal-vars) "\\)\\>") + 'font-lock-variable-name-face) + + ;; Fontify all genr functions. + (cons (concat "\\<\\(" (regexp-opt gretl-genr-functions) "\\)\\>") + 'font-lock-variable-name-face) + ;; Fontify all function declarations. + (list gretl-function-header-regexp + '(1 font-lock-keyword-face) + '(3 font-lock-function-name-face nil t))) + "Additional Gretl expressions to highlight.") + + +(defvar gretl-block-begin-regexp + (concat "\\<\\(" (regexp-opt gretl-block-start-keywords) "\\)\\>")) + +(defvar gretl-block-else-regexp + (concat "\\<\\(" (regexp-opt gretl-block-other-keywords) "\\)\\>")) + +(defvar gretl-block-end-regexp + (concat "\\<\\(" (regexp-opt gretl-block-end-keywords) "\\)\\>")) + +(defvar gretl-block-begin-or-end-regexp + (concat gretl-block-begin-regexp "\\|" gretl-block-end-regexp)) + + +(defvar gretl-block-else-or-end-regexp + (concat gretl-block-else-regexp "\\|" gretl-block-end-regexp)) + +(defvar gretl-basic-offset 4) + +(defvar gretl-block-match-alist + '(("loop" . ("endloop")) + ("if" . ("else" "elif" "endif")) + ("nls" . ("end")) + ("mle" . ("end")) + ("gmm" . ("end")) + ("foreign" . ("end")) + ("restrict" . ("end")) + ("kalman" . ("end")) + ("system" . ("end"))) + "Alist with Gretl's matching block keywords. +Has Gretl's begin keywords as keys and a list of the matching else or +end keywords as associated values.") + + + +; get the position of the last open block +(defun gretl-last-open-block-pos (min) + (let ((count 0)) + (while (not (or (> count 0) (<= (point) min))) + (backward-word 1) + (setq count + (cond ((gretl-at-keyword gretl-block-start-keywords) + (+ count 1)) + ((and (zerop (string-match "\\(?:e\\(?:l\\(?:if\\|se\\)\\|nd\\(?:if\\|loop\\)?\\)\\)" (current-word))) + (not (ess-inside-comment-p)) (not (ess-inside-brackets-p))) + (- count 1)) + (t count)))) + (if (> count 0) + (point) + nil))) + + +(defun gretl-last-open-block (min) + (let ((pos (gretl-last-open-block-pos min))) + (and pos + (progn + (goto-char pos) + (+ gretl-basic-offset (current-indentation)))))) + + +; return indent implied by a special form opening on the previous line, if any +(defun gretl-form-indent () + (forward-line -1) + (end-of-line) + (backward-sexp) + (if (gretl-at-keyword gretl-block-other-keywords) + (+ gretl-basic-offset (current-indentation)) + (if (char-equal (char-after (point)) ?\() + (progn + (backward-word 1) + (let ((cur (current-indentation))) + (if (gretl-at-keyword gretl-block-start-keywords) + (+ gretl-basic-offset cur) + nil))) + nil))) + + +(defun gretl-indent-line () + "Indent current line of gretl code." + (interactive) + (end-of-line) + (indent-line-to + (or (and (ess-inside-string-p (line-beginning-position)) 0) + (save-excursion (ignore-errors (gretl-form-indent))) + (save-excursion + (let ((endtok (progn + (beginning-of-line) + (forward-to-indentation 0) + (gretl-at-keyword gretl-block-end-keywords)))) + (ignore-errors (+ (gretl-last-open-block (point-min)) + (if endtok (- gretl-basic-offset) 0))))) + ;; previous line ends in = + (save-excursion + (if (and (not (equal (point-min) (line-beginning-position))) + (progn + (forward-line -1) + (end-of-line) (backward-char 1) + (equal (char-after (point)) ?=))) + (+ gretl-basic-offset (current-indentation)) + nil)) + ;; take same indentation as previous line + (save-excursion (forward-line -1) + (current-indentation)) + 0)) + (when (gretl-at-keyword gretl-block-end-keywords) + (forward-word 1))) + +;; (defun gretl-send-string-function (process string visibly) +;; (let ((gretl-process (get-process "gretlcli"))) +;; (process-send-string process (format ess-load-command file))) + + +;; (defun gretl-send-string-function (process string visibly) +;; (let ((file (concat temporary-file-directory "gretl_eval_region.inp"))) +;; (with-temp-file file +;; (insert string)) +;; (process-send-string process (format ess-load-command file)))) + +(defun gretl--get-words-from-command (command start-reg end-reg proc) + (with-current-buffer (ess-command command nil nil nil nil proc) + (goto-char (point-min)) + (let ((beg (or (re-search-forward start-reg nil t) + (point-min))) + (end (progn (goto-char (point-max)) + (or (re-search-backward end-reg) + (point-max)))) + acum) + (goto-char beg) + (skip-chars-forward "\n") + (while (re-search-forward "[^ \t\n]+" end t) + (push (match-string-no-properties 0) acum)) + acum))) + +(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "gretl")) + (delete-dups + (append gretl-command-words gretl-genr-functions + gretl-block-end-keywords gretl-block-other-keywords + gretl-block-start-keywords + (gretl--get-words-from-command "help\n" "are:" "^For" proc) + (gretl--get-words-from-command "help functions\n" "Accessors:" "^Functions" proc) + (gretl--get-words-from-command "help functions\n" "^Functions" "^For" proc) + ))) + +;; (defvar ess-gretl-error-regexp-alist '(gretl-in gretl-at) +;; "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.") + +;; (add-to-list 'compilation-error-regexp-alist-alist +;; '(gretl-in "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) +;; (add-to-list 'compilation-error-regexp-alist-alist +;; '(gretl-at "^\\s-*\\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1)) + + +(defvar gretl-customize-alist + '((comint-use-prompt-regexp . t) + (inferior-ess-primary-prompt . "\\? ") + (inferior-ess-secondary-prompt . "\\ ") + (inferior-ess-prompt . "\\? ") + (ess-local-customize-alist . gretl-customize-alist) + (inferior-ess-program . "gretlcli") + (ess-load-command . "open \"%s\"\n") + ;; (ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+") + ;; (ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)") + ;; (ess-error-regexp-alist . ess-gretl-error-regexp-alist) + ;; (inferior-ess-objects-command . inferior-gretl-objects-command) + ;; (inferior-ess-search-list-command . "search()\n") + ;; inferior-ess-help-command . gretl-help-command) + (inferior-ess-help-command . "help %s\n") + (ess-language . "gretl") + (ess-dialect . "gretl") + (ess-suffix . "inp") + (ess-dump-filename-template . (replace-regexp-in-string + "S$" ess-suffix ; in the one from custom: + ess-dump-filename-template-proto)) + (ess-change-sp-regexp . nil );ess-r-change-sp-regexp) + (ess-help-sec-regex . ess-help-r-sec-regex) + (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) + (ess-function-pattern . ess-r-function-pattern) + (ess-object-name-db-file . "ess-r-namedb.el" ) + ;; (ess-imenu-mode-function . nil) + (ess-smart-operators . ess-r-smart-operators) + (inferior-ess-exit-command . "exit\n") + ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help? + (inferior-ess-language-start . nil) + (ess-STERM . "iESS") + ) + "Variables to customize for Gretl -- set up later than Emacs initialization.") + +;; (defcustom inferior-gretl-program "gretlcli" +;; "*The program to use for running gretl scripts." +;; :type 'string +;; :group 'ess-gretl) + +;; (defvar ess-gretl-versions '("gretcli") +;; "List of partial strings for versions of Julia to access within ESS. +;; Each string specifies the start of a filename. If a filename +;; beginning with one of these strings is found on `exec-path', a M-x +;; command for that version of Julia is made available. ") + +(defcustom inferior-gretl-args "" + "String of arguments used when starting gretl." + :group 'ess-gretl + :type 'string) + +;;;###autoload +(define-derived-mode ess-gretl-mode ess-mode "ESS[gretl]" + "Major mode for editing gretl source. See `ess-mode' for more help." + ;;(setq imenu-generic-expression R-imenu-generic-expression) + (ess-setq-vars-local gretl-customize-alist) + (setq font-lock-defaults `(,gretl-font-lock-keywords)) + (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-ignore-fill-prefix t) + (setq-local comment-start "# ") + (setq-local comment-add 1) + (setq-local comment-start-skip "\\s<+\\s-*") + (setq-local comment-column 40) + (setq-local indent-line-function #'gretl-indent-line) + (setq-local ess-local-customize-alist gretl-customize-alist) + (when (fboundp 'ess-add-toolbar) (ess-add-toolbar))) + + +(defvar ess-gretl-post-run-hook nil + "Functions run in process buffer after Gretl starts.") + +;;;###autoload +(defun gretl (&optional start-args) + "Call `gretl', +Optional prefix (C-u) allows to set command line arguments, such as +--vsize. This should be OS agnostic. +If you have certain command line arguments that should always be passed +to gretl, put them in the variable `inferior-gretl-args'." + (interactive "P") + ;; get settings, notably inferior-ess-r-program : + ;; (if (null inferior-gretl-program) + ;; (error "'inferior-gretl-program' does not point to 'gretl-release-basic' executable") + (ess-write-to-dribble-buffer ;; for debugging only + (format + "\n(Gretl): ess-dialect=%s, buf=%s" + ess-dialect (current-buffer))) + (let* ((r-start-args + (concat inferior-gretl-args " " ; add space just in case + (if start-args + (read-string + (concat "Starting Args [other than `" + inferior-gretl-args + "'] ? ")) + nil))) + (inf-buf (inferior-ess r-start-args gretl-customize-alist))) + (setq-local indent-line-function #'gretl-indent-line) + (setq-local gretl-basic-offset 4) + (setq indent-tabs-mode nil) + (goto-char (point-max)) + ;; (if inferior-ess-language-start + ;; (ess-eval-linewise inferior-ess-language-start + ;; nil nil nil 'wait-prompt))) + (with-current-buffer inf-buf + (run-mode-hooks 'ess-gretl-post-run-hook)) + inf-buf)) + + +;;;; IMENU + +;; (defvar gretl-imenu-generic-expression +;; '(("Function (_)" "^\\s-*function\\s-+\\(_[^ \t\n]*\\)" 1) +;; ("Function" "^\\s-*function\\s-+\\([^_][^ \t\n]*\\)" 1) +;; ("Const" "^\\s-*const \\([^ \t\n]*\\)" 1) +;; ("Type" "^\\s-*\\w*type\\w* \\([^ \t\n]*\\)" 1) +;; ("Load" " *\\(load\\)(\\([^ \t\n)]*\\)" 2) +;; ;; ("Classes" "^.*setClass(\\(.*\\)," 1) +;; ;; ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to +;; ;; ("Generics" "^.*setGeneric(\\([^,]*\\)," 1) +;; ;; ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\"\\(.+\\)\"," 2) +;; ;; ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1) +;; ;; ;; +;; ;; ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1) +;; ;; ("Package" "^.*\\(library\\|require\\)(\\(.*\\)," 2) +;; ;; ("Data" "^\\(.+\\)\\s-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1))) +;; )) + + +;; (defun ess-imenu-gretl (&optional arg) +;; "Gretl Language Imenu support for ESS." +;; (interactive) +;; (setq imenu-generic-expression gretl-imenu-generic-expression) +;; (imenu-add-to-menubar "Imenu-gretl")) + + +;; (defun ess-imenu-gretl (&optional arg) +;; "Gretl Language Imenu support for ESS." +;; (interactive) +;; (setq imenu-generic-expression gretl-imenu-generic-expression) +;; (imenu-add-to-menubar "Imenu-jl")) + + +(provide 'ess-gretl) + +;;; ess-gretl.el ends here diff --git a/elpa/ess-20230419.1527/ess-help.el b/elpa/ess-20230419.1527/ess-help.el new file mode 100644 index 00000000..0b2ccd13 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-help.el @@ -0,0 +1,864 @@ +;;; ess-help.el --- Support for viewing ESS help files -*- lexical-binding: t; -*- + +;; Copyright (C) 1989-2022 Free Software Foundation, Inc. + +;; Author: David Smith +;; Created: 7 Jan 1994 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Code for dealing with ESS help files. See README. where +;; is one of `S', `SAS', `Stata' or `XLispStat'. + +;;; Code: + + ; Requires and autoloads +(require 'cl-lib) +(eval-when-compile + (require 'tramp)) +(require 'info) +(require 'ess-mode) +(require 'ess-inf) +(require 'ess-utils) +(require 'ansi-color) + +(declare-function ess-r-help-mode "ess-r-mode") +(declare-function ess-stata-help-mode "ess-stata-lang") + + +(defcustom ess-help-mode-hook nil + "Functions to call when entering `ess-help-mode'." + :group 'ess-hooks + :type 'hook) + +(defvar ess--help-frame nil + "Stores the frame used for displaying R help buffers.") + +(defvar ess-help--aliases-timeout 10 + "The large timeout is necessary for some users (#1025, #1081).") + + ; ess-help-mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; In this section: +;;;; +;;;; * The function ess-display-help-on-object +;;;; * The major mode ess-help-mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(cl-defgeneric ess--help-major-mode () + "Determine which help major mode to call, and call it. +Uses `ess-dialect' to determine the appropriate help mode." + (ess-help-mode)) + +(defun ess--help-get-bogus-buffer-substring (buffer &optional nr-first) + "Return non-nil if BUFFER looks like a bogus ESS help buffer. +Return the pair (match-beg. match-end) which can be used in error +message. NR-FIRST is the number of characters at the start of the +buffer to examine when deciding if the buffer if bogus. If nil, +the first 150 characters of the buffer are searched." + (if (not nr-first) (setq nr-first 150)) + (with-current-buffer buffer + (let ((PM (point-min)) + (case-fold-search t) + searching res) + (setq res + (or ;; evaluate up to first non-nil (or end): + (< (- (point-max) PM) 80); buffer less than 80 chars + (not (setq searching t)) + ;; todo: move to customize-alist + (progn (goto-char PM) ;; R: + (re-search-forward "Error in help" nr-first t)) + (progn (goto-char PM) ;; S-plus 5.1 : + (re-search-forward "^cat: .*--" nr-first t)) + (progn (goto-char PM) ;; S version 3 ; R : + (re-search-forward "no documentation .+" nr-first t)) + (progn (goto-char PM) ;; stata + (re-search-forward "^help .*not found" nr-first t)))) + (ess-write-to-dribble-buffer + (format " |--> %s [searching %s]\n" res searching)) + (when res + (if searching + (buffer-substring (match-beginning 0) (match-end 0)) + (buffer-string)))))) + +(defun ess-help-get-local-help-buffers () + (ess-force-buffer-current) + (cl-remove-if-not + (lambda (buffer) + (let* ((pattern (concat "*help[" ess-current-process-name "](")) + (name (buffer-name buffer)) + (candidate (when (> (length name) (length pattern)) + (substring name 0 (length pattern))) )) + (when (string= pattern candidate) + buffer))) + (buffer-list))) + +(defvar-local ess-help-type nil + "Type of help file, help, index, vignettes etc. +Local in `ess-help' buffers.") + +(defvar-local ess-help-object nil + "Name of the object the help is displayed for. +Is name of the package for package index. +Local in `ess-help' buffers.") +(put 'ess-help-object 'permanent-local t) + +(defun ess-display-help-on-object (object &optional command) + "Display documentation for OBJECT. +If prefix ARG is given, force an update of the cached help topics +and query the ESS process for the help file instead of reusing an +existing buffer if it exists. Uses the variable +`inferior-ess-help-command' for the actual help command. Prompts +for the object name based on the cursor location for all cases +except the S-Plus GUI. With S-Plus on Windows (both GUI and in an +inferior Emacs buffer) the GUI help window is used. If COMMAND is +supplied, it is used instead of `inferior-ess-help-command'." + (interactive + (progn + (ess-force-buffer-current) + (when current-prefix-arg + (ess-help--reset-cache)) + (list (ess-find-help-file "Help on")))) + (let* ((hb-name (concat "*help[" ess-current-process-name "](" + (replace-regexp-in-string "^\\?\\|`" "" object) ")*")) + (old-hb-p (get-buffer hb-name)) + (tbuffer (get-buffer-create hb-name))) + (when (or (not old-hb-p) + (ess-process-get 'sp-for-help-changed?) + (ess--help-get-bogus-buffer-substring old-hb-p)) + (ess-with-current-buffer tbuffer + (ess--flush-help-into-current-buffer object command) + (setq ess-help-object object) + (ess--help-major-mode) + (setq truncate-lines nil + ess-help-type 'help))) + (unless (ess--help-kill-bogus-buffer-maybe tbuffer) + (ess-display-help tbuffer)))) + +(defun ess-help--reset-cache () + "Reset all cached help files." + (ess-process-put 'sp-for-help-changed? t) + (ess-help--reset-cache-override)) + +(cl-defgeneric ess-help--reset-cache-override ()) + +(defun ess-help-revert-buffer (_ignore-auto _noconfirm) + "Revert the current help buffer. +This reloads the documentation. IGNORE-AUTO and NOCONFIRM are +ignored." + (ess-process-put 'sp-for-help-changed? t) + (ess-display-help-on-object ess-help-object)) + +(defalias 'ess-help #'ess-display-help-on-object) + +(cl-defgeneric ess-build-help-command (object) + "Build a string command for retrieving help on OBJECT." + (format inferior-ess-help-command object)) + +(defun ess--flush-help-into-current-buffer (object &optional command) + (let ((inhibit-modification-hooks t) + (inhibit-read-only t)) + (delete-region (point-min) (point-max)) + (let ((command (if (and command (string-match-p "%s" command)) + (format command object) + command))) + (ess-command (or command (ess-build-help-command object)) + (current-buffer))) + (ess-help-underline) + (unless (string= ess-language "STA") + (ess-nuke-help-bs)) + (goto-char (point-min)) + (set-buffer-modified-p 'nil))) + +(defun ess--help-kill-bogus-buffer-maybe (buffer) + "Internal, try to kill bogus BUFFER with message. Return t if killed." + (when ess-help-kill-bogus-buffers + (let ((bog-mes (ess--help-get-bogus-buffer-substring buffer))) + (when bog-mes + ;; The following is giving erroneous messages when help is displayed in the browser + ;; (when (< (length bog-mes) 10) ;;no message at all, how to treat this properly? + ;; (setq bog-mes (format "No documentation found; %s" bog-mes))) + (ess-write-to-dribble-buffer + (format "(ess-help: kill bogus buffer %s ..\n" (buffer-name buffer))) + (message "%s" (replace-regexp-in-string "\n" "" bog-mes)) + ;; (ding) ;; don't ding, in julia a lot of doc strings are very short + (kill-buffer buffer))))) + +(defun ess-display-help-in-browser () + "Displaying HTML help where available, using \\[browse-url]." + (interactive) + (unless (string-match "^R" ess-dialect) + (user-error "Sorry, not implemented for %s " ess-dialect)) + (if (or (not ess-help-object) + (not (eq ess-help-type 'help))) + (message "No help topic found") + (ess-command (format "help('%s', help_type='html')\n" ess-help-object)))) + +(defun ess--button-action (&optional button) + "Provide help on object at the beginning of line. +It's intended to be used in R-index help pages. Load the package +if necessary. It is bound to RET and C-m in R-index pages." + (let* ((string (button-label button)) + (command (ess-build-help-command string))) + (ess-display-help-on-object string command))) + +(cl-defgeneric ess-help-commands () + "Return an alist of dialect specific retriever commands. +Currently understood commands: +- package-for-object - command to get the package of current + help object +- packages - command to get a list of available + packages (REQUIRED) +- package-index - command to get the package index (REQUIRED) +- index-keyword-reg - regexp used to find keywords for linking in + index listing only (1st subexpression is used) +- index-start-reg - regexp from where to start searching for + keywords in index listing" + (user-error "Not implemented for %s " ess-dialect)) + +(cl-defmethod ess-help-commands (&context (ess-dialect "R")) + '((package-for-object . "sub('package:', '', .ess.findFUN('%s'))\n") + (packages . ".packages(all.available=TRUE)\n") + (package-index . ".ess.help(package='%s', help.type='text')\n") + (index-keyword-reg . "^\\([^ \t\n:]+\\)") + (index-start-reg . "^Index:"))) + +(defun ess-display-package-index (&optional package) + "Prompt for package name and display its index." + (interactive + (list (let* ((coms (ess-help-commands)) + (all-packs (ess-get-words-from-vector (cdr (assoc 'packages coms)))) + (pack (or (when (and ess-help-object + (cdr (assoc 'package-for-object coms)) + (eq ess-help-type 'help)) + (car (ess-get-words-from-vector + (format (cdr (assoc 'package-for-object coms)) + ess-help-object)))) + (car (member (ess-read-object-name-default) all-packs))))) + (ess-completing-read "Index of" all-packs nil nil nil nil pack)))) + (let ((coms (ess-help-commands))) + (ess--display-indexed-help-page + (format (cdr (assoc 'package-index coms)) package) + (cdr (assoc 'index-keyword-reg coms)) + (format "*help[%s](index:%s)*" ess-dialect package) + 'index nil nil (cdr (assoc 'index-start-reg coms)) package))) + +(defun ess--display-indexed-help-page (command item-regexp title help-type + &optional action help-echo reg-start help-object) + "Internal function to display help pages with linked actions. +COMMAND to produce the indexed help page, +ITEM-REGEXP -- first subexpression is highlighted, +TITLE of the help page, +HELP-TYPE to be stored in `ess-help-type' local variable, +ACTION is a function with no argument (default is `ess--button-action'), +HELP-ECHO if given becomes the help-echo property of the button, +REG-START gives the start location from where to search linkifying, + and HELP-OBJECT becomes `ess-help-object'." + (let ((inhibit-modification-hooks t) + (alist ess-local-customize-alist) + (pname ess-local-process-name) + (buff (get-buffer-create title))) + (ess-with-current-buffer buff + (setq buffer-read-only nil) + (delete-region (point-min) (point-max)) + (setq ess-local-process-name pname) + (ess--help-major-mode) + (ess-setq-vars-local (eval alist t)) + (setq ess-help-object help-object + ess-help-sec-regex "\\(^\\s-.*\n\\)\\|\\(^\n\\)") + (ess--foreground-command command buff) + (ess-help-underline) + (set-buffer-modified-p 'nil) + (goto-char (point-min)) + (when reg-start ;; go to the beginning of listing + (re-search-forward reg-start nil t)) + (when item-regexp + ;;linkify the buffer + (save-excursion + (while (re-search-forward item-regexp nil t) + (make-text-button (match-beginning 1) (match-end 1) + 'mouse-face 'highlight + 'action (or action #'ess--button-action) + 'help-object (buffer-substring-no-properties (match-beginning 1) (match-end 1)) + 'follow-link t + 'help-echo (or help-echo "help on object"))))) + (save-excursion ;; why R help adds all these spaces? + (goto-char (point-min)) + (when (re-search-forward "Index:\n\n" nil t) + (let ((beg (point))) + (forward-paragraph 1) + (align-regexp beg (point) "\\(\\s-+\\)")))) + (setq buffer-read-only t) + (setq ess-help-type help-type) + (setq truncate-lines nil)) + (unless (ess--help-kill-bogus-buffer-maybe buff) + (ess-display-help buff)))) + +(defun ess-display-help-apropos (&optional pattern) + "Create an ess-apropos buffer with a *linked* list of apropos topics." + (interactive "sPattern: ") + (let (com regexp) + (cond ((equal ess-dialect "R") + (setq com "help.search('%s')\n" + regexp "^\\([^ \t\n:]+::[^ \t\n:]+\\)[ \t\n]+")) + ((equal ess-dialect "julia") + (setq com "apropos(\"%s\")\n" + regexp "^\\(\\(\\w\\|\\s_\\)+\\)(")) + ((equal ess-dialect "stata") + (setq com "hsearch %s\n" + regexp "^[\t ]*[0-9]+\\.[\t ]+\\(.+\\)$")) + (t (error "Not implemented for dialect %s" ess-dialect))) + (ess--display-indexed-help-page + (format com pattern) regexp + (format "*ess-apropos[%s](%s)*" ess-current-process-name pattern) + 'apropos))) + +(defun ess-display-demos () + "Create an ess-demos buffer with a *linked* list of available demos." + (interactive) + (let (com regexp) + (cond ((equal ess-dialect "R") + (setq com "demo()\n" + regexp "^\\([^ \n:]+\\) +")) + (t (error "Not implemented for dialect %s" ess-dialect))) + (ess--display-indexed-help-page + com regexp + (format "*ess-demos[%s]*" ess-current-process-name) + 'demos #'ess--action-demo))) + +(defun ess--action-demo (&optional button) + "Provide help on object at the beginning of line. +It's intended to be used in R-index help pages. Load the package +if necessary. It is bound to RET and C-m in R-index pages." + (let* ((string (button-label button)) + (command + (cond ((equal ess-dialect "R") + (format "demo('%s')\n" string)) + (t (error "Not implemented for dialect %s" ess-dialect))))) + (ess-eval-linewise command) + (ess-switch-to-end-of-ESS))) + +(defun ess-display-vignettes (&optional all) + "Display vignettes if available for the current dialect. +With (prefix) ALL non-nil, use `vignette(*, all=TRUE)`, i.e., from all installed + packages, which can be *very* slow." + (interactive "P") + (ess--display-vignettes-override all)) + +(cl-defgeneric ess--display-vignettes-override (_all) + "Display vignettes for the current dialect. +See `ess-display-vignettes' for ALL." + (user-error "Sorry, not implemented for %s" ess-dialect)) + +(defun ess--action-open-in-emacs (pos) + (display-buffer (find-file-noselect (get-text-property pos 'help-echo)))) +(defun ess--action-R-open-vignette (pos) + (ess-eval-linewise (format "vignette('%s', package='%s')\n" + (get-text-property pos 'vignette) + (get-text-property pos 'package)))) + +(defalias 'ess-help-quit #'quit-window) +(make-obsolete 'ess-help-quit 'quit-window "16.04") + +(defun ess-display-help (buff) + "Display buffer BUFF. +If `ess-help-pop-to-buffer' is non-nil, call `pop-to-buffer', +otherwise call `display-buffer' to display the buffer. + +You may control how help buffers are displayed by EITHER setting +an entry in `display-buffer-alist' (see examples in info +node `(ess) Controlling buffer display') OR setting the +ESS-specific variables `ess-help-own-frame', +`ess-help-reuse-window', `ess-help-frame-alist', and +`ess-display-buffer-reuse-frames'." + (let* ((action (cond (ess-help-own-frame + '(display-buffer-reuse-window + display-buffer-use-some-frame + display-buffer-pop-up-frame)) + (ess-help-reuse-window + '(display-buffer-reuse-window + ess-display-buffer-reuse-mode-window + display-buffer-pop-up-window + display-buffer-use-some-window)) + (t '(display-buffer-pop-up-window + display-buffer-use-some-window)))) + (alist `((mode . (ess-help-mode ess-r-help-mode ess-stata-help-mode ess-julia-help-mode)) + (reusable-frames . ,ess-display-buffer-reuse-frames) + ;; `display-buffer-use-some-frame' uses this to + ;; determine whether to use the frame or not. + (frame-predicate . (lambda (f) + (when (equal ess-help-own-frame 'one) + ;; Note we're always returning + ;; nil for `ess-help-own-frame' t. + (frame-parameter f 'ess-help-frame)))) + ;; If `display-buffer' makes a new frame, these are + ;; given as frame parameters. + (pop-up-frame-parameters . ,(append ess-help-frame-alist + `((auto-hide-function . delete-frame) + (ess-help-frame . ,(equal ess-help-own-frame 'one))))))) + (display-alist `(,action . ,alist))) + (if ess-help-pop-to-buffer + (pop-to-buffer buff display-alist) + (display-buffer buff display-alist)))) + +(defun ess-help-web-search (cmd) + "Search the web for documentation on CMD." + (interactive "sSearch for: ") + (ess--help-web-search-override cmd)) + +(cl-defgeneric ess--help-web-search-override (_cmd) + "Dialect-specific override for `ess-help-web-search', which see for CMD." + (error "Not implemented for %s" ess-dialect)) + +(defun ess-manual-lookup () + "Search manual for documentation." + (interactive) + (ess--manual-lookup-override)) + +(cl-defgeneric ess--manual-lookup-override () + "Dialect-specific override for `ess-manual-lookup'." + (error "Not implemented for %s" ess-dialect)) + +(defvar ess-doc-map + (let (ess-doc-map) + (define-prefix-command 'ess-doc-map) + (define-key ess-doc-map "\C-e" #'ess-describe-object-at-point) + (define-key ess-doc-map "e" #'ess-describe-object-at-point) + (define-key ess-doc-map "\C-d" #'ess-display-help-on-object) + (define-key ess-doc-map "d" #'ess-display-help-on-object) + (define-key ess-doc-map "\C-i" #'ess-display-package-index) + (define-key ess-doc-map "i" #'ess-display-package-index) + (define-key ess-doc-map "\C-a" #'ess-display-help-apropos) + (define-key ess-doc-map "a" #'ess-display-help-apropos) + (define-key ess-doc-map "\C-v" #'ess-display-vignettes) + (define-key ess-doc-map "v" #'ess-display-vignettes) + (define-key ess-doc-map "\C-o" #'ess-display-demos) + (define-key ess-doc-map "o" #'ess-display-demos) + (define-key ess-doc-map "\C-w" #'ess-help-web-search) + (define-key ess-doc-map "w" #'ess-help-web-search) + (define-key ess-doc-map "\C-m" #'ess-manual-lookup) + (define-key ess-doc-map "m" #'ess-manual-lookup) + ess-doc-map) + "ESS documentation map.") + + +(defvar ess-help-mode-map + (let ((map (make-keymap))) + (define-key map "\C-m" #'next-line) + (define-key map "h" #'ess-display-help-on-object) + (define-key map "w" #'ess-display-help-in-browser) + (define-key map "i" #'ess-display-package-index) + (define-key map "a" #'ess-display-help-apropos) + (define-key map "v" #'ess-display-vignettes) + (define-key map "l" #'ess-eval-line-visibly-and-step) + (define-key map "r" #'ess-eval-region-and-go) + (define-key map "f" #'ess-eval-function-or-paragraph-and-step) + (define-key map "n" #'ess-skip-to-next-section) + (define-key map "p" #'ess-skip-to-previous-section) + (define-key map "/" #'isearch-forward) + (define-key map "x" #'ess-kill-buffer-and-go) + (define-key map "k" #'kill-this-buffer) + (define-key map "\C-c\C-s" #'ess-switch-process) + (define-key map "\C-c\C-r" #'ess-eval-region) + (define-key map "\C-c\M-r" #'ess-eval-region-and-go) + (define-key map "\C-c\C-f" #'ess-eval-function) + (define-key map "\M-\C-x" #'ess-eval-function) + (define-key map "\C-c\M-f" #'ess-eval-function-and-go) + (define-key map "\C-c\C-j" #'ess-eval-line) + (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) + (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) + (define-key map [(control return)] #'ess-eval-region-or-line-visibly-and-step) + (define-key map "\C-c\M-j" #'ess-eval-line-and-go) + (define-key map "\M-\C-a" #'ess-goto-beginning-of-function-or-para) + (define-key map "\M-\C-e" #'ess-goto-end-of-function-or-para) + (define-key map "\C-c\C-y" #'ess-switch-to-ESS) + (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) + (define-key map "\C-c\C-l" #'ess-load-file) + (define-key map "\C-c\M-l" #'ess-load-file); alias, as in #'iESS#' where C-c C-l is comint-list-* + (define-key map "\C-c\C-v" #'ess-display-help-on-object) + (define-key map "\C-c\C-k" #'ess-request-a-process) + (define-key map "\C-c\C-d" 'ess-doc-map) + (define-key map "\C-c\C-e" 'ess-extra-map) + (define-key map "\C-c\C-t" 'ess-dev-map) + map) + "Keymap for ESS help mode.") + +;; One reason for the following menu is to the user about key strokes +(defvar ess-help-mode-menu + '("ESS-help" + ["Search forward" isearch-forward t] + ["Next section" ess-skip-to-next-section t] + ["Previous section" ess-skip-to-previous-section t] + ["Help on section skipping" ess-describe-sec-map t] + ["Beginning of buffer" beginning-of-buffer t] + ["End of buffer" end-of-buffer t] + "-" + ["Help on ..." ess-display-help-on-object t] + ["Apropos of ..." ess-display-help-apropos t] + ["Index of ..." ess-display-package-index t] + ["Vignettes" ess-display-vignettes t] + ["Open in browser" ess-display-help-in-browser t] + "-" + ["Eval line" ess-eval-line-and-step t] + ["Eval paragraph & step" ess-eval-paragraph-and-step t] + ["Eval region & go" ess-eval-region-and-go t] + ["Switch to ESS process" ess-switch-to-ESS t] + ["Switch to end of ESS proc." ess-switch-to-end-of-ESS t] + ["Switch _the_ process" ess-switch-process t] + "-" + ["Kill buffer" kill-this-buffer t] + ["Kill buffer & go" ess-kill-buffer-and-go t] + "-" + ["Handy commands" ess-handy-commands t]) + "Menu used in ess-help mode.") + +(easy-menu-define ess-help-mode-menu-map ess-help-mode-map + "Menu keymap for ess-help mode." ess-help-mode-menu) + +(define-derived-mode ess-help-mode special-mode "ESS Help" + "Mode for viewing ESS help files." + :group 'ess-help + ;; FIXME + ;; (if ess-mode-syntax-table ;;set in advance by ess-setq-local + ;; (set-syntax-table ess-mode-syntax-table)) + (setq-local revert-buffer-function #'ess-help-revert-buffer) + (setq show-trailing-whitespace nil)) + + +;;*;; User commands defined in ESS help mode + +(defun ess-skip-to-help-section () + "Jump to a section heading of a help buffer. +The section selected is determined by the command letter used to +invoke the command, as indicated by `ess-help-sec-keys-alist'. +Use \\[ess-describe-sec-map] to see which keystrokes find which +sections." + (interactive) + (let ((old-point (point)) + (case-fold-search nil) + (the-sec (cdr (assoc last-command-event ess-help-sec-keys-alist)))) + (cl-assert the-sec nil (format "Invalid section key: %c" last-command-event)) + (goto-char (point-min)) + (if (re-search-forward (concat "^" the-sec) nil t) + (progn (recenter) + (beginning-of-line)) + (message "No %s section in this help. Sorry." the-sec) + (goto-char old-point)))) + +(defun ess-skip-to-next-section () + "Jump to next section in ESS help buffer." + (interactive) + (let ((case-fold-search nil)) + (when (looking-at-p ess-help-sec-regex) + (forward-line)) + (if (re-search-forward ess-help-sec-regex nil 'no-error) + (beginning-of-line) + (message "No more sections.")))) + +(defun ess-skip-to-previous-section () + "Jump to previous section in ESS help buffer." + (interactive) + (let ((case-fold-search nil)) + (if (re-search-backward ess-help-sec-regex nil 'no-error) + (beginning-of-line) + (message "No previous section.")))) + +(defun ess-kill-buffer-and-go nil + "Kill the current buffer and switch back to the ESS process." + (interactive) + (kill-buffer (current-buffer)) + (when (and ess-current-process-name (get-process ess-current-process-name)) + (ess-switch-to-ESS nil))) + +(defun ess-describe-sec-map nil + "Display help for the `s' key." + (interactive) + (let ((keys-alist ess-help-sec-keys-alist)) + (describe-function 'ess-skip-to-help-section) + + (with-current-buffer "*Help*" + (setq buffer-read-only nil) + (goto-char (point-max)) + (insert "\n\nCurrently defined keys are: + +Keystroke Section +--------- -------\n") + (dolist (cs keys-alist) + (insert " " + (car cs) + " " + (cdr cs) "\n"))))) + +(defun ess-helpobjs-at-point--read-obj () + (let* ((obj (ess-read-object-name-default))) + ;; Exclude numbers + (unless (and obj (not (string-match "[[:alpha:]]" obj))) + obj))) + +(defun ess-unqualify-symbol (object) + (if (string-match "^[[:alnum:].]+::?" object) + (substring object (match-end 0)) + object)) + +(defun ess-helpobjs-at-point (slist) + "Return a list (def obj fun). +Obj is a name at point, fun is the name of the function call +point is in, and def is either obj or fun (in that order) which +has a a help file, i.e. it is a member of SLIST (string-list). +nil otherwise." + (let* ((obj (ess-helpobjs-at-point--read-obj)) + (unqualified-obj (and obj (ess-unqualify-symbol obj))) + ;; FIXME: probably should use syntactic logic here + (fun (ignore-errors + (save-excursion + (save-restriction + (narrow-to-region (max (point-min) (- (point) 1000)) + (point-max)) + (backward-up-list 1) + (backward-char 1) + (ess-read-object-name-default)))))) + (list (or (car (member obj slist)) + (when (member unqualified-obj slist) + obj) + (car (member fun slist))) + obj fun))) + +(cl-defgeneric ess-help-get-topics (proc) + "Return a list of help topics from PROC." + (user-error "Not supported for %s (process: %s)" ess-dialect proc)) + +(defun ess-find-help-file (p-string) + "Find help, prompting for P-STRING." + (ess-make-buffer-current) + (let* ((help-files-list (ess-help-get-topics ess-current-process-name)) + (hlpobjs (delq nil (ess-helpobjs-at-point help-files-list)))) + (ess-completing-read p-string (append hlpobjs help-files-list) + nil nil nil nil (car hlpobjs)))) + + +;;*;; Utility functions + +(defun ess-get-help-files-list () + "Return a list of files which have help available." + (apply #'nconc + (mapcar (lambda (str) + (let ((dirname (concat str "/.Help"))) + (and (file-directory-p dirname) + (directory-files dirname)))) + (ess-search-list)))) + +(defun ess-get-help-aliases-list () + "Return a list of aliases which have help available." + (message "Retrieving RDS aliases...") + ;; ess-command locks display, make sure the above message is visible + (redisplay t) + (ess-write-to-dribble-buffer "Processing RDS files ...\n") + ;; FIXME: This should be run asynchronously + (prog1 (ess-get-words-from-vector ".ess.getHelpAliases()\n" + nil nil nil ess-help--aliases-timeout) + (message "Retrieving RDS aliases...done"))) + +(defun ess-nuke-help-bs () + "Remove ASCII underlining and overstriking performed by ^H codes." + ;; This function is a modification of nuke-nroff-bs in man.el from the + ;; standard Emacs 18 lisp library. + ;; Nuke underlining and overstriking (only by the same letter) + (goto-char (point-min)) + (while (search-forward "\b" nil t) + (let* ((preceding (char-after (- (point) 2))) + (following (following-char))) + (cond ((= preceding following) + ;; x\bx + (delete-char -2)) + ((= preceding ?\_) + ;; _\b + (delete-char -2)) + ((= following ?\_) + ;; \b_ + (delete-region (1- (point)) (1+ (point))))))) + (goto-char (point-min)) + (let ((case-fold-search nil)); 'URL' != 'url' ('libcurl: ' on ?capabilities) + (while (re-search-forward "\\bURL: " nil t); test with ?rtags + ;; quick fix for C-x f confusion (getting into tramp) + (delete-region (match-beginning 0) (match-end 0)))) + ;; Crunch blank lines + (goto-char (point-min)) + (while (re-search-forward "\n\n\n\n*" nil t) + (replace-match "\n\n")) + ;; Nuke blanks lines at start. + (goto-char (point-min)) + (skip-chars-forward "\n") + (delete-region (point-min) (point))) + +(defun ess-help-underline () + "Replace _^H codes with underline face." + (save-excursion + (goto-char (point-min)) + (while (search-forward "_" nil t) + (backward-delete-char 2) + (put-text-property (point) (1+ (point)) 'face 'underline)))) + +;;*;; Link to Info +(defun ess-goto-info (node) + "Display node NODE from `ess-mode' info." + (require 'info) + (split-window) + (Info-goto-node (concat "(ess)" node))) + + +;; describe object at point + +(defvar-local ess-describe-object-at-point-commands nil + "Commands cycled by `ess-describe-object-at-point'. +Dialect specific.") + +(defvar ess--descr-o-a-p-commands nil) + +(defun ess-describe-object-at-point () + "Get info for object at point, & display it in an electric buffer or tooltip. +If region is active use it instead of the object at point. + +This is an electric command (`ess--execute-electric-command'), +which means that you can use the last key to cycle through the +action set (in this case `C-e'). After invocation of this command +all standard Emacs commands, except those containing `window' in +their names, remove the electric *ess-describe* buffer. Use +`other-window' to switch to *ess-describe* window. + +Customize `ess-describe-at-point-method' if you want to display +the description in a tooltip. See also +`ess-r-describe-object-at-point-commands' (and similar option for +other dialects)." + (interactive) + (if (not ess-describe-object-at-point-commands) + (message "Not implemented for dialect %s" ess-dialect) + (ess-force-buffer-current) + (let ((map (make-sparse-keymap)) + (objname (or (and (use-region-p) + (buffer-substring-no-properties (point) (mark))) + (ess-symbol-at-point))) + ess--descr-o-a-p-commands) ;; used in ess--describe-object-at-point + (unless objname (error "No object at point ")) + (define-key map (vector last-command-event) + #'ess--describe-object-at-point) + ;; todo: put digits into the map + (let* ((inhibit-quit t) ;; C-g removes the buffer + (buf (ess--execute-electric-command + map (format "Press %s to cycle" + (single-key-description last-command-event)) + nil nil objname)) + ;; read full command + (keys (read-key-sequence-vector "")) + (command (and keys (key-binding keys)))) + (when (and (commandp command) + (bufferp buf) + (or (not (symbolp command)) ;; kill on lambdas + (not (string-match "window" (symbol-name command))))) + (kill-buffer buf)) ;; bury does not work here :( (Emacs bug?) + (setq unread-command-events + (append keys unread-command-events)))))) + +(defun ess--describe-object-at-point (_ev objname) + (setq ess--descr-o-a-p-commands (or ess--descr-o-a-p-commands + (symbol-value ess-describe-object-at-point-commands))) + (let* ((com (format (car (pop ess--descr-o-a-p-commands)) objname)) + (buf (get-buffer-create "*ess-describe*")) + pos) + (unless (eq ess-describe-at-point-method 'tooltip) + ;; can take some time for the command to execute + (display-buffer buf)) + (sit-for .01) + (ess-command (concat com "\n") buf) ;; erases buf + (with-current-buffer buf + (goto-char (point-min)) + (insert (propertize (format "%s:\n\n" com) 'face 'font-lock-string-face)) + (forward-line -1) + (setq pos (point)) + ;; set the keys that we are used to in help mode + (special-mode) + (let ((inhibit-read-only t)) + (ansi-color-apply-on-region (point-min) (point-max)))) + (if (eq ess-describe-at-point-method 'tooltip) + (ess-tooltip-show-at-point + (with-current-buffer buf (buffer-string)) 0 30) + (display-buffer buf) + (set-window-point (get-buffer-window buf) pos) ;; don't move window point + buf))) + +(with-no-warnings + ;; We're just backporting here, don't care about compiler warnings + (defalias 'ess-display-buffer-reuse-mode-window + ;; TODO: Remove once we drop support for Emacs 25 + (if (fboundp 'display-buffer-reuse-mode-window) + 'display-buffer-reuse-mode-window + (lambda (buffer alist) + (let* ((alist-entry (assq 'reusable-frames alist)) + (alist-mode-entry (assq 'mode alist)) + (frames (cond (alist-entry (cdr alist-entry)) + ((if (eq pop-up-frames 'graphic-only) + (display-graphic-p) + pop-up-frames) + 0) + (display-buffer-reuse-frames 0) + (t (last-nonminibuffer-frame)))) + (inhibit-same-window-p (cdr (assq 'inhibit-same-window alist))) + (windows (window-list-1 nil 'nomini frames)) + (buffer-mode (with-current-buffer buffer major-mode)) + (allowed-modes (if alist-mode-entry + (cdr alist-mode-entry) + buffer-mode)) + (curwin (selected-window)) + (curframe (selected-frame))) + (unless (listp allowed-modes) + (setq allowed-modes (list allowed-modes))) + (let (same-mode-same-frame + same-mode-other-frame + derived-mode-same-frame + derived-mode-other-frame) + (dolist (window windows) + (let ((mode? + (with-current-buffer (window-buffer window) + (cond ((memq major-mode allowed-modes) + 'same) + ((derived-mode-p allowed-modes) + 'derived))))) + (when (and mode? + (not (and inhibit-same-window-p + (eq window curwin)))) + (push window (if (eq curframe (window-frame window)) + (if (eq mode? 'same) + same-mode-same-frame + derived-mode-same-frame) + (if (eq mode? 'same) + same-mode-other-frame + derived-mode-other-frame)))))) + (let ((window (car (nconc same-mode-same-frame + same-mode-other-frame + derived-mode-same-frame + derived-mode-other-frame)))) + (when (window-live-p window) + (prog1 (window--display-buffer buffer window 'reuse alist) + (unless (cdr (assq 'inhibit-switch-frame alist)) + (window--maybe-raise-frame (window-frame window)))))))))))) + +(provide 'ess-help) +;;; ess-help.el ends here diff --git a/elpa/ess-20230419.1527/ess-inf.el b/elpa/ess-20230419.1527/ess-inf.el new file mode 100644 index 00000000..0bd967ca --- /dev/null +++ b/elpa/ess-20230419.1527/ess-inf.el @@ -0,0 +1,3263 @@ +;;; ess-inf.el --- Support for running S as an inferior Emacs process -*- lexical-binding: t; -*- + +;; Copyright (C) 1989-2022 Free Software Foundation, Inc. + +;; Author: David Smith +;; Created: 7 Jan 1994 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Code for handling running ESS processes. + +;;; Code: + +(eval-when-compile + (require 'cl-lib) + (require 'tramp) + (require 'subr-x)) +(require 'ess-utils) +(require 'ess) +(require 'ess-tracebug) + +(require 'ansi-color) +(require 'comint) +(require 'compile) +(require 'format-spec) +(require 'overlay) +(require 'project) + +;; Don't require tramp at run time. It's an expensive library to load. +;; Instead, guard calls with (require 'tramp) and silence the byte +;; compiler. +(declare-function tramp-sh-handle-expand-file-name "tramp-sh" (name &optional dir)) +(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) +(declare-function tramp-tramp-file-p "tramp" (name)) +(declare-function inferior-ess-r-mode "ess-r-mode" ()) +(declare-function inferior-ess-julia-mode "ess-julia" ()) +(declare-function inferior-ess-stata-mode "ess-stata-mode" ()) +(declare-function extract-rectangle-bounds "rect" (start end)) + +(declare-function ess-mode "ess-mode" ()) +(declare-function ess-complete-object-name "ess-r-completion" ()) +;; FIXME:This one should not be necessary +(declare-function ess-display-help-on-object "ess-help" (object &optional command)) +(declare-function ess-dump-object-into-edit-buffer "ess-mode" (object)) + +(defvar add-log-current-defun-header-regexp) + +;; The following declares can be removed once we drop Emacs 25 +(declare-function tramp-file-name-method "tramp") +(declare-function tramp-file-name-user "tramp") +(declare-function tramp-file-name-host "tramp") +(declare-function tramp-file-name-localname "tramp") +(declare-function tramp-file-name-hop "tramp") + +(defcustom inferior-ess-mode-hook nil + "Hook for customizing inferior ESS mode. +Called after `inferior-ess-mode' is entered and variables have +been initialized." + :group 'ess-hooks + :type 'hook) + +(defvar inferior-ess-mode-syntax-table + (let ((tab (copy-syntax-table comint-mode-syntax-table))) + tab) + "Syntax table for `inferior-ess-mode'.") + +(defun inferior-ess--set-major-mode (dialect) + "Set major mode according to DIALECT." + (cond ((string= "R" dialect) + (progn (require 'ess-r-mode) + (inferior-ess-r-mode))) + ((string= "julia" dialect) + (progn (require 'ess-julia) + (inferior-ess-julia-mode))) + ((string= "stata" dialect) + (progn (require 'ess-stata-mode) + (inferior-ess-stata-mode))) + ;; FIXME: we need this horrible hack so that + ;; inferior-ess-mode-syntax-table gets set for + ;; languages that still rely on the old way of doing + ;; things (before we used define-derived-mode for + ;; inferior modes). + (t + (progn + (setq-local inferior-ess-mode-syntax-table + (eval (or (alist-get 'inferior-ess-mode-syntax-table ess-local-customize-alist) + (alist-get 'ess-mode-syntax-table ess-local-customize-alist)) + t)) + (inferior-ess-mode))))) + + ;;*;; Process handling + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; In this section: +;;; +;;; * User commands for starting an ESS process +;;; * Functions called at startup +;;; * Process handling code +;;; * Multiple process implementation +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;*;; Starting a process +(defun ess-proc-name (n name) + "Return name of process N, as a string, with NAME prepended. +If `ess-plain-first-buffername', then initial process is number-free." + (concat name + (if (not (and ess-plain-first-buffername + (= n 1))) ; if not both first and plain-first add number + (concat ":" (number-to-string n))))) + +(defvar-local inferior-ess--local-data nil + "Program name and arguments used to start the inferior process.") + +(defvar inferior-ess--last-started-process-buffer nil + "Useful in unit tests to check initialisation errors. +In that case the command fails before it can return the process +buffer to us. This global variable can be checked instead.") + +(defun inferior-ess (start-args customize-alist &optional no-wait) + "Start inferior ESS process. +Without a prefix argument, starts a new ESS process, or switches +to the ESS process associated with the current buffer. With +START-ARGS (perhaps specified via \\[universal-argument]), starts +the process with those args. The current buffer is used if it is +an `inferior-ess-mode' or `ess-transcript-mode' buffer. + +If `ess-ask-about-transfile' is non-nil, you will be asked for a +transcript file to use. If there is no transcript file, the +buffer name will be like *R* or *R2*, determined by +`ess-gen-proc-buffer-name-function'. + +Takes the program name from the variable `inferior-ess-program'. + +See Info node `(ess)Customizing startup' and +`display-buffer-alist' to control where and how the buffer is +displayed. + +\(Type \\[describe-mode] in the process buffer for a list of +commands.) + +CUSTOMIZE-ALIST is the list of dialect-specific variables. When +non-nil, NO-WAIT tells ESS not to wait for the process to finish. +This may be useful for debugging." + ;; Use the current buffer if it is in inferior-ess-mode or ess-trans-mode + ;; If not, maybe ask about starting directory and/or transcript file. + ;; If no transfile, use buffer *S* + ;; This function is primarily used to figure out the Process and + ;; buffer names to use for inferior-ess. + (run-hooks 'ess-pre-run-hook) + (let* ((dialect (eval (cdr (assoc 'ess-dialect customize-alist)) t)) + (process-environment process-environment) + ;; Use dialect if not R, R program name otherwise + (temp-dialect (if ess-use-inferior-program-in-buffer-name ;VS[23-02-2013]: FIXME: this should not be here + (if (string-equal dialect "R") + (file-name-nondirectory inferior-ess-r-program) + dialect) + dialect)) + (inf-buf (inferior-ess--get-proc-buffer-create temp-dialect)) + (proc-name (buffer-local-value 'ess-local-process-name inf-buf))) + (with-current-buffer inf-buf + ;; TODO: Get rid of this, we should rely on modes to set the + ;; variables they need. + (ess-setq-vars-local customize-alist) + (inferior-ess--set-major-mode ess-dialect) + ;; Set local variables after changing mode because they might + ;; not be permanent + (setq default-directory + (inferior-ess--maybe-prompt-startup-directory proc-name temp-dialect)) + (setq inferior-ess--local-data (cons inferior-ess-program start-args)) + ;; Read the history file + (when ess-history-file + (setq comint-input-ring-file-name + (expand-file-name (if (eql t ess-history-file) + (concat "." ess-dialect "history") + ess-history-file) + ess-history-directory)) + (comint-read-input-ring)) + ;; Show the buffer + ;; TODO: Remove inferior-ess-own-frame after ESS 19.04, then just have: + ;; (pop-to-buffer inf-buf) + (pop-to-buffer inf-buf (with-no-warnings + (when inferior-ess-own-frame + '(display-buffer-pop-up-frame)))) + (let ((proc (inferior-ess--start-process inf-buf proc-name start-args))) + (ess-make-buffer-current) + (goto-char (point-max)) + (unless no-wait + (ess-write-to-dribble-buffer "(inferior-ess: waiting for process to start (before hook)\n") + (ess-wait-for-process proc nil 0.01 t)) + (unless (and proc (eq (process-status proc) 'run)) + (error "Process %s failed to start" proc-name)) + (setq-local font-lock-fontify-region-function #'inferior-ess-fontify-region) + (setq-local ess-sl-modtime-alist nil) + (run-hooks 'ess-post-run-hook) + ;; User initialization can take some time ... + (unless no-wait + (ess-write-to-dribble-buffer "(inferior-ess): waiting for process (after hook)\n") + (ess-wait-for-process proc))) + (setq inferior-ess--last-started-process-buffer inf-buf) + inf-buf))) + +(defun inferior-ess--get-proc-buffer-create (name) + "Get a process buffer, creating a new one if needed. +This always returns a process-less buffer. The variable +`ess-local-process-name' is set in the buffer with the name of +the next process to spawn. This name may be different from the +buffer name, depending on how `ess-gen-proc-buffer-name-function' +generated the latter from NAME." + (let* ((proc-name (let ((ntry 1)) + ;; Find the next non-existent process N (*R:N*) + (while (get-process (ess-proc-name ntry name)) + (setq ntry (1+ ntry))) + (ess-proc-name ntry name))) + (inf-name (funcall ess-gen-proc-buffer-name-function proc-name))) + (let ((buf (cond + ;; Try to use current buffer, if inferior-ess-mode but + ;; no process + ((and (not (comint-check-proc (current-buffer))) + (derived-mode-p 'inferior-ess-mode)) + ;; Don't change existing buffer name in this case. It + ;; is very common to restart the process in the same + ;; buffer. + (setq proc-name ess-local-process-name) + (current-buffer)) + ;; Pick up a transcript file + (ess-ask-about-transfile + (let ((transfilename (read-file-name + "Use transcript file (default none):" nil ""))) + (if (string= transfilename "") + (get-buffer-create inf-name) + (find-file-noselect (expand-file-name transfilename))))) + ;; Create a new buffer or take the *R:N* buffer if + ;; already exists (it should contain a dead process) + (t + (get-buffer-create inf-name))))) + ;; We generated a new process name but there might still be a + ;; live process in the buffer in corner cases because of + ;; `ess-gen-proc-buffer-name-function` or if the user renames + ;; inferior buffers + (when (comint-check-proc buf) + (error "Can't start a new session in buffer `%s` because one already exists" + inf-name)) + (with-current-buffer buf + (setq-local ess-local-process-name proc-name)) + buf))) + +(defun ess--accumulation-buffer (proc) + "Return, creating if needed, the accumulation buffer for PROC." + (let ((abuf (process-get proc :accum-buffer))) + (if (buffer-live-p abuf) + abuf + (let ((abuf (get-buffer-create (format " *%s:accum*" (process-name proc))))) + (process-put proc :accum-buffer abuf) + (with-current-buffer abuf + (buffer-disable-undo) + (setq-local inhibit-modification-hooks t)) + abuf)))) + +(defvar-local inferior-ess-objects-command nil + "The language/dialect specific command for listing objects. +It is initialized from the corresponding inferior--objects-command +and then made buffer local."); and the *--* ones are customized! + +(defvar-local ess-save-lastvalue-command nil + "The command to save the last value. See S section for more details. +Default depends on the ESS language/dialect and hence made buffer local") + +(defvar-local ess-retr-lastvalue-command nil + "The command to retrieve the last value. See S section for more details. +Default depends on the ESS language/dialect and hence made buffer local") + +(defun inferior-ess-fontify-region (beg end &optional verbose) + "Fontify output by output to avoid fontification spilling over prompts. +BEG and END signify the bounds, VERBOSE gets passed to +`font-lock-default-fontify-region'." + (let* ((buffer-undo-list t) + (font-lock-dont-widen t) + (font-lock-extend-region-functions nil) + (pos1 beg) + (pos2)) + (when (< beg end) + (with-silent-modifications + ;; fontify chunks from prompt to prompt + (while (< pos1 end) + (goto-char pos1) + (comint-next-prompt 1) + (setq pos2 (min (point) end)) + (save-restriction + (narrow-to-region pos1 pos2) + (font-lock-default-fontify-region pos1 pos2 verbose)) + (setq pos1 pos2)) + ;; highlight errors + (setq compilation--parsed beg) + `(jit-lock-bounds ,beg . ,end))))) + +(defun ess-gen-proc-buffer-name:simple (proc-name) + "Function to generate buffer name by wrapping PROC-NAME in *proc-name*. +See `ess-gen-proc-buffer-name-function'." + (format "*%s*" proc-name)) + +(defun ess-gen-proc-buffer-name:directory (proc-name) + "Return a buffer name by wrapping PROC-NAME in *PROC-NAME:DIR-NAME*. +DIR-NAME is a short directory name. See +`ess-gen-proc-buffer-name-function'." + (format "*%s:%s*" proc-name (file-name-nondirectory + (directory-file-name default-directory)))) + +(defun ess-gen-proc-buffer-name:abbr-long-directory (proc-name) + "Return a buffer name in the form *PROC-NAME:ABBREVIATED-LONG-DIR-NAME*. +PROC-NAME is a string representing an internal process +name. ABBREVIATED-LONG-DIR-NAME is an abbreviated full directory +name. Abbreviation is performed by `abbreviate-file-name'. See +`ess-gen-proc-buffer-name-function'." + (format "*%s:%s*" proc-name (abbreviate-file-name default-directory))) + +(defun ess-gen-proc-buffer-name:project-or-simple (proc-name) + "Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*. +PROC-NAME is a string representing an internal process name. If +no project directory has been found use +`ess-gen-proc-buffer-name:simple'. See +`ess-gen-proc-buffer-name-function'." + (if-let ((p (project-current)) + (proj (ess--project-root p))) + (format "*%s:%s*" proc-name (file-name-nondirectory + (directory-file-name proj))) + (ess-gen-proc-buffer-name:simple proc-name))) + +(defun ess-gen-proc-buffer-name:project-or-directory (proc-name) + "Function to generate buffer name in the form *PROC-NAME:PROJECT-ROOT*. +PROC-NAME is a string representing an internal process name. +PROJECT-ROOT is directory name returned by `ess--project-root' if +defined. If no project directory has been found, use +`ess-gen-proc-buffer-name:directory'. See +`ess-gen-proc-buffer-name-function'." + (if-let ((p (project-current)) + (proj (ess--project-root p))) + (format "*%s:%s*" proc-name (file-name-nondirectory + (directory-file-name proj))) + (ess-gen-proc-buffer-name:directory proc-name))) + +;; This ensures that people who have this set in their init file don't +;; get errors about undefined functions after upgrading ESS: +(define-obsolete-function-alias 'ess-gen-proc-buffer-name:projectile-or-simple + #'ess-gen-proc-buffer-name:project-or-simple "ESS 19.04") +(define-obsolete-function-alias 'ess-gen-proc-buffer-name:projectile-or-directory + #'ess-gen-proc-buffer-name:project-or-directory "ESS 19.04") + +(defun inferior-ess-available-p (&optional proc) + "Return non-nil if PROC is not busy." + (when-let ((proc (or proc (ess-get-current-process)))) + (unless (process-get proc 'busy) + (or (ess-debug-active-p proc) ; don't send empty lines in debugger + (when-let ((last-check (process-get proc 'last-availability-check))) + (time-less-p (process-get proc 'last-eval) last-check)) + (progn + ;; Send an empty string and waiting a bit to make sure we are not busy. + (process-send-string proc "\n") + (inferior-ess-mark-as-busy proc) + (process-put proc 'availability-check t) + ;; Start with a very conservative waiting time and quickly average + ;; down to the actual response. + (let ((avresp (or (process-get proc 'average-response-time) 0.1)) + (ts (current-time))) + (when (accept-process-output proc (max 0.005 (* 2.0 avresp))) + (let ((avresp (/ (+ (* 2.0 avresp) + (float-time (time-subtract (current-time) ts))) + 3.0))) + (process-put proc 'average-response-time avresp))) + (process-put proc 'last-availability-check ts)) + (not (process-get proc 'busy))))))) + +(defun inferior-ess--set-status (proc string) + "Internal function to set the status of process PROC. +Return non-nil if the process is in a ready (not busy) state." + ;; TODO: do it in one search, use starting position, use prog1 + (let ((ready (string-match-p (concat "\\(" inferior-ess-primary-prompt "\\)\\'") string))) + (process-put proc 'busy-end? (and ready (process-get proc 'busy))) + ;; When "\n" inserted from inferior-ess-available-p, delete the prompt. + (when (and ready + (process-get proc 'availability-check) + (string-match-p (concat inferior-ess-primary-prompt "\\'") string)) + (process-put proc 'suppress-next-output? t)) + (process-put proc 'availability-check nil) + (when ready + (process-put proc 'running-async? nil)) + (process-put proc 'busy (not ready)) + (process-put proc 'sec-prompt + (when inferior-ess-secondary-prompt + (string-match (concat "\\(" inferior-ess-secondary-prompt "\\)\\'") string))) + ready)) + +(defun ess--command-delimited-output-info (buf delim) + "Detect positions of accumulated output. +Return positions after START, before END, after prompt. If any is +not found, returns nil. The last position marks the start of new +output, if any." + (with-current-buffer buf + (save-excursion + (save-match-data + (goto-char (point-min)) + (when (re-search-forward (ess--delimiter-start-re delim) nil t) + (let ((start (1+ (match-end 0)))) + (when (re-search-forward (ess--delimiter-end-re delim) nil t) + (when (not (equal (line-beginning-position) + (match-beginning 0))) + (error "Missing newline in command output")) + (let ((end (max (1- (match-beginning 0)) + start))) + (goto-char (1+ (match-end 0))) + (when (re-search-forward inferior-ess-primary-prompt nil t) + (let* ((prompt-end (match-end 0)) + (new (when (> (point-max) prompt-end) + prompt-end))) + (list start end new))))))))))) + +(defun ess--command-output-info (buf) + "Detect positions of accumulated output. +Like `ess--command-delimited-output-info' but detects prompts +without the benefit of output delimiters. This is much less +robust. This might leave parasite output at the start of BUF +(e.g. `+' prompts with multiline commands). The result might be +incomplete if the command output includes a line that ends with +`> ' and which happens to be the last characters in a partial +output (process output passed to filters is split in batches at +arbitrary locations). In that case the rest of the output will be +inserted in the process buffer instead of the command buffer." + (with-current-buffer buf + (save-excursion + (save-match-data + (goto-char (point-min)) + (when (re-search-forward (concat inferior-ess-primary-prompt + "\\(\n\\|\\'\\)") + nil t) + (goto-char (match-beginning 0)) + (let ((end (max (1- (line-beginning-position)) + (point-min))) + (new (when (> (point-max) (line-end-position)) + (1+ (line-end-position))))) + (list (point-min) end new))))))) + +;; Be careful that new output might come in after the closing +;; delimiter or prompt. This could happen when a background command is +;; interrupted asynchronously and the user has sent new inputs before +;; the process has finished interrupting. +(defun ess--command-set-status (proc buf info) + (with-current-buffer buf + (unwind-protect + (progn + (let* ((beg (nth 0 info)) + (end (nth 1 info)) + (new (nth 2 info)) + (output (buffer-substring beg end)) + (new-output (when new + (buffer-substring new (point-max))))) + ;; Delete the start delimiter and anything before it. + ;; This takes care of `+` continuation lines that occur + ;; with multi-line commands. Delete anything after the + ;; end delimiter, including the prompt and new output + (delete-region (point-min) (point-max)) + (insert output) + new-output)) + (process-put proc 'busy nil)))) + +(defun ess--delimiter-start-re (delim) + (concat "\\(" delim "-START\r*$\\)")) + +(defun ess--delimiter-end-re (delim) + (concat "\\(" delim "-END\r*\\)")) + +(defun ess--delimiter-error-start-re () + "ESSR::ERROR \\(\"\\)") + +(defun ess--delimiter-error-end-re () + "\\(\"\\)") + +(defun inferior-ess-mark-as-busy (proc) + "Put PROC's busy value to t." + (process-put proc 'busy t) + (process-put proc 'sec-prompt nil)) + +(defun inferior-ess-run-callback (proc string) + ;; callback is stored in 'callbacks proc property. Callbacks is a list that + ;; can contain either functions to be called with two arguments PROC and + ;; STRING, or cons cells of the form (func . suppress). If SUPPRESS is non-nil + ;; next process output will be suppressed. + (unless (process-get proc 'busy) + ;; only one callback is implemented for now + (let* ((cb (car (process-get proc 'callbacks))) + (listp (not (functionp cb))) + (suppress (and listp (consp cb) (cdr cb))) + (cb (if (and listp (consp cb)) + (car cb) + cb))) + (when cb + (when ess-verbose + (ess-write-to-dribble-buffer "executing callback ...\n")) + (when suppress + (process-put proc 'suppress-next-output? t)) + (process-put proc 'callbacks nil) + (condition-case-unless-debug err + (funcall cb proc string) + (error (message "%s" (error-message-string err)))))))) + +(defun ess--if-verbose-write-process-state (proc string &optional filter) + "Write information about PROC, STRING, and FILTER to the dribble buffer." + (ess-if-verbose-write + (format "\n%s: + --> busy:%s busy-end:%s sec-prompt:%s interruptable:%s <-- + --> running-async:%s callback:%s suppress-next-output:%s <-- + --> dbg-active:%s is-recover:%s <-- + --> cmd-buffer:%s cmd-output-delimiter:%s <-- + --> string:%s<--\n" + (upcase (or filter "normal-filter")) + (process-get proc 'busy) + (process-get proc 'busy-end?) + (process-get proc 'sec-prompt) + (process-get proc 'interruptable?) + (process-get proc 'running-async?) + (if (process-get proc 'callbacks) "yes") + (process-get proc 'suppress-next-output?) + (process-get proc 'dbg-active) + (process-get proc 'is-recover) + (process-get proc 'cmd-buffer) + (process-get proc 'cmd-output-delimiter) + (if (> (length string) 150) + (format "%s .... %s" (substring string 0 50) (substring string -50)) + string)))) + +(defun inferior-ess-output-filter (proc string) + "Standard output filter for the inferior ESS process PROC. +Ring Emacs bell if process output starts with an ASCII bell, and pass +the rest to `comint-output-filter'. +Taken from octave-mod.el." + (inferior-ess--set-status proc string) + (ess--if-verbose-write-process-state proc string) + (inferior-ess-run-callback proc string) + (if (process-get proc 'suppress-next-output?) + ;; works only for suppressing short output, for time being is enough (for callbacks) + (process-put proc 'suppress-next-output? nil) + (comint-output-filter proc (inferior-ess-strip-ctrl-g string)))) + +(defun inferior-ess-strip-ctrl-g (string) + "Strip leading `^G' character. +If STRING starts with a `^G', ring the Emacs bell and strip it. +Depending on the value of `visible-bell', either the frame will +flash or you'll hear a beep. Taken from octave-mod.el." + (if (string-match "^\a" string) + (progn + (ding) + (setq string (substring string 1)))) + string) + +(defun ess-process-sentinel (proc message) + "Sentinel for use with ESS processes PROC. +This marks the process with a MESSAGE, at a particular time point." + (let ((abuf (process-get proc :accum-buffer))) + (when (buffer-live-p abuf) + (kill-buffer abuf))) + (let ((pbuf (process-buffer proc))) + (when (buffer-live-p pbuf) + (with-current-buffer pbuf + (save-excursion + (setq message (substring message 0 -1)) ; strip newline + (set-buffer (process-buffer proc)) + (comint-write-input-ring) + (goto-char (point-max)) + (insert-before-markers + (format "\nProcess %s %s at %s\n" + (process-name proc) message (current-time-string)))))))) + +;; FIXME: This list is structured as '(("R:2") ("R")). It doesn't +;; appear the CDR are used. Can probably just be '("R:2" "R"). +(defvar ess-process-name-list nil + "Alist of active ESS processes.") + +(defun inferior-ess--start-process (buf proc-name switches) + "Make a comint process in buffer BUF with process PROC-NAME. +SWITCHES is passed to `comint-exec'. BUF is guaranteed to be a +process-less buffer because it was created with +`inferior-ess--get-proc-buffer-create'." + (with-current-buffer buf + (if (eq (buffer-size) 0) nil + (goto-char (point-max)) + (insert "\^L\n"))) + (let ((process-environment + (nconc + (list "STATATERM=emacs" + (format "PAGER=%s" inferior-ess-pager)) + process-environment)) + (tramp-remote-process-environment + (nconc ;; it contains a pager already, so append + (when (boundp 'tramp-remote-process-environment) + (copy-sequence tramp-remote-process-environment)) + (list "STATATERM=emacs" + (format "PAGER=%s" inferior-ess-pager))))) + (comint-exec buf + proc-name + inferior-ess-program + nil + (when switches + (split-string switches)))) + (let ((proc (get-buffer-process buf))) + ;; Set the process hooks + (set-process-sentinel proc #'ess-process-sentinel) + (set-process-filter proc #'inferior-ess-output-filter) + (inferior-ess-mark-as-busy proc) + ;; Add this process to ess-process-name-list, if needed + (let ((conselt (assoc proc-name ess-process-name-list))) + (unless conselt + (setq ess-process-name-list + (cons (cons proc-name nil) ess-process-name-list)))) + proc)) + + +;;*;; Requester functions called at startup +(defun inferior-ess--get-startup-directory () + "Return a startup directory." + (let ((dir (or (when (boundp 'ess-startup-directory) + (if (symbolp ess-startup-directory) + (symbol-value ess-startup-directory) + ess-startup-directory)) + (and ess-startup-directory-function + (funcall ess-startup-directory-function)) + (when-let ((proj (project-current))) + (ess--project-root proj)) + default-directory))) + (directory-file-name dir))) + +(defun inferior-ess--maybe-prompt-startup-directory (procname _dialect) + "Possibly prompt for a startup directory. +When `ess-ask-for-ess-directory' is non-nil, prompt. PROCNAME is +the name of the inferior process (e.g. \"R:1\"), and DIALECT is +the language dialect (e.g. \"R\")." + (let ((default-dir (inferior-ess--get-startup-directory))) + (if ess-ask-for-ess-directory + (let ((prompt (format "%s starting project directory? " procname))) + (ess-prompt-for-directory default-dir prompt)) + default-dir))) + +(defun ess-prompt-for-directory (default prompt) + "PROMPT for a directory, using DEFAULT as the usual." + (let* ((def-dir (file-name-as-directory default)) + (the-dir (expand-file-name + (file-name-as-directory + (read-directory-name prompt def-dir def-dir t nil))))) + (if (file-directory-p the-dir) nil + (error "%s is not a valid directory" the-dir)) + the-dir)) + + +;;*;; General process handling code + +(defmacro ess-with-current-buffer (buffer &rest body) + "Like `with-current-buffer' but with transfer of some essential +local ESS vars like `ess-local-process-name'." + (declare (indent 1) (debug t)) + (let ((lpn (make-symbol "lpn")) + (dialect (make-symbol "dialect")) + (alist (make-symbol "alist"))) + `(let ((,lpn ess-local-process-name) + (,dialect ess-dialect) + (,alist ess-local-customize-alist)) + (with-current-buffer ,buffer + (ess-setq-vars-local (eval ,alist t)) + (setq ess-local-process-name ,lpn) + (setq ess-dialect ,dialect) + ,@body)))) + +(dolist (mode '(emacs-lisp-mode lisp-interaction-mode)) + (font-lock-add-keywords + mode + '(("(\\(ess-with-current-buffer\\)\\s +\\(\\(\\w\\|\\s_\\)+\\)" + (1 font-lock-keyword-face) + (2 font-lock-variable-name-face))))) + +(defun ess-get-process (&optional name use-another) + "Return the ESS process named by NAME. +If USE-ANOTHER is non-nil, and the process NAME is not +running (anymore), try to connect to another if there is one. By +default (USE-ANOTHER is nil), the connection to another process +happens interactively (when possible)." + (setq name (or name ess-local-process-name)) + (cl-assert name nil "No ESS process is associated with this buffer now") + (update-ess-process-name-list) + (cond ((assoc name ess-process-name-list) + (get-process name)) + ((= 0 (length ess-process-name-list)) + (save-current-buffer + (message "trying to (re)start process %s for language %s ..." + name ess-language) + (ess-start-process-specific ess-language ess-dialect) + ;; and return the process: "call me again" + (ess-get-process name))) + ;; else: there are other running processes + (use-another ; connect to another running process : the first one + (let ((other-name (car (elt ess-process-name-list 0)))) + ;; "FIXME": try to find the process name that matches *closest* + (message "associating with *other* process '%s'" other-name) + (ess-get-process other-name))) + ((and (not noninteractive) + (y-or-n-p + (format "Process %s is not running, but others are. Switch? " name))) + (ess-force-buffer-current (concat ess-dialect " process to use: ") 'force) + (ess-get-process ess-current-process-name)) + (t (error "Process %s is not running" name)))) + +(defun inferior-ess-default-directory () + "Return the `default-directory' of the process." + (ess-get-process-variable 'default-directory)) + +;;--- Unfinished idea (ESS-help / R-help ) -- probably not worth it... +;;- (defun ess-set-inferior-program (filename) +;;- "Allows to set or change `inferior-ess-program', the program (file)name." +;;- (interactive "fR executable (script) file: ") +;;- ;; "f" : existing file {file name completion} ! +;;- (setq inferior-ess-program filename)) +;; the inferior-ess-program is initialized in the customize..alist, +;; e.g. from inferior-ess-r-program ... --> should change rather these. +;; However these really depend on the current ess-language! +;; Plan: 1) must know and use ess-language +;; 2) change the appropriate inferior--program +;; (how?) in R/S : assign(paste("inferior-",ESSlang,"-p...."), filename)) + + +;;*;; Multiple process handling code + +;; FIXME: It seems the only effect of this function is to remove dead +;; processes from `ess-process-name-list'. Am I missing something? +(defun ess-make-buffer-current nil + "Make the process associated with the current buffer the current ESS process. +Returns the name of the process, or nil if the current buffer has none." + (update-ess-process-name-list) + ;; (if ess-local-process-name + ;; (setq ess-current-process-name ess-local-process-name)) + ess-local-process-name) + +(defun ess-get-process-variable (var) + "Return the variable VAR (symbol) local to ESS process called NAME (string)." + (buffer-local-value var (process-buffer (ess-get-process ess-local-process-name)))) + +(defun ess-set-process-variable (var val) + "Set variable VAR (symbol) local to ESS process called NAME (string) to VAL." + (with-current-buffer (process-buffer (ess-get-process ess-local-process-name)) + (set var val))) + +(defun ess-process-live-p (&optional proc) + "Check if the local ess process is alive. +Return nil if current buffer has no associated process, or +process was killed. PROC defaults to `ess-local-process-name'" + (when-let ((proc (or proc (ess-get-current-process)))) + (process-live-p proc))) + +(defun ess-process-get (propname &optional proc) + "Return the variable PROPNAME (symbol) of the current ESS process. +PROC defaults to process with name `ess-local-process-name'." + (process-get (or proc (get-process ess-local-process-name)) propname)) + +(defun ess-process-put (propname value &optional proc) + "Set the variable PROPNAME (symbol) to VALUE in the current ESS process. +PROC defaults to the process given by `ess-local-process-name'" + (process-put (or proc (get-process ess-local-process-name)) propname value)) + +(defun ess-start-process-specific (language dialect) + "Start an ESS process. +Typically from a language-specific buffer, using DIALECT. +LANGUAGE is ignored." + (save-current-buffer + (let ((dsymb (intern dialect))) + (if (fboundp dsymb) + (funcall dsymb) + (error "No ESS processes running; not yet implemented to start (%s,%s)" + language dialect))))) + +(defmacro ess--with-no-pop-to-buffer (&rest body) + "Disable some effects of `pop-to-buffer'. +Prevent `display-buffer' from performing an action and save the +current buffer to prevent `pop-to-buffer' from setting a new +current buffer." + ;; `pop-to-buffer' might still raise windows and frames so it may be + ;; better to have our own configurable `ess--pop-to-buffer' wrapper. + (declare (indent 0) + (debug (&rest form))) + `(let ((display-buffer-overriding-action '(display-buffer-no-window (allow-no-window . t)))) + (save-current-buffer + ,@body))) + +(defun ess-request-a-process (message &optional noswitch ask-if-1) + "Ask for a process, and make it the current ESS process. +If there is exactly one process, only ask if ASK-IF-1 is non-nil. +Also switches to the process buffer unless NOSWITCH is non-nil. +Interactively, NOSWITCH can be set by giving a prefix argument. +Returns the name of the selected process. MESSAGE may get passed +to `ess-completing-read'." + (interactive (list "Switch to which ESS process? " current-prefix-arg)) + (update-ess-process-name-list) + (let* ((ess-dialect (or ess-dialect + (ess-completing-read + "Set `ess-dialect'" + (delete-dups (list "R" "S+" (or (bound-and-true-p S+-dialect-name) "S+") + "stata" (or (bound-and-true-p STA-dialect-name) "stata") + "julia" "SAS"))))) + (pname-list (delq nil ;; keep only those matching dialect + (append + (mapcar (lambda (lproc) + (and (equal ess-dialect + (buffer-local-value + 'ess-dialect + (process-buffer (get-process (car lproc))))) + (not (equal ess-local-process-name (car lproc))) + (car lproc))) + ess-process-name-list) + ;; append local only if running + (when (assoc ess-local-process-name ess-process-name-list) + (list ess-local-process-name))))) + (num-processes (length pname-list)) + proc auto-started?) + (when (or (= 0 num-processes) + (and (= 1 num-processes) + (not (equal ess-dialect ;; don't auto connect if from different dialect + (buffer-local-value + 'ess-dialect + (process-buffer (get-process + (car pname-list)))))))) + ;; Try to start "the appropriate" process, don't show the buffer + ;; since we handle that explicitly with no-switch + (ess-if-verbose-write + "ess-request-a-process: Can't find a process, starting a new one\n") + (ess--with-no-pop-to-buffer + (ess-start-process-specific ess-language ess-dialect)) + (setq num-processes 1 + pname-list (car ess-process-name-list) + auto-started? t)) + ;; now num-processes >= 1 : + (let* ((proc-buffers (mapcar (lambda (lproc) + (buffer-name (process-buffer (get-process lproc)))) + pname-list))) + (setq proc + (if (or auto-started? + (and (not ask-if-1) + (= 1 num-processes) + (message "Using process `%s'" (car proc-buffers)))) + (car pname-list) + (unless (and ess-current-process-name + (get-process ess-current-process-name)) + (setq ess-current-process-name nil)) + ;; ask for buffer name not the *real* process name: + (let ((buf (ess-completing-read message (append proc-buffers (list "*new*")) nil t nil nil))) + (if (not (equal buf "*new*")) + (process-name (get-buffer-process buf)) + ;; Prevent new process buffer from being popped + ;; because we handle display depending on the value + ;; of `no-switch` + (ess-if-verbose-write + "ess-request-a-process: User requested a new process\n") + (ess--with-no-pop-to-buffer + (ess-start-process-specific ess-language ess-dialect)) + (caar ess-process-name-list)))))) + ;; Always display buffer if auto-started but do not select it if + ;; NOSWITCH is set + (when (or auto-started? (not noswitch)) + (let ((proc-buf (ess-get-process-buffer proc))) + (if noswitch + (display-buffer proc-buf) + (pop-to-buffer proc-buf)) + ;; If inferior startup has already finished, set screen + ;; options again in case the post-run hook ran before a new + ;; screen config was created by `pop-to-buffer' (#1243). + (with-current-buffer proc-buf + (ess--execute-screen-options-bg)))) + proc)) + +(defun ess-force-buffer-current (&optional prompt force no-autostart ask-if-1) + "Make sure the current buffer is attached to an ESS process. +If not, or FORCE (prefix argument) is non-nil, prompt for a +process name with PROMPT. If NO-AUTOSTART is nil starts the new +process if process associated with current buffer has +died. `ess-local-process-name' is set to the name of the process +selected. `ess-dialect' is set to the dialect associated with +the process selected. ASK-IF-1 asks user for the process, even if +there is only one process running. Returns the inferior buffer if +it was successfully forced, throws an error otherwise." + (interactive + (list (concat ess-dialect " process to use: ") current-prefix-arg nil)) + (let ((proc-name (ess-make-buffer-current))) + (cond ((and (not force) proc-name (get-process proc-name))) + ;; Make sure the source buffer is attached to a process + ((and ess-local-process-name (not force) no-autostart) + (error "Process %s has died" ess-local-process-name)) + ;; Request a process if `ess-local-process-name' is nil + (t + (let* ((prompt (or prompt "Process to use: ")) + (proc (ess-request-a-process prompt 'no-switch ask-if-1))) + (setq ess-local-process-name proc))))) + (process-buffer (get-process ess-local-process-name))) + +(defalias 'inferior-ess-force #'ess-force-buffer-current) + +(defun ess-switch-process () + "Force a switch to a new underlying process." + (interactive) + (ess-force-buffer-current "Process to use: " 'force nil 'ask-if-1)) + +(defun ess-get-current-process () + (when ess-local-process-name + (get-process ess-local-process-name))) + +(defun ess-get-current-process-buffer () + (when-let ((proc (ess-get-current-process))) + (process-buffer proc))) + +(defun ess-get-next-available-process (&optional dialect ignore-busy background) + "Return first available (aka not busy) process of dialect DIALECT. +DIALECT defaults to the local value of ess-dialect. Return nil if +no such process has been found. If BACKGROUND is non-nil, only +processes that are allowed to evaluate in the background are +matched." + (setq dialect (or dialect ess-dialect)) + (when (and dialect (or (not background) + ess-can-eval-in-background)) + (let (proc) + (catch 'found + (dolist (p (cons ess-local-process-name + (mapcar #'car ess-process-name-list))) + (when p + (setq proc (get-process p)) + (when (and proc + (process-live-p proc) + (equal dialect + (buffer-local-value 'ess-dialect (process-buffer proc))) + ;; Check that we can evaluate in background + ;; before checking for availability to + ;; avoid issues with newline handshakes + (or (not background) + (ess-can-eval-in-background proc)) + (or ignore-busy + (inferior-ess-available-p proc))) + (throw 'found proc)))))))) + +(defun ess-get-next-available-bg-process (&optional proc dialect ignore-busy) + "Returns first avaiable process only if background evaluations are allowed. +Same as `ess-get-next-available-process' but checks for +`ess-can-eval-in-background'." + (if proc + (ess-can-eval-in-background proc) + (ess-get-next-available-process dialect ignore-busy 'background))) + + +;;*;;; Commands for switching to the process buffer + +(defun ess-switch-to-ESS (eob-p) + "Switch to the current inferior ESS process buffer. +With (prefix) EOB-P non-nil, positions cursor at end of buffer." + (interactive "P") + (ess-force-buffer-current) + (pop-to-buffer (buffer-name (process-buffer (get-process ess-current-process-name))) + '(nil . ((inhibit-same-window . t)))) + (when eob-p (goto-char (point-max)))) + +(defun ess-switch-to-end-of-ESS () + "Switch to the end of the inferior ESS process buffer." + (interactive) + (ess-switch-to-ESS t)) + +(defun ess-switch-to-inferior-or-script-buffer (toggle-eob) + "Switch between script and process buffer. +This is a single-key command. Assuming that it is bound to C-c +C-z, you can navigate back and forth between iESS and script +buffer with C-c C-z C-z C-z ... If variable +`ess-switch-to-end-of-proc-buffer' is t (the default) this +function switches to the end of process buffer. If TOGGLE-EOB is +given, the value of `ess-switch-to-end-of-proc-buffer' is +toggled." + (interactive "P") + (let ((eob (if toggle-eob + (not ess-switch-to-end-of-proc-buffer) + ess-switch-to-end-of-proc-buffer))) + (if (derived-mode-p 'inferior-ess-mode) + (let ((dialect ess-dialect) + (proc-name ess-local-process-name) + (blist (buffer-list))) + (while (and (pop blist) + (with-current-buffer (car blist) + (not (or (and (ess-derived-mode-p) + (equal dialect ess-dialect) + (null ess-local-process-name)) + (and (ess-derived-mode-p) + (equal proc-name ess-local-process-name))))))) + (if blist + (pop-to-buffer (car blist)) + (message "Found no buffers for `ess-dialect' %s associated with process %s" + dialect proc-name))) + (ess-switch-to-ESS eob)) + (when (called-interactively-p 'any) + (set-transient-map (let ((map (make-sparse-keymap)) + (key (vector last-command-event))) + (define-key map key #'ess-switch-to-inferior-or-script-buffer) map))))) + + +(defun ess-get-process-buffer (&optional name) + "Return the buffer associated with the ESS process named by NAME." + (process-buffer (ess-get-process (or name ess-local-process-name)))) + +(defun update-ess-process-name-list () + "Remove names with no process." + (let (defunct) + (dolist (conselt ess-process-name-list) + (let ((proc (get-process (car conselt)))) + (unless (and proc (eq (process-status proc) 'run)) + (push conselt defunct)))) + (dolist (pointer defunct) + (setq ess-process-name-list (delq pointer ess-process-name-list)))) + (if (eq (length ess-process-name-list) 0) + (setq ess-current-process-name nil))) + + +;;; Functions for evaluating code + +;;*;; Utils for evaluation + +(defun ess-build-eval-command (string &optional visibly output file &rest args) + "Format an evaluation command. +Wrap STRING with `ess-quote-special-chars' and dispatch on +`ess-build-eval-command--override'." + (setq string (ess-quote-special-chars string)) + (ess-build-eval-command--override string visibly output file args)) + +(cl-defgeneric ess-build-eval-command--override + (string &optional _visibly _output file &rest _args) + "Default method to build eval command." + (and ess-eval-command + (format-spec ess-eval-command + `((?s . ,string) + (?f . ,file))))) + +(cl-defgeneric ess-build-load-command (file &optional _visibly _output &rest _args) + "Format a loading command. +Dispatches on the dialect-specific `ess-build-load-command' +and `ess-load-command', in that order." + (and ess-load-command + (format ess-load-command file))) + +(defun ess-wait-for-process (&optional proc sec-prompt wait force-redisplay timeout) + "Wait for \\='busy property of the process to become nil. +If SEC-PROMPT is non-nil return if secondary prompt is detected +regardless of whether primary prompt was detected or not. If WAIT +is non-nil wait for WAIT seconds for process output before the +prompt check, default 0.002s. When FORCE-REDISPLAY is non-nil +force redisplay. You better use WAIT >= 0.1 if you need +FORCE-REDISPLAY to avoid excessive redisplay. If TIMEOUT is +non-nil stop waiting for output after TIMEOUT seconds. + +Returns nil if TIMEOUT was reached, non-nil otherwise." + (setq proc (or proc (get-process ess-local-process-name))) + (setq wait (or wait 0.005)) + (setq timeout (or timeout most-positive-fixnum)) + (let ((start-time (float-time)) + (elapsed 0)) + (save-excursion + (while (and + (or (eq (process-status proc) 'run) + (progn + (when (process-buffer proc) + (display-buffer (process-buffer proc))) + (error "ESS process has died unexpectedly"))) + (< elapsed timeout) + (or (accept-process-output proc wait) + (unless (and sec-prompt (process-get proc 'sec-prompt)) + (process-get proc 'busy)))) + (when force-redisplay + (redisplay 'force)) + (setq elapsed (- (float-time) start-time)) + (when (> elapsed .3) + (setq wait .3)))) + (< elapsed timeout))) + +;; This filter is active under `ess-command` +(defun inferior-ess-ordinary-filter (proc string) + (ess--if-verbose-write-process-state proc string "ordinary-filter") + (let* ((cmd-buf (process-get proc 'cmd-buffer)) + (cmd-delim (process-get proc 'cmd-output-delimiter))) + (when (buffer-live-p cmd-buf) + (ess--exit-protect + (progn + (with-current-buffer cmd-buf + (goto-char (point-max)) + (insert string)) + (if-let ((info (if cmd-delim + (ess--command-delimited-output-info cmd-buf cmd-delim) + (ess--command-output-info cmd-buf)))) + (let ((new-output (ess--command-set-status proc cmd-buf info))) + (ess-if-verbose-write + "ess-command (filter): Found prompt\n") + (when (not (process-get proc 'busy)) + ;; Store new output until restoration + (when new-output + (process-put proc 'pending-output new-output)) + ;; Restore the user's process filter as soon as process is + ;; available + (funcall (process-get proc 'cmd-restore-function)) + ;; Run callback with command output + (when (process-get proc 'callbacks) + (inferior-ess-run-callback proc (with-current-buffer cmd-buf + (buffer-string)))))) + (ess-if-verbose-write + "ess-command (filter): Accumulating output\n"))) + ;; Be defensive when something goes wrong. Restore process to a + ;; usable state. + (ess-if-verbose-write + "ess-command (filter): Early exit\n") + (process-put proc 'busy nil) + (funcall (process-get proc 'cmd-restore-function)))))) + +(defvar ess-presend-filter-functions nil + "List of functions to call before sending the input string to the process. +Each function gets one argument, a string containing the text to +be send to the subprocess. It should return the string sent, +perhaps the same string that was received, or perhaps a modified +or transformed string. + +The functions on the list are called sequentially, and each one +is given the string returned by the previous one. The string +returned by the last function is the text that is actually sent +to the process. You can use `add-hook' to add functions to this +list either globally or locally. The hook is executed in current +buffer. Before execution, the local value of this hook in the +process buffer is appended to the hook from the current buffer.") + +(defvar ess--inhibit-presend-hooks nil + "If non-nil don't run presend hooks.") + +(defun ess--run-presend-hooks (process string) + ;; run ess-presend-filter-functions and comint-input-filter-functions + (if ess--inhibit-presend-hooks + string + ;;return modified string + (let* ((pbuf (process-buffer process)) + ;; also run proc buffer local hooks + (functions (unless (eq pbuf (current-buffer)) + (buffer-local-value 'ess-presend-filter-functions pbuf)))) + (setq functions (append (delq t (copy-sequence functions)) ;; even in let, delq destructs + ess-presend-filter-functions)) + (while (and functions string) + ;; cannot use run-hook-with-args here because string must be passed from one + ;; function to another + (if (eq (car functions) t) + (let ((functions + (default-value 'ess-presend-filter-functions))) + (while (and functions string) + (setq string (funcall (car functions) string)) + (setq functions (cdr functions)))) + (setq string (funcall (car functions) string))) + (setq functions (cdr functions))) + (with-current-buffer pbuf + (run-hook-with-args 'comint-input-filter-functions string)) + string))) + +(defun ess--concat-new-line-maybe (string) + "Append \\n at the end of STRING if missing." + (if (string-match "\n\\'" string (max (- (length string) 2) 0)) + string + (concat string "\n"))) + +(defvar ess--dbg-del-empty-p t + "Internal variable to control removal of empty lines during the debugging. +Let-bind it to nil before calling `ess-send-string' or +`ess-send-region' if no removal is necessary.") + +(defun inferior-ess--interrupt-subjob-maybe (proc) + "Internal. Interrupt the process if interruptable? process variable is non-nil. +Hide all the junk output in temporary buffer." + (when (process-get proc 'interruptable?) + (let ((cb (cadr (process-get proc 'callbacks))) + (buf (get-buffer-create " *ess-temp-buff*")) + (old-filter (process-filter proc)) + (old-buff (process-buffer proc))) + (unwind-protect + (progn + (ess-if-verbose-write "interrupting subjob ... start") + (process-put proc 'interruptable? nil) + (process-put proc 'callbacks nil) + (process-put proc 'running-async? nil) + ;; this is to avoid putting junk in user's buffer on process + ;; interruption + (set-process-buffer proc buf) + (set-process-filter proc #'inferior-ess-ordinary-filter) + (interrupt-process proc) + (when cb + (ess-if-verbose-write "executing interruption callback ... ") + (funcall cb proc)) + ;; should be very fast as it inputs only the prompt + (ess-wait-for-process proc) + (ess-if-verbose-write "interrupting subjob ... finished") + ) + (set-process-buffer proc old-buff) + (set-process-filter proc old-filter))))) + + +;;*;; Evaluation primitives + +(defun ess-send-string (process string &optional visibly message _type) + "ESS wrapper for `process-send-string'. +Run `comint-input-filter-functions' and current buffer's and +PROCESS' `ess-presend-filter-functions' hooks on the input +STRING. VISIBLY can be nil, t, \\='nowait or a string. If string +the behavior is as with \\='nowait with the differences that +inserted string is VISIBLY instead of STRING (evaluated command +is still STRING). In all other cases the behavior is as +described in `ess-eval-visibly'. STRING need not end with +\\n. TYPE is a symbol indicating type of the string. +MESSAGE is a message to display." + ;; No support of `visibly' when there's no secondary prompt + (let ((visibly (if (and (eq visibly t) + (null inferior-ess-secondary-prompt)) + 'nowait + visibly)) + (string (ess--run-presend-hooks process string))) + (inferior-ess--interrupt-subjob-maybe process) + (inferior-ess-mark-as-busy process) + (process-put process 'last-eval (current-time)) + (cond + ;; Wait after each line + ((eq visibly t) + (let ((ess--inhibit-presend-hooks t)) + (ess-eval-linewise string))) + ;; Insert command and eval invisibly + ((or (stringp visibly) + (eq visibly 'nowait)) + (with-current-buffer (process-buffer process) + (save-excursion + (goto-char (process-mark process)) + (insert-before-markers + (propertize (format "%s\n" + (replace-regexp-in-string + "\n" "\n+ " + (if (stringp visibly) visibly string))) + 'font-lock-face 'comint-highlight-input))) + (process-send-string process (ess--concat-new-line-maybe string)))) + (t + (process-send-string process (ess--concat-new-line-maybe string)))) + (when message + (message "%s" message)))) + +(defun ess-send-region (process start end &optional visibly message type) + "Low level ESS version of `process-send-region'. +If VISIBLY call `ess-eval-linewise', else call +`ess-send-string'. If MESSAGE is supplied, display it at the +end. Run current buffer's and PROCESS' +`ess-presend-filter-functions' hooks. TYPE is a symbol indicating +type of the region." + (cond + ((ess-tracebug-p) + (ess-tracebug-send-region process start end visibly message type)) + (t (ess-send-region--override process start end visibly message type)))) + +(cl-defgeneric ess-send-region--override (process start end visibly message type) + (ess-send-string process (buffer-substring start end) visibly message type)) + + +;;*;; Evaluation commands + +(defun ess-load-file--normalise-file (file) + "Handle Tramp and system peculiarities." + (require 'tramp) + (let* ((file (if (tramp-tramp-file-p file) + (tramp-file-name-localname (tramp-dissect-file-name file)) + file)) + (file (if ess-microsoft-p + (ess-replace-in-string file "[\\]" "/") + file))) + (abbreviate-file-name file))) + +(defun ess-load-file--normalise-buffer (file) + (when (ess-save-file file) + (error "Buffer %s has not been saved" (buffer-name file))) + (let ((source-buffer (get-file-buffer file))) + (if source-buffer + (with-current-buffer source-buffer + (when (buffer-modified-p) (save-buffer)) + (ess-force-buffer-current "Process to load into: ")) + (ess-force-buffer-current "Process to load into: ")))) + +;;;###autoload +(defun ess-load-file (&optional filename) + "Load FILENAME into an inferior ESS process. +This handles Tramp when working on a remote." + (interactive (list (or (and (ess-derived-mode-p) + (buffer-file-name)) + (expand-file-name + (read-file-name "Load source file: " nil nil t))))) + (ess-load-file--normalise-buffer filename) + (setq filename (ess-load-file--normalise-file filename)) + (ess-load-file--override filename) + (message "Loaded %s" filename)) + +(cl-defgeneric ess-load-file--override (filename) + (let ((command (ess-build-load-command filename nil t))) + (ess-send-string (ess-get-process) command t))) + +;; ;;; VS[03-09-2012]: Test Cases: +;; (ess-command "a<-0\n" nil nil nil nil (get-process "R")) +;; (ess-async-command-delayed "Sys.sleep(5);a<-a+1;cat(1:10)\n" nil +;; (get-process "R") (lambda (proc) (message "done"))) +;; (ess-async-command-delayed "Sys.sleep(5)\n" nil (get-process "R") +;; (lambda (proc) (message "done"))) +;; (process-get (get-process "R") 'running-async?) + +(defun ess-command--get-proc (proc no-prompt-check) + (if proc + (unless ess-local-process-name + (setq ess-local-process-name (process-name proc))) + (setq proc (ess-get-process ess-local-process-name))) + (unless no-prompt-check + (when (process-get proc 'busy) + (user-error "ESS process not ready. Finish your command before trying again"))) + proc) + +(defvar inferior-ess--output-delimiter-count 0) +(defun inferior-ess--output-delimiter () + (setq inferior-ess--output-delimiter-count (1+ inferior-ess--output-delimiter-count)) + (format "ess-output-delimiter%s" inferior-ess--output-delimiter-count)) + +(defvar ess--command-default-timeout most-positive-fixnum) + +;; NOTE: We might want to switch to something like `cl-defun' with +;; keyword arguments given the length of the signature. Would also +;; make it easier to deprecate arguments. +(defun ess-command (cmd &optional out-buffer _sleep no-prompt-check wait proc + force-redisplay timeout) + "Send the ESS process CMD and delete the output from the ESS process buffer. +If an optional second argument OUT-BUFFER exists save the output +in that buffer. OUT-BUFFER is erased before use. CMD should have +a terminating newline. Guarantees that the value of `.Last.value' +will be preserved. + +`ess-command' is executes CMD in the background synchronously, +meaning that the Emacs UI blocks while CMD is running. Make sure +that CMD returns immediately. Blocking the UI for more than 0.1 +seconds should generally be considered a bug. + +SLEEP is deprecated and no longer has any effect. WAIT, +FORCE-REDISPLAY, and TIMEOUT are as in `ess-wait-for-process' and +are passed to `ess-wait-for-process'. The default timeout is 30 +seconds. The process is interrupted with `interrupt-process' when +the timeout is reached or when an error occurs. + +PROC should be a process, if nil the process name is taken from +`ess-local-process-name'. This command doesn't set \\='last-eval +process variable. + +Note: for critical, or error prone code you should consider +wrapping the code into: + + local({ + olderr <- options(error=NULL) + on.exit(options(olderr)) + ... + })" + (let ((out-buffer (or out-buffer (get-buffer-create " *ess-command-output*"))) + (proc (ess-command--get-proc proc no-prompt-check)) + (delim (inferior-ess--output-delimiter)) + (timeout (or timeout ess--command-default-timeout))) + (with-current-buffer (process-buffer proc) + (let* ((proc-forward-alist (ess--alist (ess-local-process-name + inferior-ess-primary-prompt))) + (format-command-alist (ess-process-get 'format-command-alist)) + (use-delimiter (alist-get 'use-delimiter format-command-alist)) + (rich-cmd (if-let ((cmd-fun (alist-get 'fun format-command-alist))) + (funcall cmd-fun + (ess--strip-final-newlines cmd) + (cons 'output-delimiter delim)) + cmd)) + (early-exit t)) + (ess-if-verbose-write (format "(ess-command '%s' ..)\n" cmd)) + ;; Swap the process buffer with the output buffer before + ;; sending the command + (unwind-protect + (condition-case err + (progn + ;; The process is restored from the filter once it's + ;; available again (i.e. a prompt or delimiter is + ;; detected). This handles the synchronous case when the + ;; command runs to completion, as well as the + ;; asynchronous case when an early exit occurs. The most + ;; common cause of early exits are interrupts sent by + ;; Emacs when the user types (see `when-no-input'). In + ;; these cases we forward the interrupt to the process + ;; and return to the caller right away. We can't restore + ;; synchronously after an interrupt because the output + ;; of the background command would spill into the + ;; process buffer of the user when the process doesn't + ;; interrupt in time. + (process-put proc 'cmd-restore-function + (ess--command-make-restore-function proc)) + (when use-delimiter + (process-put proc 'cmd-output-delimiter delim)) + (process-put proc 'cmd-buffer out-buffer) + (set-process-filter proc #'inferior-ess-ordinary-filter) + (with-current-buffer out-buffer + (ess-setq-vars-local proc-forward-alist) + (setq buffer-read-only nil) + (erase-buffer) + (inferior-ess-mark-as-busy proc) + (process-send-string proc rich-cmd) + ;; Need time for ess-create-object-name-db on PC + (if no-prompt-check + (sleep-for 0.02) ; 0.1 is noticeable! + (unless (ess-wait-for-process proc nil wait force-redisplay timeout) + (error "Timeout during background ESS command `%s'" + (ess--strip-final-newlines cmd)))) + (setq early-exit nil))) + (error (setq early-exit err)) + (quit (setq early-exit err))) + (if early-exit + (ess--command-error-handler proc out-buffer use-delimiter delim early-exit) + (with-current-buffer out-buffer + (goto-char (point-min)) + (when (re-search-forward (ess--delimiter-error-start-re) nil t) + (let ((start (1+ (match-beginning 1)))) + (when (re-search-forward (ess--delimiter-error-end-re) nil t) + (let ((end (match-beginning 1))) + (error "R error during background ESS command `%s'\nError: %s" + (ess--strip-final-newlines cmd) + (buffer-substring start end))))))))))) + out-buffer)) + +(defun ess--command-error-handler (proc + out-buffer + use-delimiter + delim + early-exit) + (let ((inhibit-quit t)) + ;; In case of early exit send an interrupt to the + ;; process to abort the command + (with-current-buffer out-buffer + (goto-char (point-min)) + (when (and use-delimiter + (not (re-search-forward (ess--delimiter-start-re delim) nil t))) + ;; CMD probably failed to parse if the start delimiter + ;; can't be found in the output. Disable the delimiter + ;; before interrupt to avoid a freeze. + (ess-write-to-dribble-buffer + "Disabling output delimiter because CMD failed to parse\n") + (process-put proc 'cmd-output-delimiter nil)) + (goto-char (point-max)) + (ess--interrupt proc))) + ;; Can be `t` when early exit is caused e.g. by a throw instead of + ;; an error or a quit. This happens in tests and within + ;; `while-no-input'. + (unless (eq early-exit t) + (when (and (eq (car early-exit) 'quit) + (y-or-n-p (concat "Background background command interrupted with a user quit.\n" + "Would you like to disable background evaluations in this process?"))) + (process-put proc 'bg-eval-disabled t)) + (signal (car early-exit) (cdr early-exit)))) + +;; (ess-process-get 'ess-format-command-alist) +;; "Alist of mode-specific parameters for formatting a command. +;; All elements are optional. +;; +;; - `fun': A formatting function for running a command. First +;; argument is the background command to run. Must include a +;; catch-all `&rest` parameter for extensibility. +;; +;; - `use-delimiter' : Whether to wait for an output sentinel. If +;; non-nil, `fun' should get the `cmd-output-delimiter' element of the +;; alist of parameters and ensure the sentinel is written to the +;; process output at the end of the command." + +(defun ess--command-make-restore-function (proc) + (let ((old-pf (process-filter proc))) + (lambda () + (set-process-filter proc old-pf) + (process-put proc 'cmd-output-delimiter nil) + (process-put proc 'cmd-buffer nil) + (when-let ((pending (process-get proc 'pending-output))) + (process-put proc 'pending-output nil) + (funcall old-pf proc pending))))) + +;; TODO: Needs some Julia tests as well +(defun ess--foreground-command (cmd &optional out-buffer _sleep no-prompt-check wait proc) + "Same as `ess-command' but does not timeout. +Currently blocks the Emacs UI. Eventually it would make sense to +lock the inferior to prevent interactions and use +`ess-async-command' with a callback." + (let ((timeout most-positive-fixnum)) + (ess-command cmd out-buffer nil no-prompt-check wait proc nil timeout))) + +(defun ess-boolean-command (com &optional buf wait) + "Like `ess-command' but expects COM to print TRUE or FALSE. +If TRUE (or true) is found return non-nil otherwise nil. +Example (ess-boolean-command \"2>1\n\")" + (with-current-buffer (ess-command com buf nil nil wait) + (goto-char (point-min)) + (let ((case-fold-search t)) + (re-search-forward "true" nil t)))) + +(defun ess-string-command (com &optional buf wait) + "Returns the output of COM as a string." + (with-current-buffer (ess-command com buf nil nil wait) + (buffer-substring (point-min) (point-max)))) + +(defun ess-async-command (com &optional buf proc callback interrupt-callback) + "Asynchronous version of `ess-command'. +COM, BUF, WAIT and PROC are as in `ess-command'. + +CALLBACK is a function of two arguments (PROC STRING) to run +after the successful execution. When INTERRUPT-CALLBACK is +non-nil, user evaluation can interrupt the +job. INTERRUPT-CALLBACK should be either t or a function of one +argument (PROC) to be called on interruption. + +NOTE: Currently this function should be used only for background +jobs like caching. ESS tries to suppress any output from the +asynchronous command, but long output of COM will most likely end +up in user's main buffer." + (setq proc (or proc (get-process ess-local-process-name))) + (cond ((not (and proc (eq (process-status proc) 'run))) + (error "Process %s is dead" proc)) + ((process-get proc 'busy) + (error "Process %s is busy" proc)) + ((process-get proc 'running-async?) + (error "Process %s is already running an async command" proc))) + (when (eq interrupt-callback t) + (setq interrupt-callback (lambda (_proc)))) + (process-put proc 'callbacks (list (cons callback 'suppress-output) + interrupt-callback)) + (process-put proc 'interruptable? (and interrupt-callback t)) + (process-put proc 'running-async? t) + (ess-command com buf nil 'no-prompt-check .01 proc)) + +(defun ess-async-command-delayed (com buf proc &optional callback delay) + "Delayed asynchronous ess-command. +COM and BUF are as in `ess-command'. DELAY is a number of idle +seconds to wait before starting the execution of the COM. On +interruption (by user's evaluation) ESS tries to rerun the job +after next DELAY seconds, and the whole process repeats itself +until the command manages to run completely. DELAY defaults to +`ess-idle-timer-interval' + 3 seconds. You should always provide +PROC for delayed evaluation, as the current process might change, +leading to unpredictable consequences. This function is a wrapper +of `ess-async-command' with an explicit interrupt-callback." + (let* ((delay (or delay + (+ ess-idle-timer-interval 3))) + (int-cb `(lambda (proc) + (ess-async-command-delayed ,com ,buf proc ,callback ,delay))) + (com-fun `(lambda () + (when (eq (process-status ,proc) 'run) ; do nothing if not running + (if (or (process-get ,proc 'busy) ; if busy, try later + (process-get ,proc 'running-async?)) + ;; idle timer doesn't work here + (run-with-timer ,delay nil 'ess-async-command-delayed + ,com ,buf ,proc ,callback ,delay)) + (ess-async-command ,com ,buf ,proc ,callback ',int-cb))))) + (run-with-idle-timer delay nil com-fun))) + +(defun ess-load-library () + "Prompt and load dialect specific library/package/module. +Note that in R these are called `packages' and the name of this +function has nothing to do with R package mechanism, but it +rather serves a generic, dialect independent purpose. It is also +similar to `load-library' Emacs function." + (interactive) + (let ((ess-eval-visibly-p t) + (packs (ess-installed-packages)) + pack) + (setq pack (ess-completing-read "Load" packs)) + (ess-load-library--override pack) + (ess--mark-search-list-as-changed))) + +(cl-defgeneric ess-installed-packages () + "Return a list of installed packages.") + +(cl-defgeneric ess-load-library--override (pack) + "Load library/package PACK.") + + +;;*;; Evaluating lines, paragraphs, regions, and buffers. + +(defun ess-eval-linewise (text &optional invisibly eob even-empty + wait-last-prompt sleep-sec wait-sec) + "Evaluate TEXT in the ESS process buffer as if typed in w/o tabs. +Waits for prompt after each line of input, so won't break on large texts. + +If optional second arg INVISIBLY is non-nil, don't echo commands. +If it is a string, just include that string. If optional third +arg EOB is non-nil, display ESS process buffer after evaluation. +If optional 4th arg EVEN-EMPTY is non-nil, also send empty +text (e.g. an empty line). If 5th arg WAIT-LAST-PROMPT is +non-nil, also wait for the prompt after the last line; if 6th arg +SLEEP-SEC is a number, ESS will call `(\\[sleep-for] SLEEP-SEC)' +at the end of this function. If the 7th arg WAIT-SEC is set, it +will be used instead of the default .001s and be passed to +\\[ess-wait-for-process]. + +Run `comint-input-filter-functions' and +`ess-presend-filter-functions' of the associated PROCESS on the +TEXT." + (ess-force-buffer-current "Process to use: ") + ;; Use this to evaluate some code, but don't wait for output. + (let* ((deactivate-mark) ; keep local {do *not* deactivate wrongly} + (inf-proc (ess-get-process ess-current-process-name)) + (inf-buf (process-buffer inf-proc)) + (win (get-buffer-window inf-buf t))) + (setq text (ess--concat-new-line-maybe + (ess--run-presend-hooks inf-proc text))) + (with-current-buffer inf-buf + (setq text (propertize text 'field 'input 'front-sticky t)) + (goto-char (marker-position (process-mark inf-proc))) + (when (stringp invisibly) + (insert-before-markers (concat "*** " invisibly " ***\n"))) + ;; dbg: + ;; dbg (ess-write-to-dribble-buffer + ;; dbg (format "(eval-visibly 2): text[%d]= '%s'\n" (length text) text)) + (while (or (> (length text) 0) even-empty) + (setq even-empty nil) + (let* ((pos (string-match "\n\\|$" text)) + (input (if (= (length text) 0) + "\n" + (concat (substring text 0 pos) "\n")))) + (setq text (substring text (min (length text) (1+ pos)))) + (goto-char (marker-position (process-mark inf-proc))) + (when win + (set-window-point win (process-mark inf-proc))) + (unless invisibly + ;; for consistency with comint :( + (insert (propertize input 'font-lock-face 'comint-highlight-input)) + (set-marker (process-mark inf-proc) (point))) + (inferior-ess-mark-as-busy inf-proc) + (process-send-string inf-proc input)) + (when (or (> (length text) 0) + wait-last-prompt) + (ess-wait-for-process inf-proc t (or wait-sec 0.001)))) + (when eob + (display-buffer inf-buf)) + ;; This used to be conditioned on EOB but this is no longer the + ;; case since commit fd90550d in 2012 (probably an accident) + (goto-char (marker-position (process-mark inf-proc))) + (when win + (with-selected-window win + (goto-char (point)) + ;; this is crucial to avoid resetting window-point + (recenter (- -1 scroll-margin)))))) + (when (numberp sleep-sec) + (sleep-for sleep-sec))) + + +;;;*;;; Evaluate only + +(defun ess-eval-region--normalise-region (start end) + "Clean the region from START to END for evaluation. +This trims newlines at beginning and end of the region because +they might throw off the debugger." + (save-excursion + (goto-char start) + (skip-chars-forward "\n\t ") + (setq start (point)) + (unless mark-active + (ess-blink-region start end)) + (goto-char end) + (skip-chars-backward "\n\t ") + (setq end (point)) + (cons start end))) + +(defun ess-eval-region (start end vis &optional message type) + "Send the region from START to END to the inferior ESS process. +VIS switches the meaning of `ess-eval-visibly'. If given, +MESSAGE is `message'ed. TYPE is a symbol indicating what type of +region this is. If command `rectangle-mark-mode' is active, send +the lines of the rectangle separately to the inferior process." + (interactive "r\nP") + (ess-force-buffer-current "Process to use: ") + (message "Starting evaluation...") + (unless ess-local-customize-alist + ;; External applications might call ess-eval-* functions; make it + ;; easier for them + (ess-setq-vars-local (symbol-value (ess-get-process-variable 'ess-local-customize-alist)))) + (if (bound-and-true-p rectangle-mark-mode) + ;; If we're in rectangle-mark-mode, loop over each line of the + ;; rectangle. Send them separately. + (let ((reclines (extract-rectangle-bounds (min (mark) (point)) (max (mark) (point))))) + (mapc (lambda (l) + (ess--eval-region (car l) (cdr l) vis message type)) + reclines)) + (ess--eval-region start end vis message type))) + +(defun ess--eval-region (start end vis &optional message type) + "Helper function for `ess-eval-region', which see. +START, END, VIS, MESSAGE, and TYPE described there." + (let* ((se (ess-eval-region--normalise-region start end)) + (start (car se)) + (end (cdr se))) + (let ((visibly (if vis (not ess-eval-visibly) ess-eval-visibly)) + (message (or message "Eval region")) + (proc (ess-get-process))) + (save-excursion + (ess-send-region proc start end visibly message type))) + (when ess-eval-deactivate-mark + (ess-deactivate-mark)) + (list start end))) + +(defun ess-eval-buffer (&optional vis) + "Send the current buffer to the inferior ESS process. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-region (point-min) (point-max) vis "Eval buffer" 'buffer)) + +(defun ess-eval-buffer-from-beg-to-here (&optional vis) + "Send region from beginning to point to the inferior ESS process. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-region (point-min) (point) vis "Eval buffer till point")) + +(defun ess-eval-buffer-from-here-to-end (&optional vis) + "Send region from point to end of buffer to the inferior ESS process. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-region (point) (point-max) vis "Eval buffer till end")) + +(defun ess-eval-function (&optional vis) + "Send the current function to the inferior ESS process. +Prefix arg VIS toggles visibility of ess-code as for +`ess-eval-region'. Returns nil if not inside a function." + (interactive "P") + (ess-force-buffer-current) + (save-excursion + (ignore-errors + ;; Evaluation is forward oriented + (forward-line -1) + (ess-next-code-line 1)) + (let ((pos (point)) + beg end msg) + (end-of-defun) + (beginning-of-defun) + ;; While we are the beginning of the function, get the function + ;; name. FIXME: should use our ess-function-pattern. + (setq msg (format "Eval function: %s" + (if (looking-at add-log-current-defun-header-regexp) + (match-string 1) + (buffer-substring (point) (line-end-position))))) + (setq beg (point)) + (end-of-defun) + (setq end (point)) + (when (or (< pos beg) + (< end pos)) + (error "Not in a function")) + (if (ess-tracebug-p) + (ess-tracebug-send-function (get-process ess-local-process-name) beg end vis msg) + (ess-eval-region beg end vis msg))))) + +(defun ess-eval-paragraph (&optional vis) + "Send the current paragraph to the inferior ESS process. +Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'." + (interactive "P") + (let ((start-pos (point))) + (if (= (line-beginning-position) (point-min)) + (ess-next-code-line 0) + ;; Evaluation is forward oriented + (forward-line -1) + (ess-next-code-line 1)) + (when (< (point) start-pos) + (goto-char start-pos)) + (save-excursion + (let ((beg (progn (backward-paragraph) (point))) + (end (progn (forward-paragraph) (point)))) + (ess-eval-region beg end vis))))) + +(defun ess-eval-function-or-paragraph (&optional vis) + "Send the current function if \\[point] is inside one. +Otherwise send the current paragraph to the inferior ESS process. +Prefix arg VIS toggles visibility of ess-code as for +`ess-eval-region'. Returns \\='function if a function was evaluated +or \\='paragraph if a paragraph." + (interactive "P") + (condition-case nil + (progn (ess-eval-function vis) + 'function) + ;; TODO: Maybe be smarter than just catching all errors? + (error (ess-eval-paragraph vis) + 'paragraph))) + +(defun ess-eval-function-or-paragraph-and-step (&optional vis) + "Send the current function if \\[point] is inside one. +Otherwise send the current paragraph to the inferior ESS process. +Prefix arg VIS toggles visibility of ess-code as for +`ess-eval-region'." + (interactive "P") + (ess-skip-thing (ess-eval-function-or-paragraph vis)) + (ess-next-code-line)) + +(defun ess-eval-region-or-function-or-paragraph (&optional vis) + "Send the region, function, or paragraph depending on context. +Send the region if it is active. If not, send function if `point' +is inside one, otherwise the current paragraph. Treats +rectangular regions as `ess-eval-region' does. Prefix arg VIS +toggles visibility of ess-code as for `ess-eval-region'." + (interactive "P") + (if (use-region-p) + (ess-eval-region (region-beginning) (region-end) vis) + (ess-eval-function-or-paragraph vis))) + +(defun ess-eval-region-or-function-or-paragraph-and-step (&optional vis) + "Send the region, function, or paragraph depending on context. +Send the region if it is active. If not, send function if `point' +is inside one, otherwise the current paragraph. Treats +rectangular regions as `ess-eval-region' does. After evaluation +step to the next code line or to the end of region if region was +active. Prefix arg VIS toggles visibility of ess-code as for +`ess-eval-region'." + (interactive "P") + (ess-skip-thing (ess-eval-region-or-function-or-paragraph vis)) + (ess-next-code-line)) + +(defun ess-eval-region-or-line-and-step (&optional vis) + "Evaluate region if active, otherwise `ess-eval-line-and-step'. +See `ess-eval-region' for the meaning of VIS. Treats rectangular +regions as `ess-eval-region' does." + (interactive "P") + (if (use-region-p) + (ess-eval-region (region-beginning) (region-end) vis) + (ess-eval-line-and-step))) + +(defun ess-eval-region-or-line-visibly-and-step () + "Evaluate region if active, otherwise the current line and step. +Evaluation is done visibly. + +Note that when inside a package and namespaced evaluation is in +place (see `ess-r-set-evaluation-env') evaluation of multiline +input will fail." + (interactive) + (ess-force-buffer-current) + (display-buffer (ess-get-process-buffer) + ;; Use a different window for the process buffer: + '(nil (inhibit-same-window . t)) + ;; Pass t to reusable-frames if users have help in + ;; own frames, otherwise help frames get split to + ;; display the inferior. + (or (equal ess-help-own-frame 'one) + ess-help-own-frame)) + (let ((ess-eval-visibly t)) + (ess-eval-region-or-line-and-step))) + +(defun ess-eval-line (&optional vis) + "Send the current line to the inferior ESS process. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (let* ((beg (line-beginning-position)) + (end (line-end-position)) + (msg (format "Loading line: %s" (buffer-substring beg end)))) + (ess-eval-region beg end vis msg))) + +(defun ess-eval-line-and-step (&optional vis) + "Evaluate the current line and step to the \"next\" line. +See `ess-eval-region' for VIS." + (interactive "P") + (ess-eval-line vis) + (ess-skip-thing 'line) + (ess-next-code-line)) + +(defun ess-eval-line-visibly-and-step (&optional simple-next) + "Evaluate the current line visibly and step to the \"next\" line. +If SIMPLE-NEXT is non-nil, possibly via prefix arg, first skip +empty and commented lines. When the variable `ess-eval-empty' +is non-nil both SIMPLE-NEXT and EVEN-EMPTY are interpreted as +true. + +Note that when inside a package and namespaced evaluation is in +place (see `ess-r-set-evaluation-env'), the evaluation of +multiline input will fail." + (interactive "P") + (ess-force-buffer-current) + (display-buffer (ess-get-process-buffer) + ;; Use a different window for the process buffer: + '(nil (inhibit-same-window . t)) + ;; Pass t to reusable-frames if users have help in + ;; own frames, otherwise help frames get split to + ;; display the inferior. + (or (equal ess-help-own-frame 'one) + ess-help-own-frame)) + (let ((ess-eval-visibly t) + (ess-eval-empty (or ess-eval-empty simple-next))) + (ess-eval-line) + (ess-skip-thing 'line) + (ess-next-code-line))) + +(defun ess-eval-line-invisibly-and-step () + "Evaluate the current line invisibly and step to the next line. +Evaluate all comments and empty lines." + (interactive) + (let ((ess-eval-visibly nil)) + (ess-eval-line-and-step))) +(define-obsolete-function-alias 'ess-eval-line-and-step-invisibly + #'ess-eval-line-invisibly-and-step "18.10") + + +;;;*;;; Evaluate and switch to S + +(defun ess-eval-region-and-go (start end &optional vis) + "Send region from START to END to the inferior process buffer. +START and END default to the current region, and rectangular +regions are treated as `ess-eval-region'. VIS has same meaning as +for `ess-eval-region'." + (interactive "r\nP") + (ess-eval-region start end vis) + (ess-switch-to-ESS t)) + +(defun ess-eval-buffer-and-go (&optional vis) + "Send the current buffer to the inferior S and switch to the process buffer. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-buffer vis) + (ess-switch-to-ESS t)) + +(defun ess-eval-function-and-go (&optional vis) + "Send the current function, then switch to the inferior process buffer. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-function vis) + (ess-switch-to-ESS t)) + +(defun ess-eval-line-and-go (&optional vis) + "Send the current line, then switch to the inferior process buffer. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-line vis) + (ess-switch-to-ESS t)) + +(defun ess-eval-paragraph-and-go (&optional vis) + "Send the current paragraph, then switch to the inferior process buffer. +VIS has same meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-paragraph vis) + (ess-switch-to-ESS t)) + +(defun ess-eval-paragraph-and-step (&optional vis) + "Evaluate the current paragraph and move point to the next line. +If not inside a paragraph, evaluate the next one. VIS has same +meaning as for `ess-eval-region'." + (interactive "P") + (ess-eval-paragraph vis) + (ess-skip-thing 'paragraph) + (ess-next-code-line)) + + ; Inferior ESS mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; In this section: +;;;; +;;;; * The major mode inferior-ess-mode +;;;; * Process handling code +;;;; * Completion code +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;*;; Major mode definition + +(defvar inferior-ess-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-y" #'ess-yank) + (define-key map "\r" #'inferior-ess-send-input) + (define-key map "\C-a" #'comint-bol) + ;; 2010-06-03 SJE + ;; disabled this in favor of ess-dirs. Martin was not sure why this + ;; key was defined anyway in this mode. + ;;(define-key map "\M-\r" #'ess-transcript-send-command-and-move) + (define-key map "\C-c\M-l" #'ess-load-file) + (define-key map "\C-c`" #'ess-show-traceback) + (define-key map [(control ?c) ?~] #'ess-show-call-stack) + (define-key map "\C-c\C-d" #'ess-dump-object-into-edit-buffer) + (define-key map "\C-c\C-v" #'ess-display-help-on-object) + (define-key map "\C-c\C-q" #'ess-quit) + (define-key map "\C-c\C-s" #'ess-execute-search) + (define-key map "\C-c\C-x" #'ess-execute-objects) + (define-key map "\C-c\034" #'ess-abort) ; \C-c\C-backslash + (define-key map "\C-c\C-z" #'ess-switch-to-inferior-or-script-buffer) ; mask comint map + (define-key map "\C-d" #'delete-char) ; EOF no good in S + (define-key map "\t" #'completion-at-point) + (define-key map "\M-?" #'ess-complete-object-name) + (define-key map "\C-c\C-k" #'ess-request-a-process) + (define-key map "," #'ess-smart-comma) + (define-key map "\C-c\C-d" 'ess-doc-map) + (define-key map "\C-c\C-e" 'ess-extra-map) + (define-key map "\C-c\C-t" 'ess-dev-map) + map) + "Keymap for `inferior-ess' mode.") + +(easy-menu-define + inferior-ess-mode-menu inferior-ess-mode-map + "Menu for use in Inferior S mode" + '("iESS" + ["Quit" ess-quit t] + ["Reload process" inferior-ess-reload t] + ;; ["Send and move" ess-transcript-send-command-and-move t] + ["Copy command" comint-copy-old-input t] + ["Send command" inferior-ess-send-input t] + ["Switch to script buffer" ess-switch-to-inferior-or-script-buffer t] + ["Get help on S object" ess-display-help-on-object t] + "------" + ("Process" + ["Process Echoes" (lambda () (interactive) + (setq comint-process-echoes (not comint-process-echoes))) + :active t + :style toggle + :selected comint-process-echoes] + ("Eval visibly " + :filter ess--generate-eval-visibly-submenu )) + "------" + ("Utils" + ["Attach directory" ess-execute-attach t] + ["Display object list" ess-execute-objects t] + ["Display search list" ess-execute-search t] + ["Edit S object" ess-dump-object-into-edit-buffer t] + ["Enter S command" ess-execute t] + ["Jump to error" ess-parse-errors t] + ["Load source file" ess-load-file t] + ["Resynch S completions" ess-resynch t] + ["Recreate R versions known to ESS" + (lambda () (interactive) (ess-r-redefine-runners 'verbose)) t] + ) + "------" + ("start-dev" :visible nil); <-- ?? + ("end-dev" :visible nil) + "------" + ("Font Lock" + :active ess-font-lock-keywords + :filter ess--generate-font-lock-submenu) + "------" + ["Describe" describe-mode t] + ["Send bug report" ess-submit-bug-report t] + ["About" (ess-goto-info "Entering Commands") t] + )) + + +(defvar ess-mode-minibuffer-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-map) + (define-key map "\t" #'ess-complete-object-name) + (define-key map "\C-\M-i" #'ess-complete-object-name) ;; doesn't work:( + (define-key map "\C-c\C-s" #'ess-execute-search) + (define-key map "\C-c\C-x" #'ess-execute-objects) + map) + "Keymap used in `ess-execute'.") + +(define-derived-mode inferior-ess-mode comint-mode "iESS" + "Major mode for interacting with an inferior ESS process. +To learn more about how to use inferior ess modes, see Info +node `(ess)Top'. If you accidentally suspend your process, use +\\[comint-continue-subjob] to continue it." + :group 'ess-proc + (setq-local comint-input-sender 'inferior-ess-input-sender) + (setq-local font-lock-fontify-region-function + #'inferior-ess-fontify-region) + ;; If comint-process-echoes is t inferior-ess-input-sender + ;; recopies the input, otherwise not + (setq-local comint-process-echoes (not (member ess-language '("SAS" "XLS" "OMG" "julia")))) + + (when comint-use-prompt-regexp ;; why comint is not setting this? bug? + (setq-local inhibit-field-text-motion t)) + + (unless inferior-ess-prompt ;; build when unset + (setq inferior-ess-prompt + (concat "\\(" + inferior-ess-primary-prompt + (when inferior-ess-secondary-prompt "\\|") + inferior-ess-secondary-prompt + "\\)"))) + (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) + + (setq mode-line-process + '(" [" + ess--mode-line-process-indicator + ess--local-mode-line-process-indicator + "]: %s")) + + ;;; Completion support ---------------- + (remove-hook 'completion-at-point-functions #'comint-completion-at-point t) ;; reset the hook + (add-hook 'completion-at-point-functions + #'comint-c-a-p-replace-by-expanded-history nil 'local) + (add-hook 'completion-at-point-functions #'ess-filename-completion nil 'local) + + ;; hyperlinks support + (goto-address-mode t) + + ;; Avoid spaces after filenames + (setq-local comint-completion-addsuffix (cons "/" "")) + + (setq comint-input-autoexpand t) ; Only for completion, not on input. + + (add-hook 'window-configuration-change-hook #'ess-set-width nil t) + (setq-local indent-tabs-mode nil) + + (setq-local paragraph-start (concat inferior-ess-primary-prompt "\\|\^L")) + (setq-local paragraph-separate "\^L") + (setq-local jit-lock-chunk-size inferior-ess-jit-lock-chunk-size)) + + + +;;*;; Commands used exclusively in inferior-ess-mode + +;;;*;;; Main user commands + +(defun inferior-ess-input-sender (proc string) + (inferior-ess--interrupt-subjob-maybe proc) + (let ((comint-input-filter-functions nil)) ; comint runs them, don't run twice. + (if comint-process-echoes + (ess-eval-linewise string nil nil ess-eval-empty) + (ess-send-string proc string)))) + +(defvar ess-help-arg-regexp "\\(['\"]?\\)\\([^,=)'\"]*\\)\\1" + "Reg(ular) Ex(pression) of help(.) arguments. MUST: 2nd \\(.\\) = arg.") + +(defun inferior-ess-send-input () + "Sends the command on the current line to the ESS process." + (interactive) + (run-hooks 'ess-send-input-hook) + (unless (ess-process-get 'busy) + ;; avoid new line insertion + (ess-process-put 'prev-prompt nil)) + (comint-send-input) + (setq ess-object-list nil)) + +(defun inferior-ess--goto-input-start:field () + "Move point to the beginning of input skipping all continuation lines. +If in the output field, goes to the beginning of previous input +field. +Note: `inferior-ess-secondary-prompt' should match exactly." + (goto-char (field-beginning)) + ;; move to the beginning of non-output field + (while (and (not (bobp)) + (eq (field-at-pos (point)) 'output)) + (goto-char (field-beginning nil t))) + ;; skip all secondary prompts + (let ((pos (field-beginning (point) t)) + (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) + (while (and pos + (if (eq (get-text-property pos 'field) 'output) + (string-match secondary-prompt (field-string-no-properties pos)) + t)) + (goto-char pos) + (setq pos (previous-single-property-change pos 'field))))) + +(defun inferior-ess--goto-input-end:field () + "Move point to the end of input skipping all continuation lines. +If in the output field, goes to the beginning of previous input +field. NOTE: to be used only with fields, see +`comint-use-prompt-regexp'." + ;; this func is not used but might be useful some day + (goto-char (field-end)) + (let ((pos (point)) + (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) + (while (and pos + (if (eq (get-text-property pos 'field) 'output) + (string-match secondary-prompt (field-string-no-properties pos)) + t)) + (goto-char pos) + (setq pos (next-single-property-change pos 'field))))) + +(defun inferior-ess--get-old-input:field () + "Return the ESS command surrounding point (use with fields)." + (save-excursion + (if (eq (field-at-pos (point)) 'output) + (if (called-interactively-p 'any) + (error "No command on this line") + ;; else, just return "" + "") + (inferior-ess--goto-input-start:field) + (let ((command (field-string-no-properties (point))) + (pos (next-single-property-change (point) 'field )) + (secondary-prompt (concat "^" inferior-ess-secondary-prompt))) + (while (and pos + (cond + ((eq (get-text-property pos 'field) 'input) + (setq command (concat command "\n" (field-string-no-properties pos)))) + ((eq (get-text-property pos 'field) 'output) + (string-match secondary-prompt (field-string-no-properties pos))) + (t)));; just skip if unknown + (setq pos (next-single-property-change pos 'field))) + command)))) + +;; TODO: error when entering a multiline function +;; check.integer <- function(N){ +;; is.integer(N) | !length(grep("[^[:digit:]]", as.character(N))) +;; } +(defun inferior-ess--goto-input-start:regexp () + "Move point to the beginning of input skipping all continuation lines. +If in the output field, goes to the beginning of previous input." + (beginning-of-line) + (unless (looking-at inferior-ess-prompt) + (re-search-backward (concat "^" inferior-ess-prompt) nil t)) + ;; at bol + (when (and inferior-ess-secondary-prompt + (looking-at inferior-ess-secondary-prompt)) + (while (and (> (forward-line -1) -1) + (looking-at inferior-ess-secondary-prompt)))) + (unless (looking-at inferior-ess-prompt) + (error "Beginning of input not found")) + (comint-skip-prompt)) + +(defun inferior-ess--get-old-input:regexp () + "Return the ESS command surrounding point (use regexp)." + ;;VS[03-09-2012]: This should not rise errors!! Troubles comint-interrupt-subjob + (save-excursion + (let* ((inhibit-field-text-motion t) + command) + (beginning-of-line) + (when (and inferior-ess-secondary-prompt + (looking-at inferior-ess-secondary-prompt)) + (inferior-ess--goto-input-start:regexp)) + (beginning-of-line) + (if (looking-at inferior-ess-prompt) ; cust.var, might not include sec-prompt + (progn + (comint-skip-prompt) + (setq command (buffer-substring-no-properties (point) (line-end-position))) + (when inferior-ess-secondary-prompt + (while (progn (forward-line 1) + (looking-at inferior-ess-secondary-prompt)) + (re-search-forward inferior-ess-secondary-prompt (line-end-position) t) + (setq command (concat command "\n" + (buffer-substring-no-properties (point) (line-end-position)))))) + (forward-line -1) + command) + (message "No command at this point") + "")))) + +(defun inferior-ess-get-old-input () + "Return the ESS command surrounding point." + (if comint-use-prompt-regexp + (inferior-ess--get-old-input:regexp) + (inferior-ess--get-old-input:field))) + +(defun ess-can-eval-in-background (&optional proc) + "Can the current process be used for background commands. +Inspects the `ess-can-eval-in-background' variable as well as the +`bg-eval-disabled' property of PROC or of the current process, if +any. This makes it possible to disable background evals for a +specific process, for instance in case it was not initialized +properly." + (when ess-can-eval-in-background + (when-let ((proc (or proc (ess-get-current-process)))) + (not (process-get proc 'bg-eval-disabled))))) + + +;;;*;;; Hot key commands + +(defun ess-execute-objects (posn) + "Send the objects() command to the ESS process. +By default, gives the objects at position 1. +A prefix argument toggles the meaning of `ess-execute-in-process-buffer'. +A prefix argument of 2 or more means get objects for that position. +A negative prefix argument gets the objects for that position + and toggles `ess-execute-in-process-buffer' as well." + (interactive "P") + (ess-make-buffer-current) + (let* ((num-arg (if (listp posn) + (if posn -1 1) + (prefix-numeric-value posn))) + (the-posn (if (< num-arg 0) (- num-arg) num-arg)) + (invert (< num-arg 0)) + (the-command (format inferior-ess-objects-command the-posn ".*")) + (the-message (concat ">>> Position " + (number-to-string the-posn) + " (" + (nth (1- the-posn) (ess-search-list)) + ")\n"))) + (ess-execute the-command invert "S objects" the-message))) + +(defun ess-execute-search (invert) + "Send the `inferior-ess-search-list-command' command. +INVERT is as in `ess-execute'. E.g. search(..) in S." + (interactive "P") + (ess-execute inferior-ess-search-list-command invert "S search list")) + +;; FIXME --- this *only* works in S / S-plus; not in R +;; ----- ("at least" is not assigned to any key by default) +(defun ess-execute-attach (dir &optional posn) + "Attach a directory in the `ess-language' process with the attach() command. +When used interactively, user is prompted for DIR to attach and +prefix argument is used for POSN (or 2, if absent.) +Doesn't work for data frames." + (interactive "Attach directory: \nP") + (ess-execute (concat "attach(\"" + (directory-file-name (expand-file-name dir)) + "\"" + (if posn (concat "," (number-to-string + (prefix-numeric-value posn)))) + ")") 'buffer) + (ess-process-put 'sp-for-help-changed? t)) + +(defun ess-execute-screen-options (&optional invisibly) + "Cause S to set the \"width\" option to 1 less than the window width. +Also sets the \"length\" option to 99999. When INVISIBLY is +non-nil, don't echo to R subprocess. This is a good thing to put +in `ess-r-post-run-hook' or `ess-S+-post-run-hook'." + (interactive) + (ess-if-verbose-write + (format "ess-execute-screen-options: invisibly=%s\n" invisibly)) + (if (null ess-execute-screen-options-command) + (message "Not implemented for '%s'" ess-dialect) + (let ((command (ess-calculate-width 'window))) + (if invisibly + (ess-command command) + (ess-eval-linewise command nil nil nil 'wait-prompt))))) + +;; Runs in background if inferior is not busy +(defun ess--execute-screen-options-bg () + (when (and ess-execute-screen-options-command + (inferior-ess-available-p)) + (ess-execute-screen-options t))) + +(defun ess-calculate-width (opt) + "Calculate width command given OPT. +OPT can be \\='window, \\='frame, or an integer. Return a command +suitable to send to the inferior process (e.g. +\"options(width=80, length=999999)\")." + (when (null ess-execute-screen-options-command) + (error "Not implemented for %s" ess-dialect)) + (let (command) + (cond ((and (integerp opt) + (>= opt 0)) + (setq command (format ess-execute-screen-options-command opt))) + ((or (eql 'window opt) + (and (integerp opt) + (> 0 opt))) + ;; We cannot use (window-width) here because it returns sizes + ;; in default (frame) characters which leads to incorrect + ;; sizes with scaled fonts.To solve this we approximate font + ;; width in pixels and use window-pixel-width to compute the + ;; approximate number of characters that fit into line. + (let* ((wedges (window-inside-pixel-edges)) + (wwidth (- (nth 2 wedges) (nth 0 wedges))) + (nchars (floor (/ wwidth (default-font-width))))) + (when (and (integerp opt) + (> 0 opt)) + (setq nchars (- nchars (- opt)))) + (setq command (format ess-execute-screen-options-command + nchars)))) + ((eql 'frame opt) + (setq command + (format ess-execute-screen-options-command (frame-width)))) + (t (error "OPT (%s) not 'window, 'frame or an integer" opt))) + command)) + +(defun ess-set-width () + "Set the width option. +A part of `window-configuration-change-hook' in inferior ESS +buffers." + (when (and ess-auto-width + ess-execute-screen-options-command) + ;; `window-configuration-change-hook' runs with the window selected. + (let ((proc (get-buffer-process (window-buffer))) + command) + ;; TODO: Set the width once the process is no longer busy. + (when (and (process-live-p proc) + (not (process-get proc 'busy))) + (setq command (ess-calculate-width ess-auto-width)) + (if ess-auto-width-visible + (ess-eval-linewise command nil nil nil 'wait-prompt) + (ess-command command)))))) + +(defun ess-execute (command &optional invert buff message) + "Send a command to the ESS process. +A newline is automatically added to COMMAND. Prefix arg (or second arg +INVERT) means invert the meaning of +`ess-execute-in-process-buffer'. If INVERT is \\='buffer, output is +forced to go to the process buffer. If the output is going to a +buffer, name it *BUFF*. This buffer is erased before use. Optional +fourth arg MESSAGE is text to print at the top of the buffer (defaults +to the command if BUFF is not given.)" + (interactive (list + ;; simpler way to set proc name in mb? + (let ((enable-recursive-minibuffers t) + (proc-name (progn (ess-force-buffer-current) + ess-local-process-name))) + (with-current-buffer (get-buffer " *Minibuf-1*") ;; FIXME: hardcoded name + (setq ess-local-process-name proc-name)) + (read-from-minibuffer "Execute> " nil + ess-mode-minibuffer-map)) + current-prefix-arg)) + (ess-make-buffer-current) + (let ((the-command (concat command "\n")) + (buff-name (concat "*" (or buff "ess-output") "*")) + (in-pbuff (if invert (or (eq invert 'buffer) + (not ess-execute-in-process-buffer)) + ess-execute-in-process-buffer))) + (if in-pbuff + (ess-eval-linewise the-command) + (ess-with-current-buffer (get-buffer-create buff-name) + (ess-command the-command (current-buffer) nil nil nil + (get-process ess-local-process-name)) + (ansi-color-apply-on-region (point-min) (point-max)) + (goto-char (point-min)) + (if message (insert message) + (insert "> " the-command)) + (display-buffer (current-buffer)))))) + + +;;;*;;; Quitting + +(cl-defgeneric ess-quit--override (_arg) + "Stop the inferior process." + (let ((proc (ess-get-process))) + (ess-cleanup) + (when ess-eval-visibly + (goto-char (marker-position (process-mark proc))) + (insert inferior-ess-exit-command)) + (process-send-string proc inferior-ess-exit-command))) + +(defun ess-quit (&optional arg) + "Issue an exiting command to the inferior process. +Runs `ess-cleanup'. ARG gets passed to a language specific +method, see `ess-quit--override'." + (interactive "P") + (unless (ess-process-live-p) + (user-error "No live ESS process associated with this buffer")) + (ess-force-buffer-current "Process to quit: ") + (ess-interrupt) + (ess-make-buffer-current) + (ess-quit--override arg)) + +(defvar ess--interrupt-timeout 5) + +(defun ess-interrupt () + "Interrupt the inferior process. +This sends an interrupt and quits a debugging session." + (interactive) + (inferior-ess-force) + (let ((proc (ess-get-process))) + (ess--interrupt proc) + (unless (ess-wait-for-process proc nil nil nil + ess--interrupt-timeout) + (error "Timeout while interrupting process")) + (with-current-buffer (process-buffer proc) + (goto-char (process-mark proc))))) + +(defun ess--interrupt (proc) + (interrupt-process proc comint-ptyp) + ;; Workaround for Windows terminals. NOTE: Is this really needed + ;; for background commands? Or just for interactive interrupts? + (unless (memq system-type '(gnu/linux darwin)) + (process-send-string nil "\n"))) + +(defun ess-abort () + "Kill the ESS process, without executing .Last or terminating devices. +If you want to finish your session, use \\[ess-quit] instead." +;;; Provided as a safety measure over the default binding of C-c C-z in +;;; comint-mode-map. + (interactive) + (ding) + (message "WARNING: \\[inferior-ess-exit-command] will not be executed and graphics devices won't finish properly!") + (sit-for 2) + (if (y-or-n-p "Still abort? ") + (comint-quit-subjob) + (message "Good move."))) + +(defun ess-cleanup () + "Cleanup buffers associated with the process. +Possibly kill or offer to kill, depending on the value of +`ess-S-quit-kill-buffers-p', all buffers associated with this ESS +process. Uses `display-buffer' to display the process buffer. It +is run automatically by \\[ess-quit]." + (interactive) + (let* ((the-procname (or (ess-make-buffer-current) ess-local-process-name)) + (buf (buffer-name (process-buffer (get-process the-procname))))) + (unless the-procname + (error "I don't know which ESS process to clean up after!")) + (when + (or (eq ess-S-quit-kill-buffers-p t) + (and + (eq ess-S-quit-kill-buffers-p 'ask) + (y-or-n-p + (format + "Delete all buffers associated with process %s? " the-procname)))) + (dolist (buf (buffer-list)) + (with-current-buffer buf + ;; Consider buffers for which ess-local-process-name is + ;; the same as the-procname + (when (and (not (get-buffer-process buf)) + ess-local-process-name + (equal ess-local-process-name the-procname)) + (kill-buffer buf))))) + (display-buffer buf) + buf)) + +(defun inferior-ess-reload (&optional start-args) + "Reload the inferior process. +START-ARGS gets passed to the dialect-specific +`inferior-ess-reload-override'." + (interactive) + (let* ((inf-buf (inferior-ess-force)) + (inf-proc (get-buffer-process inf-buf)) + (inf-start-data (buffer-local-value 'inferior-ess--local-data inf-buf)) + (start-name (car inf-start-data)) + (start-args (or start-args (cdr inf-start-data)))) + ;; Interrupt early so we can get working directory + (ess-interrupt) + ;; Quit debugging session before reloading + (when (ess-debug-active-p) + (ess-debug-command-quit) + (ess-wait-for-process inf-proc nil nil nil 1)) + (save-window-excursion + ;; Make sure we don't ask for directory again + ;; Use current working directory as default + (let ((project-find-functions nil) + (ess-startup-directory-function nil) + (ess-startup-directory (ess-get-process-variable 'default-directory)) + (ess-ask-for-ess-directory nil)) + (ess-quit 'no-save) + (inferior-ess--wait-for-exit inf-proc) + (with-current-buffer inf-buf + (inferior-ess-reload--override start-name start-args)))))) + +(cl-defgeneric inferior-ess-reload--override (_start-name _start-args) + (user-error "Reloading not implemented for %s" ess-dialect)) + +(defun inferior-ess--wait-for-exit (proc) + "Wait for process PROC to exit. +This should be used instead of `ess-wait-for-process' for waiting +after issuing a quit command as the latter assumes a live process." + (let ((start-time (float-time))) + (while (eq (process-status proc) 'run) + (accept-process-output proc 0.002) + (when (> (- (float-time) start-time) 30) + (error "Timeout while quitting process"))))) + + +;;;*;;; Support functions + +(defun ess-extract-onames-from-alist (alist posn &optional force) + "Return the object names in position POSN of ALIST. +ALIST is an alist like `ess-sl-modtime-alist'. POSN should be in 1 .. (length +ALIST). If optional third arg FORCE is t, the corresponding element +of the search list is re-read. Otherwise it is only re-read if it's a +directory and has been modified since it was last read." + (let* ((entry (nth (1- posn) alist)) + (dir (car entry)) + (timestamp (car (cdr entry))) + (new-modtime (and timestamp + (ess-dir-modtime dir)))) + ;; Refresh the object listing if necessary + (if (or force (not (equal new-modtime timestamp))) + (setcdr (cdr entry) (ess-object-names dir posn))) + (cdr (cdr entry)))) + +(defun ess-dir-modtime (dir) + "Return the last modtime if DIR is a directory, and nil otherwise." + (and ess-filenames-map + (file-directory-p dir) + (nth 5 (file-attributes dir)))) + +(defun ess-object-modtime (object) + "Return the modtime of the S object OBJECT (a string). +Searches along the search list for a file named OBJECT and returns its modtime +Returns nil if that file cannot be found, i.e., for R or any non-S language!" + (let ((path (ess-search-list)) + result) + (while (and (not result) path) + (setq result (file-attributes + (concat (file-name-as-directory (car path)) + object))) + (setq path (cdr path))) + (nth 5 result))) + +(defun ess-modtime-gt (mod1 mod2) + "Return t if MOD1 is later than MOD2." + (and mod1 + (or (> (car mod1) (car mod2)) + (and (= (car mod1) (car mod2)) + (> (car (cdr mod1)) (car (cdr mod2))))))) + +(defun ess-get-object-list (name &optional exclude-first) + "Return a list of current S object names associated with process NAME. +Uses `ess-object-list' if that is non-nil. If EXCLUDE-FIRST is +non-nil, don't return objects in first position (.GlobalEnv)." + (or ess-object-list ;; <<- MM: this is now always(?) nil; we cache the *-modtime-alist + (with-current-buffer (process-buffer (ess-get-process name)) + (ess-make-buffer-current) + (ess-write-to-dribble-buffer (format "(get-object-list %s) .." name)) + (if (or (not ess-sl-modtime-alist) + (ess-process-get 'sp-for-help-changed?)) + (progn (ess-write-to-dribble-buffer "--> (ess-get-modtime-list)\n") + (ess-get-modtime-list)) + ;;else + (ess-write-to-dribble-buffer " using existing ess-sl-modtime-alist\n")) + (let* ((alist ess-sl-modtime-alist) + (i 2) + (n (length alist)) + result) + (ess-write-to-dribble-buffer (format " (length alist) : %d\n" n)) + (unless exclude-first + ;; re-read of position 1 : + (setq result (ess-extract-onames-from-alist alist 1 'force))) + (ess-write-to-dribble-buffer + (format " have re-read pos=1: -> length %d\n" (length result))) + ;; Re-read remaining directories if necessary. + (while (<= i n) + (setq result + (append result + (ess-extract-onames-from-alist alist i))) + (setq i (1+ i))) + (setq ess-object-list (delete-dups result)))))) + +(defun ess-get-words-from-vector (command &optional no-prompt-check wait proc + timeout) + "Evaluate the S command COMMAND, which returns a character vector. +Return the elements of the result of COMMAND as an alist of +strings. COMMAND should have a terminating newline. +NO-PROMPT-CHECK, WAIT, PROC, and TIMEOUT are passed to `ess-command'. + +FILTER may be the keyword \\='non-... or nil. To avoid truncation of +long vectors, wrap your command (%s) like this, or a version with +explicit options(max.print=1e6): \"local({ out <- try({%s}); +print(out, max=1e6) })\n\"." + (unless proc + (inferior-ess-force)) + (let* ((tbuffer (get-buffer-create + " *ess-get-words*")); initial space: disable-undo + (word-RE + (concat "\\(" + "\\\\\"" "\\|" "[^\"]" ; \" or non-"-char + "\\)*")) + (full-word-regexp + (concat "\"" "\\(" word-RE "\\)" + "\"" + "\\( \\|$\\)"; space or end + )) + words) + (ess-command command tbuffer 'sleep no-prompt-check wait proc nil timeout) + (with-current-buffer tbuffer + (goto-char (point-min)) + (while (re-search-forward full-word-regexp nil t) + (setq words (cons (buffer-substring (match-beginning 1) (match-end 1)) + words)))) + (ess-if-verbose-write + (if (> (length words) 5) + (format " |-> (length words)= %d\n" (length words)) + (format " |-> words= '%s'\n" words))) + (reverse words))) + +(defun ess-get-words-from-vector--foreground (command &optional no-prompt-check wait proc) + (let ((timeout most-positive-fixnum)) + (ess-get-words-from-vector command no-prompt-check wait proc timeout))) + +(defun ess-compiled-dir (dir) + "Return non-nil if DIR is an S object directory with special files. +I.e. if the filenames in DIR are not representative of the objects in DIR." + (or (file-exists-p (concat (file-name-as-directory dir) "___nonfile")) + (file-exists-p (concat (file-name-as-directory dir) "__BIGIN")) + (file-exists-p (concat (file-name-as-directory dir) "___NONFI")))) + +(defun ess-object-names (obj &optional pos) + "Return alist of S object names in directory (or object) OBJ. +If OBJ is a directory name (begins with `/') returns a listing of +that dir. This may use the search list position POS if necessary. +If OBJ is an object name, returns result of the command +`inferior-ess-safe-names-command'. If POS is supplied return the +result of the command in `inferior-ess-objects-command'. If OBJ +is nil or not a directory, POS must be supplied. In all cases, +the value is an list of object names." + (cond ((and (stringp obj) + (string-match-p "ESSR" obj)) + nil) + ;; FIXME: in both cases below, the same fallback "objects(POS)" is used -- merge! + ((and obj (file-accessible-directory-p obj)) + ;; Check the pre-compiled object list in ess-object-name-db first + + ;; FIXME: If used at all, ess-object-name-db should not only + ;; ----- be used in the directory case !! + (or (cdr-safe (assoc obj ess-object-name-db)) + ;; Take a directory listing + (and ess-filenames-map + ;; first try .Data subdirectory: + ;;FIXME: move ".Data" or ``this function'' to ess-sp6-d.el etc: + (let ((dir (concat (file-name-as-directory obj) ".Data"))) + (if (not (file-accessible-directory-p dir)) + (setq dir obj)) + (and (not (ess-compiled-dir dir)) + (directory-files dir)))) + ;; Get objects(pos) instead + (and (or (ess-write-to-dribble-buffer + (format "(ess-object-names ..): directory %s not used\n" obj)) + t) + pos + (ess-get-words-from-vector + (format inferior-ess-objects-command pos))))) + ((and obj ;; want names(obj) + (ess-get-words-from-vector + (format inferior-ess-safe-names-command obj)))) + (pos + (ess-get-words-from-vector + (format inferior-ess-objects-command pos))))) + +(defun ess-slot-names (obj) + "Return alist of S4 slot names of S4 object OBJ." + (ess-get-words-from-vector (format "slotNames(%s)\n" obj))) + +(defun ess-function-arguments (funname &optional proc) + "Get FUNARGS from cache or ask the process for it. +Return FUNARGS - a list with the first element being a +cons (PACKAGE_NAME . TIME_STAMP), second element is a string +giving arguments of the function as they appear in documentation, +third element is a list of arguments of all methods. If PROC is +given, it should be an ESS process. If PACKAGE_NAME is nil, and +TIME_STAMP is less recent than the time of the last user +interaction to the process, then update the entry. PACKAGE_NAME +is also nil when FUNNAME was not found, or FUNNAME is a special +name that contains :,$ or @." + (when (and funname ;; usually returned by ess--fn-name-start (might be nil) + (or proc (ess-process-live-p))) + (let* ((proc (or proc (get-process ess-local-process-name))) + (cache (or (process-get proc 'funargs-cache) + (let ((cache (make-hash-table :test 'equal))) + (process-put proc 'funargs-cache cache) + cache))) + (args (gethash funname cache)) + (pack (caar args)) + (ts (cdar args))) + (when (and args + (and (time-less-p ts (process-get proc 'last-eval)) + (or (null pack) + (equal pack "")))) + ;; reset cache + (setq args nil)) + (or args + (cadr (assoc funname (process-get proc 'funargs-pre-cache))) + (and + (not (process-get proc 'busy)) + (with-current-buffer (ess-command (format ess-funargs-command + (ess-quote-special-chars funname)) + nil nil nil nil proc) + (goto-char (point-min)) + (when (re-search-forward "(list" nil t) + (goto-char (match-beginning 0)) + (setq args (ignore-errors (eval (read (current-buffer)) t))) + (when args + (setcar args (cons (car args) (current-time))))) + ;; push even if nil + (puthash (substring-no-properties funname) args cache))))))) + +;;; SJE: Wed 29 Dec 2004 --- remove this function. +;;; rmh: Wed 5 Jan 2005 --- bring it back for use on Windows +(defun ess-create-object-name-db () + "Create a database of object names in standard S directories. +This database is saved in the file specified by +`ess-object-name-db-file', and is loaded when `ess-mode' is +loaded. It defines the variable `ess-object-name-db', which is +used for completions. Before you call this function, modify the S +search list so that it contains all the non-changing (i.e. +system) S directories. All positions of the search list except +for position 1 are searched and stored in the database. After +running this command, you should move ess-namedb.el to a +directory in the `load-path'." + (interactive) + (setq ess-object-name-db nil) + (let ((search-list (cdr (ess-search-list))) + (pos 2) + name + (buffer (get-buffer-create " *ess-db*")) + (temp-object-name-db nil)) + + (ess-write-to-dribble-buffer + (format "(object db): search-list=%s \n " search-list)) + (while search-list + (message "Searching %s" (car search-list)) + (setq temp-object-name-db (cons (cons (car search-list) + (ess-object-names nil pos)) + temp-object-name-db)) + (setq search-list (cdr search-list)) + (ess-write-to-dribble-buffer + (format "(object db): temp-obj-name-db=%s \n pos=%s" + temp-object-name-db pos)) + (setq pos (1+ pos))) + (with-current-buffer buffer + (erase-buffer) + (insert "(setq ess-object-name-db '") + (prin1 temp-object-name-db (current-buffer)) + (insert ")\n") + (setq name (expand-file-name ess-object-name-db-file)) + (write-region (point-min) (point-max) name) + (message "Wrote %s" name)) + (kill-buffer buffer) + (setq ess-object-name-db temp-object-name-db))) + +(defun ess-resynch nil + "Reread all directories and objects in `ess-search-list' for completions." + (interactive) + (if (ess-make-buffer-current) nil + (error "Not an ESS process buffer")) + (setq + ess-sl-modtime-alist nil + ess-object-list nil + ess-object-name-db nil ; perhaps it would be better to reload? + ) + (ess-process-put 'sp-for-help-changed? t) + ;; Action! : + (ess-get-modtime-list)) + +(defun ess-filename-completion () + "Return completion only within string or comment." + (save-restriction ;; explicitly handle inferior-ess + (ignore-errors + (when (and (derived-mode-p 'inferior-ess-mode) + (> (point) (process-mark (get-buffer-process (current-buffer))))) + (narrow-to-region (process-mark (get-buffer-process (current-buffer))) + (point-max)))) + (when (and (not (equal ?` (nth 3 (syntax-ppss (point))))) + (ess-inside-string-or-comment-p (point))) + (append (comint-filename-completion) '(:exclusive no))))) + +(defun ess-complete-filename () + "Do file completion only within strings." + (declare (obsolete comint-filename-completion "ESS 19.04")) + (save-restriction ;; explicitly handle inferior-ess + (ignore-errors + (when (and (derived-mode-p 'inferior-ess-mode) + (> (point) (process-mark (get-buffer-process (current-buffer))))) + (narrow-to-region (process-mark (get-buffer-process (current-buffer))) + (point-max)))) + (when (or (ess-inside-string-or-comment-p (point))) ;; usable within ess-mode as well + (comint-dynamic-complete-filename)))) + +(defun ess-after-pathname-p nil + ;; Heuristic: after partial pathname if it looks like we're in a + ;; string, and that string looks like a pathname. Not the best for + ;; use with unix() (or it's alias, !). Oh well. + (declare (obsolete comint-filename-completion "ESS 19.04")) + (save-excursion + (save-match-data + (let ((opoint (point))) + (and (re-search-backward "\\(\"\\|'\\)[~/#$.a-zA-Z0-9][^ \t\n\"']*" + nil t) + (eq opoint (match-end 0))))))) + + +;;*;; Functions handling the search list + +(defun ess-search-list (&optional force-update) + "Return the current search list as a list of strings. +Elements which are apparently directories are expanded to full +dirnames. Don't try to use cache if FORCE-UPDATE is non-nil. Is +*NOT* used by \\[ess-execute-search], but by \\[ess-resynch], +\\[ess-get-object-list], \\[ess-get-modtime-list], +\\[ess-execute-objects], \\[ess-object-modtime], +\\[ess-create-object-name-db], and (indirectly) by +\\[ess-get-help-files-list]." + (with-current-buffer + (ess-get-process-buffer ess-current-process-name);to get *its* local vars + (let ((result nil) + (slist (ess-process-get 'search-list)) + (tramp-mode nil)) ;; hack for bogus file-directory-p below + (if (and slist + (not force-update) + (not (ess-process-get 'sp-for-help-changed?))) + slist + ;; else, re-compute: + (ess-write-to-dribble-buffer " (ess-search-list ... ) ") + (let ((tbuffer (get-buffer-create " *search-list*")) + (homedir default-directory) + (my-search-cmd inferior-ess-search-list-command); from ess-buffer + elt) + (ess-command my-search-cmd tbuffer 0.05); <- sleep for dde only; does (erase-buffer) + (with-current-buffer tbuffer + ;; guaranteed by the initial space in its name: (buffer-disable-undo) + (goto-char (point-min)) + (ess-write-to-dribble-buffer + (format "after '%s', point-max=%d\n" my-search-cmd (point-max))) + (while (re-search-forward "\"\\([^\"]*\\)\"" nil t) + (setq elt (buffer-substring (match-beginning 1) (match-end 1))) + ;;Dbg: (ess-write-to-dribble-buffer (format " .. elt= %s \t" elt)) + (if (and (string-match "^[^/]" elt) + (file-directory-p (concat homedir elt))) + (progn + ;;Dbg: (ess-write-to-dribble-buffer "*IS* directory\n") + (setq elt (concat homedir elt))) + ;;else + ;;dbg + ;;- (ess-write-to-dribble-buffer "not dir.\n") + ) + (setq result (append result (list elt)))) + (kill-buffer tbuffer))) + result)))) + +;;; ess-sl-modtime-alist is a list with elements as follows: +;;; * key (directory or object name) +;;; * modtime (list of 2 integers) +;;; * name, name ... (accessible objects in search list posn labeled by key) +;;; It is a buffer-local variable (belonging to e.g. *R*, *S+6*, .. etc) +;;; and has the same number of elements and is in the same order as the +;;; S search list + +(defun ess-get-modtime-list (&optional cache-var-name exclude-first) + "Record directories in the search list, and the objects in those directories. +The result is stored in CACHE-VAR-NAME. If nil, CACHE-VAR-NAME +defaults to `ess-sl-modtime-alist'. If EXCLUDE-FIRST is non-nil +don't recompile first object in the search list." + ;; Operation applies to process of current buffer + (let* ((searchlist (if exclude-first + (cdr (ess-search-list)) + (ess-search-list))) + (index (if exclude-first 2 1)) + (cache-name (or cache-var-name 'ess-sl-modtime-alist)) + pack newalist) + (while searchlist + (setq + pack (car searchlist) + newalist (append newalist + (list (or (assoc pack (symbol-value cache-name)) + (append + (list pack (ess-dir-modtime pack)) + (prog2 + (message "Forming completions for %s..." pack) + (ess-object-names pack index) + (message "Forming completions for %s...done" pack)))))) + index (1+ index) + searchlist (cdr searchlist))) + ;;DBG: + (ess-write-to-dribble-buffer + (format "(%s): created new alist of length %d\n" + cache-var-name (length newalist))) + (set cache-name newalist))) + + +(defun ess-search-path-tracker (str) + "Check if input STR changed the search path. +This function monitors user input to the inferior ESS process so +that Emacs can keep the process variable `search-list' up to +date. `ess-completing-read' in \\[ess-read-object-name] uses this +list indirectly when it prompts for help or for an object to +dump. From ESS 12.09 this is not necessary anymore, as the search +path is checked on idle time. It is kept for robustness and +backward compatibility only." + (when ess-change-sp-regexp + (if (string-match ess-change-sp-regexp str) + (ess-process-put 'sp-for-help-changed? t)))) + + +;;; Miscellaneous routines + +;;;*;;; Routines for reading object names +(defun ess-read-object-name (p-string) + "Read an object name from the minibuffer with completion, and return it. +P-STRING is the prompt string." + (let* ((default (ess-read-object-name-dump)) + (object-list (ess-get-object-list ess-local-process-name)) + (spec (ess-completing-read p-string object-list nil nil nil nil default))) + (list (cond + ((string= spec "") default) + (t spec))))) + +(defun ess-read-object-name-default () + "Return the object name at point, or nil if none." + (ignore-errors + (save-excursion + ;; The following line circumvents an 18.57 bug in following-char + (if (eobp) (backward-char 1)) ; Hopefully buffer is not empty! + ;; Get onto a symbol + (catch 'nosym ; bail out if there's no symbol at all before point + (while (let ((sc (char-syntax (following-char)))) + (not (or (= sc ?w) (= sc ?_)))) + (if (bobp) (throw 'nosym nil) (backward-char 1)))) + (let* + ((end (progn (forward-sexp 1) (point))) + (beg (progn (backward-sexp 1) (point)))) + (buffer-substring-no-properties beg end))))) + +(defun ess-read-object-name-dump () + "Return the object name at point, or \"Temporary\" if none." + (ignore-errors + (save-excursion + ;; Get onto a symbol + (catch 'nosym ; bail out if there's no symbol at all before point + (while (/= (char-syntax (following-char)) ?w) + (if (bobp) (throw 'nosym nil) (backward-char 1))) + (let* + ((end (progn (forward-sexp 1) (point))) + (beg (progn (backward-sexp 1) (point))) + (object-name (buffer-substring beg end))) + (or object-name "Temporary")))))) + +;;;; start of ess-smart-operators +;;;; inspired by slime repl shortcuts + +(defvar ess--handy-history nil) + +(defun ess-handy-commands () + "Request and execute a command from variable `ess-handy-commands'." + (interactive) + (let* ((commands (or ess--local-handy-commands + ess-handy-commands)) + (hist (and (assoc (car ess--handy-history) + commands) + (car ess--handy-history)))) + (call-interactively + (cdr (assoc (ess-completing-read "Execute" + (sort (mapcar #'car commands) + #'string-lessp) + nil t nil 'ess--handy-history hist) + commands))))) + +(defun ess-smart-comma () + "If comma is invoked at the process marker of an ESS inferior +buffer, request and execute a command from `ess-handy-commands' +list." + (interactive) + (let ((proc (get-buffer-process (current-buffer)))) + (if (and proc + (eq (point) (marker-position (process-mark proc)))) + (ess-handy-commands) + (if ess-smart-operators + (progn + (delete-horizontal-space) + (insert ", ") + (unless (derived-mode-p 'inferior-ess-mode) + (indent-according-to-mode))) + (insert ","))))) + + ; directories +(defun ess-set-working-directory (path &optional no-error) + "Set the current working to PATH for the ESS buffer and iESS process. +NO-ERROR prevents errors when this has not been implemented for +`ess-dialect'." + (interactive "DChange working directory to: ") + (if ess-setwd-command + (let* ((remote (file-remote-p path)) + (path (if remote + (progn + (require 'tramp-sh) + (tramp-sh-handle-expand-file-name path)) + path)) + (lpath (if remote + (with-parsed-tramp-file-name path v v-localname) + path))) + (ess-eval-linewise (format ess-setwd-command lpath)) + (ess-set-process-variable 'default-directory + (file-name-as-directory path))) + (unless no-error + (error "Not implemented for dialect %s" ess-dialect)))) + +(defalias 'ess-change-directory #'ess-set-working-directory) +(define-obsolete-function-alias + 'ess-use-dir #'ess-set-working-directory "ESS 18.10") + +(defun ess-use-this-dir (&rest _ignore) + "Set the current process directory to the directory of this file. +`default-directory' is used as a fallback." + (interactive) + (let ((dir (if buffer-file-name + (file-name-directory buffer-file-name) + default-directory))) + (ess-set-working-directory (abbreviate-file-name dir)))) + +(defun ess-get-working-directory (&optional no-error) + "Retrieve the current working directory from the current ess process." + (if ess-getwd-command + (abbreviate-file-name (car (ess-get-words-from-vector ess-getwd-command))) + (unless no-error + (error "Not implemented for dialect %s" ess-dialect)))) + +(defun ess-synchronize-dirs () + "Set Emacs' current directory to be the same as the subprocess directory. +To be used in `ess-idle-timer-functions'." + (when (and (ess-can-eval-in-background) + ess-getwd-command + (inferior-ess-available-p)) + (ess-when-new-input last-sync-dirs + (ess-if-verbose-write "\n(ess-synchronize-dirs)\n") + (let ((lpath (car (ess-get-words-from-vector ess-getwd-command)))) + (setq default-directory + (file-name-as-directory + (ess--derive-connection-path default-directory lpath)))) + default-directory))) + +(defun ess-dirs () + "Set Emacs' current directory to be the same as the *R* process." + ;; Note: This function is not necessary anymore. The Emacs + ;; default-directory and subprocess working directory are + ;; synchronized automatically. + (interactive) + (let* ((dir (car (ess-get-words-from-vector "getwd()\n"))) + (new-default-dir (ess--derive-connection-path default-directory dir))) + (message "(ESS / default) directory: %s" dir) + (setq default-directory (file-name-as-directory new-default-dir)))) + +(defun ess--derive-connection-path (old new) + "Derive a (possibly remote) path with an updated local filename. +A new connection path is derived from OLD (a path) and NEW (a +path), in such a way that the host and connection information (if +any) in OLD is retained in the NEW path. NEW must be an absolute +path, and can be a remote path" + (concat (file-remote-p old) + (or (file-remote-p new 'localname) new))) + +;; search path +(defun ess--mark-search-list-as-changed () + "Internal. Mark all the search-list related variables as changed." + ;; other guys might track their own + (ess-process-put 'sp-for-help-changed? t) + (ess-process-put 'sp-for-ac-changed? t)) + +(defun ess-cache-search-list () + "To be used in `ess-idle-timer-functions', to set search path related variables." + (when (and (ess-can-eval-in-background) + inferior-ess-search-list-command) + (ess-when-new-input last-cache-search-list + (let ((path (ess-search-list 'force)) + (old-path (process-get *proc* 'search-list))) + (when (not (equal path old-path)) + (process-put *proc* 'search-list path) + (ess--mark-search-list-as-changed) + path))))) + + +;;*;; Temporary buffer handling +(defun ess-display-temp-buffer (buff) + "Display the buffer BUFF. +Uses `temp-buffer-show-function' and respects +`ess-display-buffer-reuse-frames'." + (if (fboundp temp-buffer-show-function) + (funcall temp-buffer-show-function buff)) + (display-buffer buff '(display-buffer-reuse-window) ess-display-buffer-reuse-frames)) + +(defun ess--inject-code-from-file (file &optional chunked) + "Load code from FILE into process. +If CHUNKED is non-nil, split the file by separator (must be at +bol) and load each chunk separately." + ;; This is different from ess-load-file as it works by directly loading the + ;; string into the process and thus works on remotes. + (let ((proc-name ess-local-process-name) + (dialect ess-dialect) + (send-1 (lambda (str) + (if (string= ess-dialect "R") + ;; avoid detection of intermediate prompts + (ess-command (concat "{" str "}\n")) + (ess-command str))))) + (with-temp-buffer + (setq ess-local-process-name proc-name + ess-dialect dialect) + (insert-file-contents-literally file) + (if chunked + (let ((beg (point-min))) + (goto-char beg) + (while (re-search-forward "^ " nil t) + (funcall send-1 (buffer-substring beg (point))) + (setq beg (point))) + (funcall send-1 (buffer-substring (point) (point-max)))) + (funcall send-1 (buffer-string)))))) + +(defun ess-check-modifications nil + "Check whether loading this file would overwrite some ESS objects +which have been modified more recently than this file, and confirm +if this is the case." + (declare (obsolete "Do not use" "21.04")) + (when (> (length ess-change-sp-regexp) 0) + (and (buffer-file-name) ess-filenames-map + (let ((sourcemod (nth 5 (file-attributes (buffer-file-name)))) + (objname)) + (save-excursion + (goto-char (point-min)) + ;; Get name of assigned object, if we can find it + (setq objname + (and + (re-search-forward + "^\\s *\"?\\(\\(\\sw\\|\\s_\\)+\\)\"?\\s *[<_]" + nil + t) + (buffer-substring (match-beginning 1) + (match-end 1))))) + (and + sourcemod ; the file may have been deleted + objname ; may not have been able to + ; find name + (ess-modtime-gt (ess-object-modtime objname) sourcemod) + (not (y-or-n-p + (format + "The ESS object %s is newer than this file. Continue? " + objname))) + (error "Aborted")))))) + +(define-obsolete-function-alias 'ess-check-source #'ess-save-file "ESS 19.04") +(defun ess-save-file (file) + "If FILE (a string) has an unsaved buffer, offer to save it. +Return t if the buffer existed and was modified, but was not +saved. If `ess-save-silently' is non-nil, the buffer is +saved without offering." + (when-let ((buff (find-buffer-visiting file))) + (when (and (buffer-modified-p buff) + (or (eql ess-save-silently t) + (and (eql ess-save-silently 'auto) + (or (not compilation-ask-about-save) + (bound-and-true-p + ;; Only added in Emacs 26.1 + auto-save-visited-mode))) + (y-or-n-p + (format "Buffer %s is modified. Save? " + (buffer-name buff))))) + (with-current-buffer buff + (save-buffer))) + (buffer-modified-p buff))) + + +;;*;; Error messages + +(defun ess-parse-errors (&optional showerr _reset) + "Jump to error in last loaded ESS source file. +With prefix argument SHOWERR, only show the errors ESS reported. RESET +is for compatibility with `next-error' and is ignored." + (interactive "P") + (ess-make-buffer-current) + (let ((errbuff (get-buffer ess-error-buffer-name))) + (when (not errbuff) + (error "You need to do a load first!")) + (set-buffer errbuff) + (goto-char (point-max)) + ;; FIXME: R does not give "useful" error messages by default. We + ;; could try to use a more useful one, via + ;; options(error=essErrorHandler) + (cond ((re-search-backward ess-error-regexp nil t) + (let* ((filename (buffer-substring (match-beginning 3) (match-end 3))) + (fbuffer (get-file-buffer filename)) + (linenum + (string-to-number + (buffer-substring (match-beginning 2) (match-end 2)))) + (errmess (buffer-substring (match-beginning 1) (match-end 1)))) + (if showerr + (ess-display-temp-buffer errbuff) + (if fbuffer nil + (setq fbuffer (find-file-noselect filename)) + (with-current-buffer fbuffer + ;; TODO: ess-mode is surely wrong here, but I don't + ;; think we need this whole function anymore? + (when (fboundp 'ess-mode) + (ess-mode)))) + (pop-to-buffer fbuffer) + (ess-goto-line linenum)) + (princ errmess t))) + (t + (message "Not a syntax error.") + (ess-display-temp-buffer errbuff))))) + +(defun ess-error (msg) + "Something bad has happened. +Display the S buffer, and cause an error displaying MSG." + (declare (obsolete error "ESS 18.10")) + (display-buffer (process-buffer (get-process ess-local-process-name))) + (error msg)) + +(provide 'ess-inf) +;;; ess-inf.el ends here diff --git a/elpa/ess-20230419.1527/ess-jags-d.el b/elpa/ess-20230419.1527/ess-jags-d.el new file mode 100644 index 00000000..5700f337 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-jags-d.el @@ -0,0 +1,257 @@ +;;; ess-jags-d.el --- ESS[JAGS] dialect -*- lexical-binding: t; -*- + +;; Copyright (C) 2009-2022 Free Software Foundation, Inc. + +;; Author: Rodney Sparapani +;; Created: 13 March 2008 +;; Maintainer: ESS Core Team + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Code: + +(require 'ess-bugs-d) +(require 'ess-utils) +(require 'ess-inf) +(require 'ess-mode) + +(defvar ess-jags-command "jags" "Default JAGS program in PATH.") +(make-local-variable 'ess-jags-command) + +(defvar ess-jags-monitor '("") "Default list of variables to monitor.") +(make-local-variable 'ess-jags-monitor) + +(defvar ess-jags-thin 1 "Default thinning parameter.") +(make-local-variable 'ess-jags-thin) + +(defvar ess-jags-chains 1 "Default number of chains.") +(make-local-variable 'ess-jags-chains) + +(defvar ess-jags-burnin 10000 "Default burn-in.") +(make-local-variable 'ess-jags-burnin) + +(defvar ess-jags-update 10000 "Default number of updates after burnin.") +(make-local-variable 'ess-jags-update) + +(defvar ess-jags-system t "Default whether JAGS recognizes the system command.") + +(defvar ess-jags-font-lock-keywords + (list + ;; .jag files + (cons "#.*\n" font-lock-comment-face) + + (cons "^[ \t]*\\(model\\|var\\)\\>" + font-lock-keyword-face) + + (cons (concat "\\& " ess-bugs-file-root ".jog ") + ;else + "> " ess-bugs-file-root ".jog 2>&1 ") + + ; ;.txt not recognized by BOA and impractical to over-ride + ; "&& (rm -f " ess-bugs-file-root ".ind; " + ; "ln -s " ess-bugs-file-root "index.txt " ess-bugs-file-root ".ind; " + ; "for i in " ess-jags-temp-chains "; do; " + ; "rm -f " ess-bugs-file-root "$i.out; " + ; "ln -s " ess-bugs-file-root "chain$i.txt " ess-bugs-file-root "$i.out; done) " + + ess-bugs-batch-post-command) + + (comint-send-input) + )) + +(defun ess-jags-na-bug () + "ESS[JAGS]: Perform Next-Action for .jag" + + (if (equal 0 (buffer-size)) (ess-jags-switch-to-suffix ".jag") + ;else + (ess-save-and-set-local-variables) + (ess-jags-switch-to-suffix ".jmd" + ess-jags-chains ess-jags-monitor ess-jags-thin ess-jags-burnin ess-jags-update)) + ) + +;;;###autoload +(define-derived-mode ess-jags-mode ess-bugs-mode "ESS[JAGS]" + "Major mode for JAGS." + (setq-local comment-start "#") + (setq font-lock-defaults '(ess-jags-font-lock-keywords nil t)) + (setq ess-language "S") ; mimic S for ess-smart-underscore + (unless (and (fboundp 'w32-shell-dos-semantics) + (w32-shell-dos-semantics)) + (add-hook 'comint-output-filter-functions #'ess-bugs-exit-notify-sh)) + ) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Jj][Aa][Gg]\\'" . ess-jags-mode)) + +(provide 'ess-jags-d) + +;;; ess-jags-d.el ends here diff --git a/elpa/ess-20230419.1527/ess-julia.el b/elpa/ess-20230419.1527/ess-julia.el new file mode 100644 index 00000000..56548e4a --- /dev/null +++ b/elpa/ess-20230419.1527/ess-julia.el @@ -0,0 +1,463 @@ +;; ess-julia.el --- ESS julia mode and inferior interaction -*- lexical-binding: t; -*- + +;; Copyright (C) 2012-2022 Free Software Foundation, Inc. +;; Author: Vitalie Spinu +;; Maintainer: Vitalie Spinu +;; Created: 02-04-2012 (ESS 12.03) +;; Keywords: ESS, julia + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Customize inferior-julia-program to point to your julia binary +;; and start the inferior with M-x julia. + +;; As of Sept 2015, this file depends heavily on julia-mode.el from the Julia +;; sources. If you install ESS using `make', this will work fine, otherwise +;; ensure that julia-mode.el is on your path before loading this file. + +;;; Code: + +(require 'ess-help) +(require 'ess-inf) +(require 'ess-r-mode) +(require 'ess-utils) +;; Don't require `julia-mode' to compile this file. +(when t (require 'julia-mode)) +(declare-function julia-mode "julia-mode" ()) +(declare-function julia-latexsub "julia-mode" ()) +(defvar julia-mode-syntax-table) + +(defvar ac-prefix) +(declare-function company-in-string-or-comment "company") +(declare-function company-doc-buffer "company") + +(defcustom inferior-julia-args "" + "String of arguments (see `julia --help') used when starting julia." + :group 'ess-julia + :type 'string) + +(eval-when-compile + (require 'cl-lib)) + +(defun ess-julia-send-string-function (process string _visibly) + "Send the Julia STRING to the PROCESS. +VISIBLY is not currently used." + (let ((file (concat temporary-file-directory "julia_eval_region.jl"))) + (with-temp-file file + (insert string)) + (process-send-string process (format ess-load-command file)))) + + +;;; HELP +(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "julia")) + (append (with-current-buffer (ess--foreground-command "ESS.all_help_topics()\n") + (split-string (buffer-string) "\n")) + (ess-julia--get-objects proc))) + +(defun ess-julia--retrieve-topics (url) + (with-current-buffer (url-retrieve-synchronously url) + (require 'url) + (goto-char (point-min)) + (let (out) + (while (re-search-forward + "toctext[ \"]+href=\"\\([^>]+\\)\">\\([^<]+\\) ") + (inferior-ess-secondary-prompt . nil) + (inferior-ess-prompt . "\\w*> ") + (ess-local-customize-alist . ess-julia-customize-alist) + (inferior-ess-program . inferior-julia-program) + (ess-load-command . "include(expanduser(\"%s\"))\n") + (ess-funargs-command . "ESS.fun_args(\"%s\")\n") + (ess-dump-error-re . "in \\w* at \\(.*\\):[0-9]+") + (ess-error-regexp . "\\(^\\s-*at\\s-*\\(?3:.*\\):\\(?2:[0-9]+\\)\\)") + (ess-error-regexp-alist . ess-julia-error-regexp-alist) + (ess-mode-completion-syntax-table . ess-julia-completion-syntax-table) + ;; (inferior-ess-objects-command . inferior-ess-r-objects-command) + ;; (inferior-ess-search-list-command . "search()\n") + (inferior-ess-help-command . "ESS.help(\"%s\")\n") + ;; (inferior-ess-help-command . "help(\"%s\")\n") + (ess-language . "julia") + (ess-dialect . "julia") + (ess-suffix . "jl") + (ess-dump-filename-template . (replace-regexp-in-string + "S$" ess-suffix ; in the one from custom: + ess-dump-filename-template-proto)) + (ess-mode-editing-alist . nil) + (ess-change-sp-regexp . nil );ess-r-change-sp-regexp) + (ess-help-sec-regex . ess-help-r-sec-regex) + (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) + (ess-function-pattern . ess-r-function-pattern) + (ess-object-name-db-file . "ess-jl-namedb.el" ) + (ess-smart-operators . ess-r-smart-operators) + (inferior-ess-exit-command . "exit()\n") + ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help? + (inferior-ess-language-start . nil) + (ess-STERM . "iESS") + (ess-editor . ess-r-editor) + (ess-pager . ess-r-pager) + (ess-getwd-command . "pwd()\n") + (ess-setwd-command . "cd(expanduser(\"%s\"))\n")) + "Variables to customize for Julia.") + +(cl-defmethod ess--help-web-search-override (cmd &context (ess-dialect "julia")) + "Offer to search the web for a Julia command." + (browse-url (format "https://docs.julialang.org/en/latest/search/?q=%s" cmd))) + +(defvar ess-julia-completion-syntax-table + (let ((table (copy-syntax-table ess-r-mode-syntax-table))) + (modify-syntax-entry ?. "_" table) + ;; (modify-syntax-entry ?: "_" table) + ;; (modify-syntax-entry ?$ "_" table) + (modify-syntax-entry ?@ "_" table) + table) + "Syntax table used for completion and help symbol lookup. +It makes underscores and dots word constituent chars.") + +(cl-defmethod ess-help-commands (&context (ess-dialect "julia")) + '((packages . "_ess_list_categories()\n") + (package-index . "_ess_print_index(\"%s\")\n") + (index-keyword-reg . "^\\(.*+\\):$*") + (index-start-reg . ":"))) + +(defvar ess-julia-mode-syntax-table (copy-syntax-table julia-mode-syntax-table)) + +(defvar ess-julia-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map ess-mode-map) + map) + "Keymap for `ess-julia-mode'.") + +;;;###autoload +(define-derived-mode ess-julia-mode julia-mode "ESS[julia]" + "Major mode for julia files." + :group 'ess-Julia + (setq-local ess-local-customize-alist ess-julia-customize-alist) + (setq ess-dialect "julia") + (ess-setq-vars-local ess-julia-customize-alist) + ;; eldoc + (ess--setup-eldoc #'ess-julia-eldoc-function) + ;; auto-complete + (ess--setup-auto-complete '(ac-source-ess-julia-objects)) + ;; company + (ess--setup-company '(company-ess-julia-objects)) + ;; for emacs >= 24 + (remove-hook 'completion-at-point-functions #'ess-filename-completion 'local) ;; should be first + (add-hook 'completion-at-point-functions #'ess-julia-object-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-filename-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-julia-latexsub-completion nil 'local) + (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))) + +;; Inferior mode +(defvar inferior-ess-julia-mode-syntax-table + (copy-syntax-table ess-julia-mode-syntax-table) + "Syntax table for `inferior-ess-julia-mode'.") + +(define-derived-mode inferior-ess-julia-mode inferior-ess-mode "iESS[julia]" + "Major mode for inferior julia processes." + :group 'ess-Julia + (ess-setq-vars-local ess-julia-customize-alist) + (setq-local comint-use-prompt-regexp t) + (setq comint-prompt-regexp (concat "^" inferior-ess-prompt)) + (setq ess-dialect "julia") + ;; eldoc + (ess--setup-eldoc #'ess-julia-eldoc-function) + ;; auto-complete + (ess--setup-auto-complete '(ac-source-ess-julia-objects) t) + ;; company + (ess--setup-company '(company-ess-julia-objects) t) + (remove-hook 'completion-at-point-functions #'ess-filename-completion 'local) ;; should be first + (add-hook 'completion-at-point-functions #'ess-julia-object-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-filename-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-julia-latexsub-completion nil 'local) + (setq comint-input-sender #'ess-julia-input-sender)) + +(defvar ess-julia-mode-hook nil) +(defvar ess-julia-post-run-hook nil + "Functions run in process buffer after starting julia process.") + +;;;###autoload +(defun run-ess-julia (&optional start-args) + "Start an inferior julia process. +Optional prefix START-ARGS (\\[universal-argument]) allows to set +command line arguments, such as --load=. This should be OS +agnostic. If you have certain command line arguments that should +always be passed to julia, put them in the variable +`inferior-julia-args'." + (interactive "P") + ;; get settings, notably inferior-julia-program : + (if (null inferior-julia-program) + (error "'inferior-julia-program' does not point to 'julia' or 'julia-basic' executable") + (ess-write-to-dribble-buffer ;; for debugging only + (format + "\n(julia): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n" + ess-dialect (current-buffer) start-args current-prefix-arg)) + (let* ((jl-start-args + (concat inferior-julia-args " " ; add space just in case + (if start-args + (read-string + (concat "Starting Args" + (if inferior-julia-args + (concat " [other than '" inferior-julia-args "']")) + " ? ")) + nil)))) + (let ((inf-buf (inferior-ess jl-start-args ess-julia-customize-alist))) + (with-current-buffer inf-buf + (ess--tb-start) + ;; Remove ` from julia's logo + (goto-char (point-min)) + (while (re-search-forward "`" nil t) + (replace-match "'")) + ;; Remove an offending unmatched parenthesis + (goto-char (point-min)) + (forward-line 4) + (when (re-search-forward "(" nil t) + (replace-match "|")) + (goto-char (point-max)) + ;; --> julia helpers from ../etc/ess-julia.jl : + (ess--inject-code-from-file (format "%sess-julia.jl" ess-etc-directory)) + (run-mode-hooks 'ess-julia-post-run-hook)) + inf-buf)))) + +;;;###autoload +(defalias 'julia #'run-ess-julia) + +(cl-defmethod ess--help-major-mode (&context (ess-dialect "julia")) + (ess-julia-help-mode)) + +(define-derived-mode ess-julia-help-mode ess-help-mode "ESS[Julia] Help" + "Major mode for Julia documentation." + :group 'ess-help + (let ((inhibit-read-only t)) + ;; Julia help buffers can contain color if julia starts with + ;; --color=yes + (ansi-color-apply-on-region (point-min) (point-max)))) + +(add-to-list 'auto-mode-alist '("\\.jl\\'" . ess-julia-mode)) + +(provide 'ess-julia) +;;; ess-julia.el ends here diff --git a/elpa/ess-20230419.1527/ess-mode.el b/elpa/ess-20230419.1527/ess-mode.el new file mode 100644 index 00000000..4bc3583f --- /dev/null +++ b/elpa/ess-20230419.1527/ess-mode.el @@ -0,0 +1,685 @@ +;;; ess-mode.el -- Emacs Speaks Statistics root mode. -*- lexical-binding: t; -*- + +;; Copyright (C) 1994-2022 Free Software Foundation, Inc. +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; This file defines ess-mode from which other modes (like ess-r-mode) +;; derive. + +;;; Code: + +(require 'ess) + +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) +(require 'ess-inf) + +;; Silence the byte compiler +(declare-function R "ess-r-mode" (&optional start-args)) +(declare-function S+ "ess-sp6-d" (&optional proc-name)) +(declare-function SAS "ess-sas-d" ()) + +;; FIXME:This one should not be necessary +(declare-function ess-display-help-on-object "ess-help" (object &optional command)) + +;; ESS mode +;; Major mode definition + +;;*;; Hooks + +(defcustom ess-mode-hook nil + "Hook for customizing ESS each time it is entered." + :group 'ess-hooks + :type 'hook) + +(defvar ess-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap yank] #'ess-yank) + (define-key map "\C-c\C-r" #'ess-eval-region) + (define-key map "\C-c\M-r" #'ess-eval-region-and-go) + (define-key map "\C-c\C-b" #'ess-eval-buffer) + (define-key map "\C-c\M-b" #'ess-eval-buffer-and-go) + (define-key map (kbd "C-c C-") #'ess-eval-buffer-from-beg-to-here) + (define-key map (kbd "C-c C-") #'ess-eval-buffer-from-here-to-end) + (define-key map "\C-c\C-f" #'ess-eval-function) + (define-key map "\C-c\M-f" #'ess-eval-function-and-go) + (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) + (define-key map "\C-c\C-p" #'ess-eval-paragraph-and-step) + (define-key map "\C-c\M-p" #'ess-eval-paragraph-and-go) + (define-key map "\C-\M-x" #'ess-eval-region-or-function-or-paragraph) + (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) + (define-key map "\C-c\C-j" #'ess-eval-line) + (define-key map [(control return)] #'ess-eval-region-or-line-visibly-and-step) + (define-key map "\C-c\M-j" #'ess-eval-line-and-go) + ;; FIXME: The next three can only work in S/R - mode + (define-key map "\C-\M-a" #'ess-goto-beginning-of-function-or-para) + (define-key map "\C-\M-e" #'ess-goto-end-of-function-or-para) + (define-key map "\C-xnd" #'ess-narrow-to-defun-or-para) + (define-key map "\C-xnf" #'ess-narrow-to-defun-or-para) + (define-key map "\C-c\C-z" #'ess-switch-to-inferior-or-script-buffer) + (define-key map "\C-c\C-l" #'ess-load-file) + ;;; Make an alias because C-c C-l is taken up by comint in inferiors + (define-key map "\C-c\M-l" #'ess-load-file) + (define-key map "\C-c\C-v" #'ess-display-help-on-object) + (define-key map "\C-c\C-s" #'ess-switch-process) + (define-key map "\C-c\C-k" #'ess-force-buffer-current) + (define-key map "\C-c`" #'ess-show-traceback) + (define-key map [(control ?c) ?~] #'ess-show-call-stack) + (define-key map "\C-\M-q" #'ess-indent-exp) + (define-key map "{" #'skeleton-pair-insert-maybe) + (define-key map "}" #'skeleton-pair-insert-maybe) + (define-key map "\C-\M-h" #'ess-mark-function-or-para) + (define-key map "\t" #'ess-indent-or-complete) + (define-key map "\C-c\C-q" #'ess-quit) + (define-key map "\M-\r" #'ess-use-this-dir) + (define-key map "," #'ess-smart-comma) + (define-key map "\C-c\C-d" 'ess-doc-map) + (define-key map "\C-c\C-e" 'ess-extra-map) + (define-key map "\C-c\C-t" 'ess-dev-map) + map) + "Keymap for `ess-mode'.") + +;; Redefine `indent-new-comment-line' commands for Emacs < 26. Emacs +;; 27 binds M-j to `default-indent-new-line' which calls +;; `comment-line-break-function' if point is in a comment. We set this +;; function in the mode init. +(substitute-key-definition #'indent-new-comment-line + #'ess-indent-new-comment-line + ess-mode-map global-map) + +(defvar ess-extra-map + (let (ess-extra-map) + (define-prefix-command 'ess-extra-map) + (define-key ess-extra-map "\C-d" #'ess-dump-object-into-edit-buffer) + (define-key ess-extra-map "d" #'ess-dump-object-into-edit-buffer) + (define-key ess-extra-map "\C-e" #'ess-execute) + (define-key ess-extra-map "e" #'ess-execute) + (define-key ess-extra-map "\C-i" #'ess-install-library) + (define-key ess-extra-map "i" #'ess-install-library) + (define-key ess-extra-map "\C-l" #'ess-load-library) + (define-key ess-extra-map "l" #'ess-load-library) + (define-key ess-extra-map "\C-r" #'inferior-ess-reload) + (define-key ess-extra-map "r" #'inferior-ess-reload) + (define-key ess-extra-map "\C-s" #'ess-set-style) + (define-key ess-extra-map "s" #'ess-set-style) + (define-key ess-extra-map "\C-t" #'ess-build-tags-for-directory) + (define-key ess-extra-map "t" #'ess-build-tags-for-directory) + (define-key ess-extra-map "\C-w" #'ess-execute-screen-options) + (define-key ess-extra-map "w" #'ess-execute-screen-options) + (define-key ess-extra-map "/" #'ess-set-working-directory) + ess-extra-map) + "ESS extra map.") + +(easy-menu-define + ess-mode-menu ess-mode-map + "Menu for use in `ess-mode'." + '("ESS" ; ESS-mode + ["Load file" ess-load-file t] + ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t] + ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t] + ["Eval region | line" ess-eval-region-or-line-visibly-and-step t] + ["Enter expression" ess-execute t] + ;; sub menus + "------" + ("Process" + ["Goto end of process buffer" ess-switch-to-end-of-ESS t] + ["Switch to process buffer" ess-switch-to-inferior-or-script-buffer t] + ["Switch process" ess-switch-process t] + ;; ["Recreate R and S versions known to ESS" (ess-r-s-versions-creation+menu) t] + ("Start Process" + ["R" R :help "Start a new R process" :active t] + ["S" S :help "Start a new S process" :active t] + ["Sqpe" Sqpe ess-microsoft-p] ;; :help "Start a new Sqpe process" :active t + ["S+6-existing" S+6-existing ess-microsoft-p] ;; :help "Access an existing S process" :active t + ["SAS" SAS-menu t] ;; :help "Start a new SAS process" :active t + ;; The following menu item "Other" is a place-holder that will + ;; be replaced with the other versions of R and Sqpe that can be run. + ;; See `ess-r-define-runners' and ess-site.el + ("Other" + ["No other R or Sqpe versions" nil nil]) + ["About" + (ess-goto-info "Starting up") t] + ;; :help "Read about starting a new ESS process" :active t] + ) + ("Eval visibly " + :filter ess--generate-eval-visibly-submenu) + ["Quit process" ess-quit t] + ["Reload process" inferior-ess-reload t]) + "------" + ("ESS Eval" + ["Eval region | func | para" ess-eval-region-or-function-or-paragraph t] + ["Eval region | func | para & step" ess-eval-region-or-function-or-paragraph-and-step t] + ["Eval region | line & step" ess-eval-region-or-line-visibly-and-step t] + "-----" + ["Eval buffer" ess-eval-buffer t] + ["Eval buffer till here" ess-eval-buffer-from-beg-to-here t] + ["Eval buffer from here" ess-eval-buffer-from-here-to-end t] + ["Eval region" ess-eval-region t] + ["Eval function" ess-eval-function t] + ["Eval line" ess-eval-line t] + ["Eval line & step" ess-eval-line-and-step t] + ["Eval paragraph" ess-eval-paragraph t] + ["Eval paragraph & step" ess-eval-paragraph-and-step t] + ["About" (ess-goto-info "Evaluating code") t] + ) + ("Eval and Go" + ["Eval buffer" ess-eval-buffer-and-go t] + ["Eval region" ess-eval-region-and-go t] + ["Eval function" ess-eval-function-and-go t] + ["Eval line" ess-eval-line-and-go t] + ["Eval paragraph" ess-eval-paragraph-and-go t] + ["About" (ess-goto-info "Evaluating code") t] + ) + ("Motion" + ["Beginning of function or para" ess-goto-beginning-of-function-or-para t] + ["End of function or para" ess-goto-end-of-function-or-para t] + "-----" + ["Backward list" backward-list t] + ["Forward list" forward-list t] + ["Next parenthesis" down-list t] + ["Enclosing parenthesis" backward-up-list t] + ["Backward sexp" backward-sexp t] + ["Forward sexp" forward-sexp t] + ["About" (Info-goto-node "(Emacs)Lists") t] + ) + ("ESS Edit" + ["Edit new object" ess-dump-object-into-edit-buffer t] + ["Complete Filename" comint-replace-by-expanded-filename t] + ["Complete File or Object" ess-indent-or-complete t] + ["Kill sexp" kill-sexp t] + ["Mark function" ess-mark-function-or-para t] + ["Indent expression" ess-indent-exp t] + ["Indent line" ess-indent-command t] + ["Toggle Auto-Fill Mode" auto-fill-mode t] + ["Undo" undo t] + ["About" (ess-goto-info "Edit buffer") t] + ) + "------" + ("start-dev" :visible nil) + ("end-dev" :visible nil) + "------" + ("Font Lock" + :active ess-font-lock-keywords + :filter ess--generate-font-lock-submenu) + "------" + ["Describe" describe-mode t] + ["About editing" (ess-goto-info "Editing") t] + ["Read ESS info" (ess-goto-info "") t] + ["Send bug report" ess-submit-bug-report t])) + +;;;###autoload +(define-derived-mode ess-mode prog-mode "ESS" + "Major mode for editing ESS source. +Optional arg ALIST describes how to customize the editing mode. +Optional arg PROC-NAME is name of associated inferior process. + +\\{ess-mode-map} + +You can send text to the inferior ESS process from other buffers containing +ESS source. + `ess-eval-region' sends the current region to the ESS process. + `ess-eval-buffer' sends the current buffer to the ESS process. + `ess-eval-function' sends the current function to the ESS process. + `ess-eval-line' sends the current line to the ESS process. + `ess-switch-to-ESS' switches the current buffer to the ESS process buffer. + `ess-switch-to-end-of-ESS' switches the current buffer to the ESS process + buffer and puts point at the end of it. + + `ess-eval-region-and-go', `ess-eval-buffer-and-go', + `ess-eval-function-and-go', and `ess-eval-line-and-go' switch to the S + process buffer after sending their text. + + `ess-load-file' sources a file of commands to the ESS process. + +\\[ess-indent-command] indents for ESS code. +\\[backward-delete-char-untabify] converts tabs to spaces as it moves back. +Comments are indented in a similar way to Emacs-lisp mode: + `###' beginning of line + `##' the same level of indentation as the code + `#' the same column on the right, or to the right of such a + column if that is not possible.(default value 40). + \\[indent-for-comment] command automatically inserts such a + `#' in the right place, or aligns such a comment if it is + already inserted. +\\[ess-indent-exp] command indents each line of the syntactic unit following point. + +Variables controlling indentation style: + `ess-indent-offset' + Indentation of ESS statements within surrounding block. + The surrounding block's indentation is the indentation of the line on + which the open-brace appears. + `ess-offset-block' + Indentation of blocks opened with curly braces or anonymous parentheses. + `ess-offset-arguments' + Indentation of function arguments or bracket indices. + `ess-offset-arguments-newline' + Indentation of function arguments or bracket indices when the opening + delimiter is immediately followed by a newline. + `ess-offset-continued' + Indentation style for continued statements. + `ess-align-nested-calls' + Functions whose nested calls should be aligned. + `ess-align-arguments-in-calls' + Calls in which arguments should be aligned. + `ess-align-continuations-in-calls' + Whether ignore indentation after an operator in calls + `ess-align-blocks' + Blocks that should always be aligned vertically. + `ess-indent-from-lhs' + Whether function calls given as argument should be indented from the + parameter name. + `ess-indent-from-chain-start' + Whether to indent arguments from the first of several consecutive calls. + `ess-indent-with-fancy-comments' + Non-nil means distinguish between #, ##, and ### for indentation. + +Furthermore, \\[ess-set-style] command enables you to set up predefined ess-mode +indentation style. See `ess-style-alist' for predefined styles." + :group 'ess + ;; TODO: get rid of these and rely on modes to set variables properly + (when-let ((alist (buffer-local-value 'ess-local-customize-alist (current-buffer)))) + (ess-setq-vars-local alist)) + (when-let ((alist ess-mode-editing-alist)) + (ess-setq-vars-local alist)) + ;; Keep out of the code. + (setq-local indent-tabs-mode nil) + (setq-local comment-line-break-function #'ess-newline-and-indent) + (setq mode-line-process + '(" [" + (:eval (ess--get-mode-line-indicator)) + ess--local-mode-line-process-indicator + "]")) + (add-hook 'ess-idle-timer-functions #'ess-synchronize-dirs nil 'local)) + +(defun ess--get-mode-line-indicator () + "Get `ess--mode-line-process-indicator' from process buffer. +Internal function to be used for dynamic mode-line display in +`ess-mode'." + (if ess-local-process-name + (let* ((proc (get-process ess-local-process-name)) + (buff (when proc (process-buffer proc)))) + (if (and proc (buffer-live-p buff)) + (with-current-buffer buff + (mapcar (lambda (e) (eval e t)) ess--mode-line-process-indicator)) + "none")) + "none")) + + +;;; User commands in ess-mode + +(defun ess-install-library (&optional update package) + "Install PACKAGE for current dialect. +With UPDATE, update cached package list." + (interactive "P") + (ess-install-library--override update package)) + +(cl-defgeneric ess-install-library--override (update package) + "See `ess-install-library' for UPDATE, PACKAGE." + (when update (message "Don't know how to update for %s" ess-dialect)) + (error "Cannot install %s, not available for %s" package ess-dialect)) + + +;; Motion / manipulation commands + +(defun ess-goto-beginning-of-function-or-para () + "If inside a function go to the beginning of it. +Otherwise go to the beginning of paragraph." + (interactive) + (let ((start-pos (point)) + beg end) + (beginning-of-defun) + (setq beg (point)) + (end-of-defun) + (setq end (point)) + (goto-char beg) + (unless (and (< beg start-pos) + (> end start-pos)) + (let ((par-pos (save-excursion + (goto-char start-pos) + (forward-comment most-negative-fixnum) + (backward-paragraph) + (forward-comment most-positive-fixnum) + (point)))) + (if (< end par-pos) + (goto-char par-pos) + (goto-char beg)))))) + +(defun ess-goto-end-of-function-or-para () + "If inside a function go to end of it. +Otherwise go to the end of paragraph." + (interactive) + (let ((pos (point)) + beg end) + (end-of-defun) + (setq end (point)) + (beginning-of-defun) + (setq beg (point)) + (goto-char end) + (when (or (< beg pos) + (> end pos)) + (let ((par-pos (save-excursion + (goto-char pos) + (forward-comment most-positive-fixnum) + (forward-paragraph) + (point)))) + (when (<= par-pos beg) + (goto-char par-pos)))))) + +(defun ess-mark-function-or-para () + "Put mark at end of ESS function, point at beginning." + (interactive) + (ess-goto-beginning-of-function-or-para) + (push-mark (point)) + (ess-goto-end-of-function-or-para) + (exchange-point-and-mark)) + +(define-obsolete-function-alias 'ess-mark-function + #'ess-mark-function-or-para "15.09") + +(defun ess-narrow-to-defun-or-para () + "Make text outside current function invisible. +If text is already narrowed, this is removed before narrowing to the +current function." + (interactive) + (save-excursion + (widen) + (let* ((beg (progn (ess-goto-beginning-of-function-or-para) + (point))) + (end (progn (ess-goto-end-of-function-or-para) + (point)))) + (narrow-to-region beg end)))) + +(define-obsolete-function-alias 'ess-narrow-to-defun + #'ess-narrow-to-defun-or-para "15.09") + +;; FIXME: Support soft breaks with `insert-and-inherit'. See +;; https://www.gnu.org/software/emacs/manual/html_node/emacs/Hard-and-Soft-Newlines.html +(defun ess-newline-and-indent (&optional _soft) + (ess-indent-new-comment-line)) + +(defun ess-indent-new-comment-line () + "Like `indent-new-comment-line' but accounts for roxygen comments." + (interactive) + (cond ((and (fboundp 'ess-roxy-indent-new-comment-line) + (string= ess-dialect "R")) + (ess-roxy-indent-new-comment-line)) + (t + (indent-new-comment-line)))) + + +;;; Formatting / indentation +(defvar-local ess--installed-style-vars nil + "A cons of the form (STYLE . VARS). +VARS is a list of all style vars which were not set explicitly to +buffer local values by the user in mode hooks.") + +(defun ess-set-style (&optional style _quiet) + "Set up the `ess-mode' style variables from the `ess-style' variable. +If STYLE argument is given, use that instead. It makes the ESS +indentation style variables buffer local. QUIET is for backward +compatibility and is ignored. + +In programs, when STYLE is nil, the `ess-style' is installed. In +this case, if `ess-style' is buffer local, all settings are +overwritten, otherwise only those settings which are not already +buffer local. For example, `ess-style' is buffer local when it is +set in .dir-locals and thus must have priority over the user +settings in the mode hook." + (interactive + (list (let ((styles (mapcar (lambda (x) (symbol-name (car x))) + ess-style-alist))) + (intern (ess-completing-read + "Set ESS mode indentation style" + styles nil t nil nil ess-style))))) + (let* ((keep-local (and (null style) + (not (local-variable-p 'ess-style)))) + (style (or style ess-style)) + (style-alist (or (cdr (assq style ess-style-alist)) + (error "Bad ESS style: %s" style))) + (vars (if keep-local + ;; Install, but Keep user's buffer-local settings. + (cl-loop for (var . _) in (cdr (assq 'DEFAULT ess-style-alist)) + unless (local-variable-p var) + collect var) + (mapcar #'car style-alist)))) + (when (called-interactively-p 'any) + (message "Set indentation style to %s" style)) + (mapc (lambda (var) + (make-local-variable var) + (set var (cdr (assq var style-alist)))) + vars) + style)) + +(defun ess-indent-command (&optional whole-exp) + "Indent current line as ESS code, or in some cases insert a tab character. +If `tab-always-indent' is non-nil, always indent current line. +Otherwise, indent the current line only if point is at the left +margin or in the line's indentation; otherwise insert a tab. If +given, WHOLE-EXP means indent rigidly all the lines of the +expression starting after point so that this line becomes +properly indented. The relative indentation among the lines of +the expression are preserved. + +If in a roxygen block at the beginning of the line with +`ess-roxy-hide-show-p' non-nil, call `ess-roxy-toggle-hiding' +instead of indenting." + (interactive "P") + (cond ((and (fboundp 'ess-roxy-entry-p) + (fboundp 'ess-roxy-toggle-hiding) + (bolp) + (ess-roxy-entry-p) + ess-roxy-hide-show-p) + (ess-roxy-toggle-hiding)) + (whole-exp + ;; If arg, always indent this line as S + ;; and shift remaining lines of expression the same amount. + (let ((shift-amt (funcall indent-line-function)) + beg end) + (save-excursion + (if tab-always-indent + (beginning-of-line)) + (setq beg (point)) + (backward-up-list 1) + (forward-list 1) + (setq end (point)) + (goto-char beg) + (forward-line 1) + (setq beg (point))) + (if (> end beg) + (indent-code-rigidly beg end shift-amt)))) + ((and (not tab-always-indent) + (save-excursion + (skip-chars-backward " \t") + (not (bolp)))) + (insert-tab)) + (t (funcall indent-line-function)))) + +(defun ess-indent-or-complete () + "When region is selected indent the region. +Otherwise, if `tab-always-indent' is \\='complete, try to indent, if +code is already indented, complete instead. Also see +`ess-first-tab-never-complete'." + (interactive) + (if (use-region-p) + (indent-region (region-beginning) (region-end)) + (let ((shift (let ((indent (current-indentation))) + (ess-indent-command) + (- (current-indentation) indent)))) + (when (and (or (equal tab-always-indent 'complete) + ess-tab-complete-in-script) + (numberp shift) ;; can be nil if tab-always-indent is nil + (equal shift 0) + (or (eq last-command 'ess-indent-or-complete) + (null ess-first-tab-never-complete) + (and (eq ess-first-tab-never-complete 'unless-eol) + (looking-at "\\s-*$")) + (and (eq ess-first-tab-never-complete 'symbol) + (not (looking-at "\\w\\|\\s_"))) + (and (eq ess-first-tab-never-complete 'symbol-or-paren) + (not (looking-at "\\w\\|\\s_\\|\\s)"))) + (and (eq ess-first-tab-never-complete 'symbol-or-paren-or-punct) + (not (looking-at "\\w\\|\\s_\\|\\s)\\|\\s."))))) + (completion-at-point))))) + +(defun ess-indent-exp () + "Indent each line of the ESS grouping following point." + (interactive) + (cond ((and (fboundp 'ess-r-indent-exp) + (string= ess-dialect "R")) + (ess-r-indent-exp)) + (t + (save-excursion + (let ((start (point)) + (end (ignore-errors (forward-sexp 1) (point)))) + (when end + (indent-region start end))))))) + +(defun ess-indent-line () + "Indent current line as ESS code. +Return the amount the indentation changed by." + (declare (obsolete 'indent-line-function "ESS 19.04")) + (funcall indent-line-function)) + + +;;; Dump Objects + +(defun ess-dump-object-into-edit-buffer (object) + "Edit an ESS OBJECT in its own buffer. +Without a prefix argument, this simply finds the file pointed to by +`ess-source-directory'. If this file does not exist, or if a +prefix argument is given, a dump() command is sent to the ESS process to +generate the source buffer." + (interactive + (progn + (ess-force-buffer-current "Process to dump from: ") + (ess-read-object-name "Object to edit"))) + (let* ((dirname (file-name-as-directory + (if (stringp ess-source-directory) + ess-source-directory + (with-current-buffer (process-buffer (ess-get-process + ess-local-process-name)) + (ess-setq-vars-local ess-local-customize-alist) + (apply ess-source-directory nil))))) + (filename (concat dirname (convert-standard-filename (format ess-dump-filename-template object)))) + (old-buff (get-file-buffer filename))) + ;; If the directory doesn't exist, offer to create it + (unless (file-exists-p (directory-file-name dirname)) + (if (y-or-n-p (format "Directory %s does not exist. Create it? " dirname)) + (make-directory (directory-file-name dirname)) + (error "Directory %s does not exist" dirname))) + ;; Three options: + ;; (1) Pop to an existing buffer containing the file in question + ;; (2) Find an existing file + ;; (3) Create a new file by issuing a dump() command to S + ;; Force option (3) if there is a prefix arg + (cond (current-prefix-arg + (ess-dump-object object filename)) + (old-buff + (pop-to-buffer old-buff)) + ((file-exists-p filename) + (ess-find-dump-file-other-window filename) + (message "Read %s" filename)) + (t (ess-dump-object object filename))))) + +(defun ess-dump-object (object filename) + "Dump the ESS object OBJECT into file FILENAME." + (unless (file-writable-p filename) + (error "Can't dump %s as %f is not writeable" object filename)) + (let ((dump-cmd (format inferior-ess-dump-command object filename))) + ;; Make sure we start fresh + (when (get-file-buffer filename) + (kill-buffer (get-file-buffer filename))) + (ess-command dump-cmd) + (message "Dumped in %s" filename) + (ess-find-dump-file-other-window filename) + ;; PD, 1Apr97 + ;;This ensures that the object gets indented according to ess-mode, + ;;not as the R/S deparser does it. At the same time, it gets rid + ;;of the mess generated by sending TAB characters to the readline + ;;functions in R when you eval-buffer-*. + (indent-region (point-min-marker) (point-max-marker) nil) + (set-buffer-modified-p nil) ; no need to safe just because of indenting + ;; Don't make backups for temporary files; it only causes clutter. + ;; The ESS object itself is a kind of backup, anyway. + (unless ess-keep-dump-files + (make-local-variable 'make-backup-files) + (setq make-backup-files nil)) + ;; Don't get confirmation to delete dumped files when loading + (when (eq ess-keep-dump-files 'check) + (setq ess-keep-dump-files nil)) + ;; Delete the file if necessary + (when ess-delete-dump-files + (delete-file (buffer-file-name))))) + +(defun ess-find-dump-file-other-window (filename) + "Find ESS source file FILENAME in another window." + (unless (file-readable-p filename) + (ess-write-to-dribble-buffer + (format "%s does not exist. Bad dump, starting fresh." filename))) + ;; Generate a buffer with the dumped data + (find-file-other-window filename) + (auto-save-mode 1) ; Auto save in this buffer + (when (and ess-function-template + (goto-char (point-max)) + (re-search-backward ess-dumped-missing-re nil t)) + (replace-match ess-function-template t t) + (set-buffer-modified-p nil) ; Don't offer to save if killed now + (goto-char (point-min)) + (ignore-errors + ;; This may fail if there are no opens + (down-list 1)))) + + +;;; Runners + +(defun ess-define-runner (name dialect &optional path) + "Create a function NAME. +This function starts the inferior process with the specified +version. DIALECT can be \"R,\" \"S,\", \"SAS.\" If given, PATH +should be the absolute path to the program. It defaults to NAME." + (let ((name name) + (dialect dialect) + (path path)) + (fset (intern name) + (lambda (&optional start-args) + "Start this process version in an inferior ESS buffer. +Function defined using `ess-define-runner'." + (interactive "P") + (cond ((string= dialect "R") + (let ((inferior-ess-r-program (or path name))) + (require 'ess-r-mode) + (R start-args))) + ((string= dialect "S") + (let ((inferior-S+-program (or path name))) + (require 'ess-sp6-d) + (S+))) + ((string= dialect "SAS") + (let ((inferior-SAS-program (or path name))) + (require 'ess-sas-d) + (SAS)))))))) + + + +(provide 'ess-mode) + +;;; ess-mode.el ends here diff --git a/elpa/ess-20230419.1527/ess-pkg.el b/elpa/ess-20230419.1527/ess-pkg.el new file mode 100644 index 00000000..094240ac --- /dev/null +++ b/elpa/ess-20230419.1527/ess-pkg.el @@ -0,0 +1,23 @@ +(define-package "ess" "20230419.1527" "Emacs Speaks Statistics" + '((emacs "25.1")) + :commit "5c4ae91cefa5c56fd13b204a9a996825af836a67" :authors + '(("David Smith" . "dsmith@stats.adelaide.edu.au") + ("A.J. Rossini" . "blindglobe@gmail.com") + ("Richard M. Heiberger" . "rmh@temple.edu") + ("Kurt Hornik" . "Kurt.Hornik@R-project.org") + ("Martin Maechler" . "maechler@stat.math.ethz.ch") + ("Rodney A. Sparapani" . "rsparapa@mcw.edu") + ("Stephen Eglen" . "stephen@gnu.org") + ("Sebastian P. Luque" . "spluque@gmail.com") + ("Henning Redestig" . "henning.red@googlemail.com") + ("Vitalie Spinu" . "spinuvit@gmail.com") + ("Lionel Henry" . "lionel.hry@gmail.com") + ("J. Alexander Branham" . "alex.branham@gmail.com")) + :maintainers + '(("ESS Core Team" . "ESS-core@r-project.org")) + :maintainer + '("ESS Core Team" . "ESS-core@r-project.org") + :url "https://ess.r-project.org/") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/ess-20230419.1527/ess-r-completion.el b/elpa/ess-20230419.1527/ess-r-completion.el new file mode 100644 index 00000000..3c388cb4 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-completion.el @@ -0,0 +1,518 @@ +;;; ess-r-completion.el --- R completion -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2022 Free Software Foundation, Inc. +;; Author: Vitalie Spinu +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; Provide completion support in R buffers. + +;;; Code: + +(require 'cl-lib) +(require 'ess-inf) +(require 'ess-help) + +(eval-when-compile + (require 'subr-x)) + +(defvar ac-auto-start) +(defvar ac-prefix) +(defvar ac-point) +(defvar ac-use-comphist) +(declare-function company-begin-backend "company") +(declare-function company-doc-buffer "company") + +(defcustom ess-R-argument-suffix " = " + "Suffix appended by `ac-source-R' and `ac-source-R-args' to candidates." + :group 'ess-R + :type 'string) + + +;;;*;;; ElDoc + +(defun ess-r-eldoc-function (&rest _ignored) + "Return the doc string, or nil. +If an ESS process is not associated with the buffer, do not try +to look up any doc strings." + (when eldoc-mode + (when-let ((proc (ess-get-next-available-bg-process)) + (funname (or (and ess-eldoc-show-on-symbol ;; Aggressive completion + (thing-at-point 'symbol)) + (car (ess--fn-name-start))))) + (let* ((args (ess-function-arguments funname proc)) + (bargs (cadr args)) + (doc (mapconcat (lambda (el) + (if (equal (car el) "...") + "..." + (concat (car el) "=" (cdr el)))) + bargs ", ")) + (margs (nth 2 args)) + (W (- (window-width (minibuffer-window)) (+ 4 (length funname)))) + (multiline (eq t eldoc-echo-area-use-multiline-p)) + doc1) + (when doc + (setq doc (ess-eldoc-docstring-format funname doc (not multiline))) + (when (or multiline (and margs (< (length doc1) W))) + (setq doc1 (concat doc (propertize " || " 'face font-lock-function-name-face))) + (while (and margs (< (length doc1) W)) + (let ((head (pop margs))) + (unless (assoc head bargs) + (setq doc doc1 + doc1 (concat doc1 head "=, "))))) + (when (equal (substring doc -2) ", ") + (setq doc (substring doc 0 -2))) + (when (and margs (< (length doc) W)) + (setq doc (concat doc " {--}")))) + doc))))) + +(defun ess-eldoc-docstring-format (funname doc &optional truncate) + (save-match-data + (let* (;; Subtract 1 from window width since will cause a wraparound and + ;; resize of the echo area. + (W (1- (- (window-width (minibuffer-window)) + (+ 2 (length funname)))))) + (setq doc + (if (or (<= (length doc) W) + (null ess-eldoc-abbreviation-style) + (eq 'none ess-eldoc-abbreviation-style)) + doc + ;;MILD filter + (setq doc (replace-regexp-in-string "TRUE" "T" doc)) + (setq doc (replace-regexp-in-string "FALSE" "F" doc)) + (if (or (<= (length doc) W) + (eq 'mild ess-eldoc-abbreviation-style)) + doc + ;;NORMAL filter (deal with long defaults) + (setq doc (replace-regexp-in-string + ;; function calls inside default docs foo(xxxx{..}) + "([^)]\\{8\\}\\([^)]\\{4,\\}\\))" + "{.}" doc nil nil 1)) + (if (<= (length doc) W) + doc + (setq doc (replace-regexp-in-string + " +[^ \t=,\"\]+=[^ \t]\\{10\\}\\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)" + "{.}," doc nil nil 1)) + (if (<= (length doc) W) + doc + (setq doc (replace-regexp-in-string + " +[^ \t=,\"]+=\\([^ \t]\\{10,\\}\\)\\(,\\|\\'\\)" + "{.}," doc nil nil 1)) + (if (or (<= (length doc) W) + (eq 'normal ess-eldoc-abbreviation-style)) + doc + ;;STRONG filter (replace defaults) + (setq doc (replace-regexp-in-string + " *[^ \t=,\"\\]* = \\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)" + "{.}," doc nil nil 1)) + (if (<= (length doc) W) + doc + (setq doc (replace-regexp-in-string + "\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+=\\|\\'\\)" + "" doc nil nil 1)) + (setq doc (replace-regexp-in-string + "\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+,\\|\\'\\)" + "" doc nil nil 1)) + (if (or (<= (length doc) W) + (eq 'strong ess-eldoc-abbreviation-style)) + doc + ;;AGGRESSIVE filter (truncate what is left) + (concat (substring doc 0 (- W 4)) "{--}"))))))))) + (when (and truncate (> (length doc) W)) + (setq doc (concat (substring doc 0 (- W 4)) "{--}"))) + (format "%s: %s" (propertize funname 'face 'font-lock-function-name-face) doc)))) + + +;;;*;;; OBJECTS + +(defun ess-r-object-completion () + "Return completions at point as required in `completion-at-point-functions'." + (if (ess-make-buffer-current) + (let* ((funstart (cdr (ess--fn-name-start))) + (completions (ess-r-get-rcompletions funstart)) + (token (pop completions))) + (when completions + (list (- (point) (length token)) (point) + completions))) + (when (string-match "complete" (symbol-name last-command)) + (message "No ESS process associated with current buffer") + nil))) + +(defun ess-complete-object-name () + "Perform completion on object preceding point. +Uses `ess-r-complete-object-name' when `ess-use-R-completion' is non-nil, +and `ess-internal-complete-object-name' otherwise." + (interactive) + (if (ess-make-buffer-current) + (if ess-use-R-completion + (ess-r-complete-object-name) + (ess-internal-complete-object-name)) + ;; else give a message on second invocation + (when (string-match "complete" (symbol-name last-command)) + (message "No ESS process associated with current buffer") + nil))) + +(define-obsolete-function-alias 'ess-list-object-completions #'ess-complete-object-name "ESS 19.04") + +;; This one is needed for R <= 2.6.x -- hence *not* obsoleting it +(defun ess-internal-complete-object-name () + "Perform completion on `ess-language' object preceding point. +The object is compared against those objects known by +`ess-get-object-list' and any additional characters up to ambiguity are +inserted. Completion only works on globally-known objects (including +elements of attached data frames), and thus is most suitable for +interactive `command-line' entry, and not so much for function editing +since local objects (e.g. argument names) aren't known. + +Use \\[ess-resynch] to re-read the names of the attached directories. +This is done automatically (and transparently) if a directory is +modified (S only!), so the most up-to-date list of object names is always +available. However attached dataframes are *not* updated, so this +command may be necessary if you modify an attached dataframe." + (ess-make-buffer-current) + (if (memq (char-syntax (preceding-char)) '(?w ?_)) + (let* ((comint-completion-addsuffix nil) + (bounds (ess-bounds-of-symbol)) + (beg (car bounds)) + (end (cdr bounds)) + (full-prefix (buffer-substring beg end)) + (pattern full-prefix) + ;; See if we're indexing a list with `$' + (listname (if (string-match "\\(.+\\)\\$\\(\\(\\sw\\|\\s_\\)*\\)$" + full-prefix) + (progn + (setq pattern + (if (not (match-beginning 2)) "" + (substring full-prefix + (match-beginning 2) + (match-end 2)))) + (substring full-prefix (match-beginning 1) + (match-end 1))))) + ;; are we trying to get a slot via `@' ? + (classname (if (string-match "\\(.+\\)@\\(\\(\\sw\\|\\s_\\)*\\)$" + full-prefix) + (progn + (setq pattern + (if (not (match-beginning 2)) "" + (substring full-prefix + (match-beginning 2) + (match-end 2)))) + (ess-write-to-dribble-buffer + (format "(ess-C-O-Name : slots..) : patt=%s" + pattern)) + (substring full-prefix (match-beginning 1) + (match-end 1))))) + (components (if listname + (ess-object-names listname) + (if classname + (ess-slot-names classname) + ;; Default case: It hangs here when + ;; options(error=recover) : + (ess-get-object-list ess-current-process-name))))) + ;; always return a non-nil value to prevent history expansions + (or (completion-in-region beg end components) 'none)))) + +(defun ess-r-get-rcompletions (&optional start end prefix allow-3-dots) + "Call R internal completion utilities (rcomp) for possible completions. +Optional START and END delimit the entity to complete, default to +bol and point. If PREFIX is given, perform completion on +PREFIX. First element of the returned list is the completion +token. Needs version of R >= 2.7.0." + (let* ((start (or start + (if prefix + 0 + (save-excursion (comint-bol nil) (point))))) + (end (or end (if prefix (length prefix) (point)))) + (prefix (or prefix (buffer-substring start end))) + ;; (opts1 (if no-args "op<-rc.options(args=FALSE)" "")) + ;; (opts2 (if no-args "rc.options(op)" "")) + (call1 (format ".ess_get_completions(\"%s\", %d, \"%s\")" + (ess-quote-special-chars prefix) + (- end start) + ess-R-argument-suffix)) + (cmd (if allow-3-dots + (concat call1 "\n") + (concat "local({ r <- " call1 "; r[r != '...='] })\n")))) + (ess-get-words-from-vector cmd))) + +(defun ess-r-complete-object-name () + "Completion in R via R's completion utilities (formerly `rcompgen'). +To be used instead of ESS' completion engine for R versions >= 2.7.0." + (let ((possible-completions (ess-r-get-rcompletions)) + token-string) + (when possible-completions + (setq token-string (pop possible-completions)) + (or (completion-in-region (- (point) (length token-string)) + (point) + possible-completions) + 'none)))) + +(defvar ess--cached-sp-objects nil) + +(defun ess--get-cached-completions (prefix &optional _point) + (if (string-match-p "[]:$@[]" prefix) + ;; call proc for objects + (cdr (ess-r-get-rcompletions nil nil prefix)) + ;; else, get cached list of objects + (with-ess-process-buffer 'no-error ;; use proc buf alist + (ess-when-new-input last-cached-completions + (if (and ess--cached-sp-objects + (not (process-get *proc* 'sp-for-ac-changed?))) + ;; if global cache is already there, only re-read local .GlobalEnv + (progn + (unless ess-sl-modtime-alist + ;; initialize if empty + (setq ess-sl-modtime-alist '((".GlobalEnv" nil)))) + ;; fixme: Make adaptive. Not on all remotes are slow; For lots of + ;; objects in .GlobalEnv,locals could also be slow. + (unless (file-remote-p default-directory) + (ess-extract-onames-from-alist ess-sl-modtime-alist 1 'force))) + (if ess--cached-sp-objects + (ess-get-modtime-list 'ess--cached-sp-objects 'exclude-first) + (ess-get-modtime-list) + (setq ess--cached-sp-objects (cdr ess-sl-modtime-alist))) + ;; reread new package, but not rda, much faster and not needed anyways + (process-put *proc* 'sp-for-ac-changed? nil))) + (apply #'append + (cl-cddar ess-sl-modtime-alist) ; .GlobalEnv + (mapcar #'cddr ess--cached-sp-objects))))) + + +;;;*;;; ARGUMENTS + +(defvar ess-r--funargs-pre-cache + '(("plot" + (("graphics") + (("x" . "") ("y" . "NULL") ("type" . "p") ("xlim" . "NULL") ("ylim" . "NULL") ("log" . "") ("main" . "NULL") ("sub" . "NULL") ("xlab" . "NULL") ("ylab" . "NULL") + ("ann" . "par(\"ann\")") ("axes" . "TRUE") ("frame.plot" . "axes") ("panel.first" . "NULL") ("panel.last" . "NULL") ("asp" . "NA") ("..." . "")) + ("x" "y" "..." "ci" "type" "xlab" "ylab" "ylim" "main" "ci.col" "ci.type" "max.mfrow" "ask" "mar" "oma" "mgp" "xpd" "cex.main" "verbose" "scale" "xlim" "log" "sub" "ann" "axes" "frame.plot" + "panel.first" "panel.last" "asp" "center" "edge.root" "nodePar" "edgePar" "leaflab" "dLeaf" "xaxt" "yaxt" "horiz" + "zero.line" "verticals" "col.01line" "pch" "legend.text" "formula" "data" "subset" "to" "from" "newpage" "vp" "labels" + "hang" "freq" "density" "angle" "col" "border" "lty" "add" "predicted.values" "intervals" "separator" "col.predicted" + "col.intervals" "col.separator" "lty.predicted" "lty.intervals" "lty.separator" "plot.type" "main2" "par.fit" "grid" + "panel" "cex" "dimen" "abbrev" "which" "caption" "sub.caption" "id.n" "labels.id" "cex.id" "qqline" "cook.levels" + "add.smooth" "label.pos" "cex.caption" "rows" "levels" "conf" "absVal" "ci.lty" "xval" "do.points" "col.points" "cex.points" + "col.hor" "col.vert" "lwd" "set.pars" "range.bars" "col.range" "xy.labels" "xy.lines" "nc" "yax.flip" "mar.multi" "oma.multi"))) + ("print" + (("base") + (("x" . "") ("digits" . "NULL") ("quote" . "TRUE") ("na.print" . "NULL") ("print.gap" . "NULL") ("right" . "FALSE") ("max" . "NULL") ("useSource" . "TRUE") ("..." . "")) + ("x" "..." "digits" "signif.stars" "intercept" "tol" "se" "sort" "verbose" "indent" "style" ".bibstyle" "prefix" "vsep" "minlevel" "quote" "right" "row.names" "max" "na.print" "print.gap" + "useSource" "diag" "upper" "justify" "title" "max.levels" "width" "steps" "showEnv" "newpage" "vp" "cutoff" "max.level" "give.attr" "units" "abbrCollate" "print.x" "deparse" "locale" "symbolic.cor" + "loadings" "zero.print" "calendar")))) + "Alist of cached arguments for time consuming functions.") + + +;;;*;;; HELP + +(defun ess-r-get-object-help-string (sym) + "Help string for ac." + (let ((proc (ess-get-next-available-bg-process))) + (if (null proc) + "No free ESS process found" + (let ((buf (get-buffer-create " *ess-command-output*"))) + (when (string-match ":+\\(.*\\)" sym) + (setq sym (match-string 1 sym))) + (with-current-buffer (process-buffer proc) + (ess-with-current-buffer buf + (ess--flush-help-into-current-buffer sym nil))) + (with-current-buffer buf + (ess-help-underline) + (goto-char (point-min)) + (buffer-string)))))) + +(defun ess-r-get-arg-help-string (sym &optional proc) + "Help string for ac." + (setq sym (replace-regexp-in-string " *= *\\'" "" sym)) + (let ((proc (ess-get-next-available-bg-process proc))) + (if (null proc) + "No free ESS process found" + (let ((fun (car ess--fn-name-start-cache))) + (with-current-buffer (ess-command (format ".ess_arg_help('%s','%s')\n" sym fun) + nil nil nil nil proc) + (goto-char (point-min)) + (forward-line) + (buffer-substring-no-properties (point) (point-max))))))) + + +;;;*;;; COMPANY +;; https://company-mode.github.io + +(defun company-R-objects (command &optional arg &rest _ignored) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-R-objects)) + (prefix (unless (ess-inside-string-or-comment-p) + (let ((start (ess-symbol-start))) + (when start + (buffer-substring-no-properties start (point)))))) + (candidates (when-let ((proc (ess-get-next-available-bg-process))) + (with-current-buffer (process-buffer proc) + (all-completions arg (ess--get-cached-completions arg))))) + (doc-buffer (company-doc-buffer (ess-r-get-object-help-string arg))))) + +(defun company-R-args (command &optional arg &rest _ignored) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-R-args)) + (prefix (unless (ess-inside-string-or-comment-p) + (let ((start (ess-arg-start))) + (when start + (let ((prefix (buffer-substring-no-properties start (point)))) + (if ess-company-arg-prefix-length + (cons prefix (>= (length prefix) + ess-company-arg-prefix-length)) + prefix)))))) + (candidates (when-let ((proc (ess-get-next-available-bg-process))) + (let* ((args (delete "..." (nth 2 (ess-function-arguments + (car ess--fn-name-start-cache) proc)))) + (args (mapcar (lambda (a) (concat a ess-R-argument-suffix)) + args))) + (all-completions arg args)))) + ;; Displaying help for the argument in the echo area is disabled + ;; by default for performance reasons. It causes delays or hangs (#1062). + (meta (when (bound-and-true-p ess-r--company-meta) + (when-let ((proc (ess-get-next-available-bg-process))) + (when (with-current-buffer (process-buffer proc) + (not (file-remote-p default-directory))) + ;; fixme: ideally meta should be fetched with args + (let ((doc (ess-r-get-arg-help-string arg proc))) + (replace-regexp-in-string "^ +\\| +$" "" + (replace-regexp-in-string "[ \t\n]+" " " doc))))))) + (sorted t) + (require-match 'never) + (doc-buffer (company-doc-buffer (ess-r-get-arg-help-string arg))))) + +(defun company-R-library (command &optional arg &rest _ignored) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-R-library)) + (prefix (and (member (car (ess--fn-name-start)) + '("library" "require")) + (let ((start (ess-symbol-start))) + (and start (buffer-substring start (point)))))) + (candidates (when (ess-can-eval-in-background) + (all-completions arg (ess-installed-packages)))) + (annotation "") + (duplicates nil) + (sorted t))) + +;; FIXME: There's a lot of overlap between `ess-r-package-completion' +;; and `company-R-library'. Can we merge them somehow? +(defun ess-r-package-completion () + "Return installed packages if in a call to library or require. +Return format suitable for `completion-at-point-functions'." + (when (and (ess-can-eval-in-background) + (member (car (ess--fn-name-start)) + '("library" "require"))) + (list (ess-symbol-start) + (point) + (ess-installed-packages) + :annotation-function + (lambda (_) " ")))) + + +;;;*;;; AC SOURCES +;; http://cx4a.org/software/auto-complete/index.html +;; auto-complete is de-facto unmaintained, users should switch to `company-mode'. + +(defvar ac-source-R + '((prefix . ess-ac-start) + ;; (requires . 0) ::) + (candidates . ess-ac-candidates) + ;; (action . ess-ac-action-args) ;; interfere with ac-fallback mechanism on RET (which is extremely annoying in inferior buffers) + (document . ess-ac-help)) + "Combined ad-completion source for R function arguments and R objects.") +(make-obsolete-variable 'ac-source-R "Use company-mode instead" "ESS 19.04") + +(defun ess-ac-start () + (when (ess-process-live-p) + (or (ess-arg-start) + (ess-symbol-start)))) +(make-obsolete-variable 'ess-ac-start "Use company-mode instead" "ESS 19.04") + +(defun ess-ac-candidates () + "OBJECTS + ARGS." + (let ((args (with-no-warnings + ;; suppress obsolete warnings + (ess-ac-args)))) + ;; sort of intrusive but right + (if (and ac-auto-start + (< (length ac-prefix) ac-auto-start)) + args + (if args + (append args (with-no-warnings + ;; suppress obsolete warnings + (ess-ac-objects t))) + (with-no-warnings + ;; suppress obsolete warnings + (ess-ac-objects)))))) +(make-obsolete-variable 'ess-ac-candidates "Use company-mode instead" "ESS 19.04") + +(defun ess-ac-help (sym) + (if (string-match-p "= *\\'" sym) + (ess-r-get-arg-help-string sym) + (ess-r-get-object-help-string sym))) +(make-obsolete-variable 'ess-ac-help "Use company-mode instead" "ESS 19.04") + +;; OBJECTS +(defvar ac-source-R-objects + '((prefix . ess-symbol-start) + ;; (requires . 2) + (candidates . ess-ac-objects) + (document . ess-r-get-object-help-string)) + "Auto-completion source for R objects.") +(make-obsolete-variable 'ac-source-R-objects "Use company-mode instead" "ESS 19.04") + +(defun ess-ac-objects (&optional no-kill) + "Get all cached objects." + (declare (obsolete "Use company-mode instead" "ESS 19.04")) + (let ((aprf ac-prefix)) + (when (and aprf (ess-process-live-p)) + (unless no-kill ;; workaround + (kill-local-variable 'ac-use-comphist)) + (ess--get-cached-completions aprf ac-point)))) + +;; ARGS +(defvar ac-source-R-args + '((prefix . ess-arg-start) + ;; (requires . 0) + (candidates . ess-ac-args) + ;; (action . ess-ac-action-args) + (document . ess-r-get-arg-help-string)) + "Auto-completion source for R function arguments.") +(make-obsolete-variable 'ac-source-R-args "Use company-mode instead" "ESS 19.04") + +(defun ess-ac-args () + "Get the args of the function when inside parentheses." + (declare (obsolete "Use company-mode-instead" "ESS 19.04")) + (when (and ess--fn-name-start-cache ;; set in a call to ess-arg-start + (ess-process-live-p)) + (let ((args (nth 2 (ess-function-arguments (car ess--fn-name-start-cache))))) + (if args + (setq-local ac-use-comphist nil) + (kill-local-variable 'ac-use-comphist)) + (delete "..." args) + (mapcar (lambda (a) (concat a ess-R-argument-suffix)) + args)))) + +(provide 'ess-r-completion) + +;;; ess-r-completion.el ends here diff --git a/elpa/ess-20230419.1527/ess-r-flymake.el b/elpa/ess-20230419.1527/ess-r-flymake.el new file mode 100644 index 00000000..dae24679 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-flymake.el @@ -0,0 +1,251 @@ +;;; ess-r-flymake.el --- A ess-r Flymake backend -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2022 Free Software Foundation, Inc. +;; Maintainer: ESS-core + + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Flymake is the built-in Emacs package that supports on-the-fly +;; syntax checking. This file adds support for this in ess-r-mode by +;; relying on the lintr package, available on CRAN and currently +;; hosted at https://github.com/jimhester/lintr. + +;;; Code: + +(eval-when-compile (require 'cl-lib)) +(require 'ess-inf) +(require 'flymake) + +;; Appease the byte compiler for Emacs 25. Remove after dropping +;; support for Emacs 25. +(declare-function flymake-diag-region "flymake") +(declare-function flymake-make-diagnostic "flymake") +(declare-function flymake--overlays "flymake") +(declare-function ess-r-project "ess-r-mode") +(declare-function ess-r-package-project "ess-r-package") + +(defcustom ess-r-flymake-linters + '("closed_curly_linter = NULL" + "commas_linter = NULL" + "commented_code_linter = NULL" + "infix_spaces_linter = NULL" + "line_length_linter = NULL" + "object_length_linter = NULL" + "object_name_linter = NULL" + "object_usage_linter = NULL" + "open_curly_linter = NULL" + "pipe_continuation_linter = NULL" + "single_quotes_linter = NULL" + "spaces_inside_linter = NULL" + "spaces_left_parentheses_linter = NULL" + "trailing_blank_lines_linter = NULL" + "trailing_whitespace_linter = NULL") + "Default linters to use. +Can be either a string with R expression to be used as +is (e.g. `lintr::default_linters'). Or a list of strings where +each element is passed as argument to `lintr::with_defaults'." + :group 'ess-R + :type '(choice string (repeat string)) + :package-version '(ess . "18.10")) + +(defcustom ess-r-flymake-lintr-cache t + "If non-nil, cache lintr results." + :group 'ess-R + :type 'boolean + :package-version '(ess . "18.10")) + +(defvar-local ess-r--flymake-proc nil) + +(defvar-local ess-r--lintr-file nil + "Location of the .lintr file for this buffer.") + +(defvar ess-r--flymake-def-linter + (replace-regexp-in-string + "[\n\t ]+" " " + "esslint <- function(str, ...) { + if (!suppressWarnings(require(lintr, quietly=T))) { + cat('@@error: @@`lintr` package not installed') + } else { + if (packageVersion('lintr') <= '1.0.3') { + cat('@@error: @@Need `lintr` version > v1.0.3') + } else { + tryCatch(lintr::lint(commandArgs(TRUE), ...), + error = function(e) { + cat('@@warning: @@', e) + }) + } + } +};")) + +(defun ess-r--find-lintr-file () + "Return the absolute path to the .lintr file. +Check first the current directory, then the project root, then +the package root, then the user's home directory. Return nil if +we couldn't find a .lintr file." + ;; VS[2022-01-26]: Can't this entire thing be replaced by + ;; `(locate-dominating-file ".lintr")`? + (let* ((cur-file (expand-file-name ".lintr" default-directory)) + (pkg (cdr (ess-r-package-project))) + (pkg-file (and pkg (expand-file-name ".lintr" pkg))) + (proj (ess-r-project)) + (proj-file (and proj (expand-file-name ".lintr" proj))) + (home-file (expand-file-name ".lintr" (getenv "HOME")))) + (cond ((file-readable-p cur-file) + cur-file) + ((and proj-file (file-readable-p proj-file)) + proj-file) + ((and pkg-file (file-readable-p pkg-file)) + pkg-file) + ((file-readable-p home-file) + home-file)))) + +(defun ess-r--flymake-linters () + "If `ess-r-flymake-linters' is a string, use that. +Otherwise, construct a string to pass to lintr::with_defaults." + (replace-regexp-in-string + "[\n\t ]+" " " + (if (stringp ess-r-flymake-linters) + ess-r-flymake-linters + (concat "lintr::with_defaults(" + (mapconcat #'identity + ess-r-flymake-linters + ", ") + ")")))) + +(defun ess-r--flymake-msg-type (str) + "Transform STR into log level." + (cond ((string= str "error: ") :error) + ((string= str "warning: ") :warning) + ((string= str "style: ") :note) + (t (error "Invalid msg type %s" str)))) + +(defun ess-r--flymake-check-errors () + "Check for critical errors and return non-nil if such occurred." + (goto-char (point-min)) + (when (re-search-forward "@@\\(\\(error\\|warning\\): \\)@@" nil t) + (let ((type (ess-r--flymake-msg-type (match-string 1))) + (msg (buffer-substring-no-properties (match-end 0) (point-max)))) + (flymake-log type msg) + (eq type :error)))) + +(defun ess-r--flymake-parse-output (msg-buffer src-buffer report-fn) + "Parse the content of MSG-BUFFER for lint locations. +SRC-BUFFER is the original source buffer. Collect all messages +into a list and call REPORT-FN on it." + (with-current-buffer msg-buffer + (if (ess-r--flymake-check-errors) + (with-current-buffer src-buffer + ;; we are in the sentinel here; don't throw but remove our hook instead + (remove-hook 'flymake-diagnostic-functions #'ess-r-flymake t)) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp + ;; Regex to match the output lint() gives us. + (rx line-start ":" + ;; row + (group-n 1 (one-or-more num)) ":" + ;; column + (group-n 2 (one-or-more num)) ": " + ;; type + (group-n 3 (| "style: " "warning: " "error: ")) + ;; msg + (group-n 4 (one-or-more not-newline)) line-end) + nil t) + for msg = (match-string 4) + for (beg . end) = (let ((line (string-to-number (match-string 1))) + (col (string-to-number (match-string 2)))) + (flymake-diag-region src-buffer line col)) + for type = (ess-r--flymake-msg-type (match-string 3)) + collect (flymake-make-diagnostic src-buffer beg end type msg) + into diags + finally (funcall report-fn diags))))) + +(defun ess-r-flymake (report-fn &rest _args) + "A Flymake backend for ESS-R modes. Relies on the lintr package. +REPORT-FN is flymake's callback function." + (unless (executable-find inferior-ess-r-program) + (error "Cannot find program '%s'" inferior-ess-r-program)) + ;; Kill the process if earlier check was found. The sentinel of the earlier + ;; check will detect this. + (when (process-live-p ess-r--flymake-proc) + (kill-process ess-r--flymake-proc)) + (if (and (eql ess-use-flymake 'process) + (not (ess-process-live-p))) + (progn + (funcall report-fn nil) + (mapc #'delete-overlay (flymake--overlays))) + (let ((src-buffer (current-buffer))) + (setq ess-r--flymake-proc + (make-process + :name "ess-r-flymake" :noquery t :connection-type 'pipe + :buffer (generate-new-buffer " *ess-r-flymake*") + :command (list inferior-R-program + "--no-save" "--no-restore" "--no-site-file" "--no-init-file" "--slave" + "-e" (concat + (when ess-r--lintr-file + (concat "options(lintr.linter_file = \"" ess-r--lintr-file "\");")) + ess-r--flymake-def-linter + ;; commandArgs(TRUE) returns everything after + ;; --args as a character vector + "esslint(commandArgs(TRUE)" + (unless ess-r--lintr-file + (concat ", linters = " (ess-r--flymake-linters))) + (when ess-r-flymake-lintr-cache + ", cache = TRUE") + ")") + "--args" (buffer-substring-no-properties + (point-min) (point-max))) + :sentinel + (lambda (proc _event) + (cond + ((eq 'exit (process-status proc)) + (unwind-protect + (if (eq proc (buffer-local-value 'ess-r--flymake-proc src-buffer)) + (ess-r--flymake-parse-output (process-buffer proc) src-buffer report-fn) + (flymake-log :warning "Canceling obsolete check %s" proc)) + (kill-buffer (process-buffer proc)))) + ((not (eq 'run (process-status proc))) + (kill-buffer (process-buffer proc)))))))))) + +(defun ess-r-setup-flymake () + "Setup flymake for ESS. +Activate flymake only if `ess-use-flymake' is non-nil." + (when ess-use-flymake + (when (< emacs-major-version 26) + (error "ESS-flymake requires Emacs version 26 or later")) + (when (string= "R" ess-dialect) + (setq ess-r--lintr-file (ess-r--find-lintr-file)) + (add-hook 'flymake-diagnostic-functions #'ess-r-flymake nil t) + ;; Try not to enable flymake if flycheck is already running: + (unless (bound-and-true-p flycheck-mode) + (flymake-mode))))) + +;; Enable flymake in Emacs 26+ +(when (<= 26 emacs-major-version) + (if (eval-when-compile (<= 26 emacs-major-version)) + (add-hook 'ess-r-mode-hook #'ess-r-setup-flymake) + (when ess-use-flymake + (display-warning 'ess "ESS was compiled with older version of Emacs;\n `ess-r-flymake' won't be available")))) + +(provide 'ess-r-flymake) + +;;; ess-r-flymake.el ends here diff --git a/elpa/ess-20230419.1527/ess-r-mode.el b/elpa/ess-20230419.1527/ess-r-mode.el new file mode 100644 index 00000000..bd902710 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-mode.el @@ -0,0 +1,3019 @@ +;;; ess-r-mode.el --- R customization -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: A.J. Rossini +;; Created: 12 Jun 1997 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This file defines all the R customizations for ESS. See ess-s-lang.el +;; for general S language customizations. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) +(require 'cl-lib) +(require 'compile) +(require 'ess-mode) +(require 'ess-help) +(require 'ess-s-lang) +(require 'ess-roxy) +(require 'ess-r-completion) +(require 'ess-r-syntax) +(require 'ess-r-package) +(require 'ess-trns) +(require 'ess-r-xref) +(when (>= emacs-major-version 26) (require 'ess-r-flymake)) ; Flymake rewrite in Emacs 26 + +(declare-function ess-rdired "ess-rdired" ()) + +(defcustom ess-r-mode-hook nil + "Hook run when entering `ess-r-mode'." + :options '(electric-layout-local-mode) + :type 'hook + :group 'ess-R) + +;; Define and run old hook for backward compatibility. We don't +;; obsolete it with warnings because this is a historically important +;; user-facing variable and it would not be worth the trouble. +(defvar R-mode-hook nil + "This variable is obsolete since ESS 19.04; +use `ess-r-mode-hook' instead.") +(add-hook 'ess-r-mode-hook (lambda () (run-hooks 'R-mode-hook))) + +(defcustom ess-r-fetch-ESSR-on-remotes nil + "If non-nil, when loading ESSR, fetch it from the GitHub repository. +Otherwise source from local ESS installation. When the value is +\\='ess-remote, fetch only with ess-remote's and not with TRAMP +connections. When t, always fetch from remotes. Change this +variable when loading ESSR code on remotes fails for you. + +Fetching happens once per new ESSR version. The archive is stored +in ~/.config/ESSR/ESSRv[VERSION].rds file. You can download and +place it there manually if the remote has restricted network +access." + :type '(choice (const nil :tag "Never") + (const ess-remote :tag "With ess-remote only") + (const t :tag "Always")) + :group 'ess-R) + +;; Silence the byte compiler +(defvar add-log-current-defun-header-regexp) + +;; TODO: Refactor so as to not rely on dynamic scoping. After that +;; refactor, also remove the file-local-variable byte-compile-warnings +;; (not lexical) at the bottom. +(defvar containing-sexp) +(defvar indent-point) +(defvar prev-containing-sexp) + +(define-obsolete-variable-alias 'ess-r-versions 'ess-r-runner-prefixes "ESS 19.04") +(defcustom ess-r-runner-prefixes + (let ((r-ver '("R-1" "R-2" "R-3" "R-4" "R-5" "R-6" "R-7" "R-devel" "R-patched"))) + (if (eq system-type 'darwin) (append r-ver '("R32" "R64")) r-ver)) + "List of partial strings for versions of R to access within ESS. +Each string specifies the start of a filename. If a filename +beginning with one of these strings is found on variable +`exec-path', a command for that version of R is made available. +For example, if the file \"R-1.8.1\" is found and this variable +includes the string \"R-1\", a function called `R-1.8.1' will be +available to run that version of R. If duplicate versions of the +same program are found (which happens if the same path is listed +on variable `exec-path' more than once), they are ignored by +calling `delete-dups'. Set this variable to nil to disable +searching for other versions of R. Setting this variable directly +does not take effect; use either \\[customize-option] or set the +value by using `ess-r-runners-reset'." + :group 'ess-R + :package-version '(ess . "19.04") + :type '(repeat string) + :set #'ess-r-runners-reset + ;; Use `custom-initialize-default' since we call + ;; `ess-r-define-runners' at the end of this file directly. + :initialize #'custom-initialize-default) + + + +;;*;; Mode definition + +;;;*;;; UI (Keymaps / Menus) +(defvar ess-dev-map + (let (ess-dev-map) + (define-prefix-command 'ess-dev-map) + (define-key ess-dev-map "\C-s" #'ess-r-set-evaluation-env) + (define-key ess-dev-map "s" #'ess-r-set-evaluation-env) + (define-key ess-dev-map "T" #'ess-toggle-tracebug) + (define-key ess-dev-map "\C-l" #'ess-r-devtools-load-package) + (define-key ess-dev-map "l" #'ess-r-devtools-load-package) + (define-key ess-dev-map "`" #'ess-show-traceback) + (define-key ess-dev-map "~" #'ess-show-call-stack) + (define-key ess-dev-map "\C-w" #'ess-watch) + (define-key ess-dev-map "w" #'ess-watch) + (define-key ess-dev-map "\C-d" #'ess-debug-flag-for-debugging) + (define-key ess-dev-map "d" #'ess-debug-flag-for-debugging) + (define-key ess-dev-map "\C-u" #'ess-debug-unflag-for-debugging) + (define-key ess-dev-map "u" #'ess-debug-unflag-for-debugging) + (define-key ess-dev-map "" #'ess-debug-unflag-for-debugging) + (define-key ess-dev-map "\C-b" #'ess-bp-set) + (define-key ess-dev-map "b" #'ess-bp-set) + (define-key ess-dev-map "" #'ess-bp-set-conditional) + (define-key ess-dev-map "B" #'ess-bp-set-conditional) + (define-key ess-dev-map "\C-L" #'ess-bp-set-logger) + (define-key ess-dev-map "L" #'ess-bp-set-logger) + (define-key ess-dev-map "\C-o" #'ess-bp-toggle-state) + (define-key ess-dev-map "o" #'ess-bp-toggle-state) + (define-key ess-dev-map "\C-k" #'ess-bp-kill) + (define-key ess-dev-map "k" #'ess-bp-kill) + (define-key ess-dev-map "\C-K" #'ess-bp-kill-all) + (define-key ess-dev-map "K" #'ess-bp-kill-all) + (define-key ess-dev-map "\C-n" #'ess-bp-next) + (define-key ess-dev-map "n" #'ess-bp-next) + (define-key ess-dev-map "i" #'ess-debug-goto-input-event-marker) + (define-key ess-dev-map "I" #'ess-debug-goto-input-event-marker) + (define-key ess-dev-map "\C-p" #'ess-bp-previous) + (define-key ess-dev-map "p" #'ess-bp-previous) + (define-key ess-dev-map "\C-e" #'ess-debug-toggle-error-action) + (define-key ess-dev-map "e" #'ess-debug-toggle-error-action) + (define-key ess-dev-map "0" #'ess-electric-selection) + (define-key ess-dev-map "1" #'ess-electric-selection) + (define-key ess-dev-map "2" #'ess-electric-selection) + (define-key ess-dev-map "3" #'ess-electric-selection) + (define-key ess-dev-map "4" #'ess-electric-selection) + (define-key ess-dev-map "5" #'ess-electric-selection) + (define-key ess-dev-map "6" #'ess-electric-selection) + (define-key ess-dev-map "7" #'ess-electric-selection) + (define-key ess-dev-map "8" #'ess-electric-selection) + (define-key ess-dev-map "9" #'ess-electric-selection) + (define-key ess-dev-map "?" #'ess-tracebug-show-help) + ess-dev-map) + "Keymap for commands related to development and debugging.") + +(defvar ess-r-package-check-map + (let (ess-r-package-check-map) + (define-prefix-command 'ess-r-package-check-map) + (define-key ess-r-package-check-map "\C-c" #'ess-r-devtools-check-package) + (define-key ess-r-package-check-map "c" #'ess-r-devtools-check-package) + (define-key ess-r-package-check-map "\C-w" #'ess-r-devtools-check-with-winbuilder) + (define-key ess-r-package-check-map "w" #'ess-r-devtools-check-with-winbuilder) + (define-key ess-r-package-check-map "h" #'ess-r-rhub-check-package) + ess-r-package-check-map) + "Keymap for R package checks.") + +(defvar ess-r-package-dev-map + (let (ess-r-package-dev-map) + (define-prefix-command 'ess-r-package-dev-map) + (define-key ess-r-package-dev-map "\C-s" #'ess-r-set-evaluation-env) + (define-key ess-r-package-dev-map "s" #'ess-r-set-evaluation-env) + (define-key ess-r-package-dev-map "\C-a" #'ess-r-devtools-execute-command) + (define-key ess-r-package-dev-map "a" #'ess-r-devtools-execute-command) + (define-key ess-r-package-dev-map "\C-e" #'ess-r-devtools-execute-command) + (define-key ess-r-package-dev-map "e" #'ess-r-devtools-execute-command) + (define-key ess-r-package-dev-map "\C-b" #'ess-r-devtools-build) + (define-key ess-r-package-dev-map "b" #'ess-r-devtools-build) + (define-key ess-r-package-dev-map "\C-c" 'ess-r-package-check-map) + (define-key ess-r-package-dev-map "c" 'ess-r-package-check-map) + (define-key ess-r-package-dev-map "\C-d" #'ess-r-devtools-document-package) + (define-key ess-r-package-dev-map "d" #'ess-r-devtools-document-package) + (define-key ess-r-package-dev-map "g" #'ess-r-devtools-install-github) + (define-key ess-r-package-dev-map "\C-i" #'ess-r-devtools-install-package) + (define-key ess-r-package-dev-map "i" #'ess-r-devtools-install-package) + (define-key ess-r-package-dev-map "\C-l" #'ess-r-devtools-load-package) + (define-key ess-r-package-dev-map "l" #'ess-r-devtools-load-package) + (define-key ess-r-package-dev-map "\C-t" #'ess-r-devtools-test-package) + (define-key ess-r-package-dev-map "t" #'ess-r-devtools-test-package) + (define-key ess-r-package-dev-map "\C-u" #'ess-r-devtools-unload-package) + (define-key ess-r-package-dev-map "u" #'ess-r-devtools-unload-package) + ess-r-package-dev-map)) + +(easy-menu-define ess-roxygen-menu nil + "Roxygen submenu." + '("Roxygen" + :visible (and ess-dialect (string-match "^R" ess-dialect)) + ["Update/Generate Template" ess-roxy-update-entry t] + ["Preview Rd" ess-roxy-preview-Rd t] + ["Preview HTML" ess-roxy-preview-HTML t] + ["Preview text" ess-roxy-preview-text t] + ["Hide all" ess-roxy-hide-all t] + ["Toggle Roxygen Prefix" ess-roxy-toggle-roxy-region t])) + +(easy-menu-define ess-tracebug-menu nil + "Tracebug submenu." + '("Tracebug" + :visible (and ess-dialect (string-match "^R" ess-dialect)) + ;; :enable ess-local-process-name + ["Active?" ess-toggle-tracebug + :style toggle + :selected (or (and (ess-process-live-p) + (ess-process-get 'tracebug)) + ess-use-tracebug)] + ["Show traceback" ess-show-traceback (ess-process-live-p)] + ["Show call stack" ess-show-call-stack (ess-process-live-p)] + ["Watch" ess-watch (and (ess-process-live-p) + (ess-process-get 'tracebug))] + ["Error action cycle" ess-debug-toggle-error-action (and (ess-process-live-p) + (ess-process-get 'tracebug))] + "----" + ["Flag for debugging" ess-debug-flag-for-debugging ess-local-process-name] + ["Unflag for debugging" ess-debug-unflag-for-debugging ess-local-process-name] + "----" + ["Set BP" ess-bp-set t] + ["Set conditional BP" ess-bp-set-conditional t] + ["Set logger BP" ess-bp-set-logger t] + ["Kill BP" ess-bp-kill t] + ["Kill all BPs" ess-bp-kill-all t] + ["Next BP" ess-bp-next t] + ["Previous BP" ess-bp-previous t] + "-----" + ["About" ess-tracebug-show-help t])) + +(easy-menu-define ess-r-package-menu nil + "Package Development submenu." + '("Package development" + :visible (and ess-dialect (string-match "^R" ess-dialect)) + ["Active?" ess-r-package-mode + :style toggle + :selected ess-r-package-mode] + ["Select package for evaluation" ess-r-set-evaluation-env t])) + +(easy-menu-add-item ess-mode-menu nil ess-roxygen-menu "end-dev") +(easy-menu-add-item ess-mode-menu nil ess-r-package-menu "end-dev") +(easy-menu-add-item ess-mode-menu nil ess-tracebug-menu "end-dev") +(easy-menu-add-item inferior-ess-mode-menu nil ess-r-package-menu "end-dev") +(easy-menu-add-item inferior-ess-mode-menu nil ess-tracebug-menu "end-dev") + +(defvar ess-r-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-=") #'ess-cycle-assign) + (define-key map "\M-?" #'ess-complete-object-name) + (define-key map (kbd "C-c C-.") 'ess-rutils-map) + map)) + +(defvar ess-r-mode-syntax-table + (let ((table (copy-syntax-table S-syntax-table))) + ;; Letting Emacs treat backquoted names and %ops% as strings solves + ;; many problems with regard to nested strings and quotes + (modify-syntax-entry ?` "\"" table) + (modify-syntax-entry ?% "\"" table) + ;; Underscore is valid in R symbols + (modify-syntax-entry ?_ "_" table) + (modify-syntax-entry ?: "." table) + (modify-syntax-entry ?@ "." table) + (modify-syntax-entry ?$ "." table) + (modify-syntax-entry ?\\ "." table) + table) + "Syntax table for `ess-r-mode'.") + +(defvar ess-r-completion-syntax-table + (let ((table (copy-syntax-table ess-r-mode-syntax-table))) + (modify-syntax-entry ?. "_" table) + (modify-syntax-entry ?: "_" table) + (modify-syntax-entry ?$ "_" table) + (modify-syntax-entry ?@ "_" table) + table) + "Syntax table used for completion and help symbol lookup. +It makes underscores and dots word constituent chars.") + +(defvar ess-r-namespaced-load-verbose t + "Whether to display information on namespaced loading. +When t, loading a file into a namespaced will output information +about which objects are exported and which stay hidden in the +namespace.") + +;; The syntax class for '\' is punctuation character to handle R 4.1 +;; lambdas. Inside strings it should be treated as an escape +;; character which we ensure here. +(defun ess-r--syntax-propertize-backslash () + (when (nth 3 (save-excursion (syntax-ppss (1- (point))))) + (string-to-syntax "\\"))) + +;; Adapted from `python-syntax-stringify' +(defun ess-r--syntax-propertize-raw-string-opening () + (let* ((raw-beg (match-beginning 0)) + (quote-beg (1+ raw-beg)) + (ppss (save-excursion (goto-char raw-beg) (syntax-ppss))) + (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))) + (cond + ;; Inside a comment + ((nth 4 ppss) + nil) + ;; This set of quotes delimits the start of a string + ((null string-start) + (put-text-property quote-beg (1+ quote-beg) + 'syntax-table (string-to-syntax "|")))))) + +(defun ess-r--syntax-propertize-raw-string-closing () + (let* ((quote-end (match-end 0)) + (quote-chr (aref (match-string 3) 0)) + (dashes (match-string 2)) + (matching-delim (pcase (match-string 1) + (`")" ?\() (`"}" ?{) (`"]" ?\[))) + (ppss (save-excursion (goto-char quote-end) (syntax-ppss))) + (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))) + (when string-start + (save-match-data + (save-excursion + (goto-char string-start) + (when (equal (char-after) quote-chr) + (forward-char) + (re-search-forward "-*" nil t) + (let ((matching-dashes (match-string 0))) + (when (or (not matching-dashes) + (string= matching-dashes dashes)) + (when (equal (char-after) matching-delim) + (put-text-property (1- quote-end) quote-end + 'syntax-table (string-to-syntax "|"))))))))))) + +(defconst ess-r--syntax-propertize-function + (syntax-propertize-rules + ("[rR]\\([\"']\\)\\(-*\\)\\([([{]\\)" + (0 (ignore (ess-r--syntax-propertize-raw-string-opening)))) + ("\\([])}]\\)\\(-*\\)\\([\"']\\)" + (0 (ignore (ess-r--syntax-propertize-raw-string-closing)))) + ("\\\\" + (0 (ess-r--syntax-propertize-backslash))))) + +(defun ess-r-font-lock-syntactic-face-function (state) + (if (nth 3 state) + ;; string case + (let ((string-end (save-excursion + (ess-goto-char (nth 8 state)) + (ess-forward-sexp) + (point)))) + (cond + ((eq (nth 3 state) ?%) + (if (eq (point) (1- string-end)) + (when (cdr (assq 'ess-fl-keyword:operators ess-R-font-lock-keywords)) + 'ess-operator-face) + (if (cdr (assq 'ess-R-fl-keyword:%op% ess-R-font-lock-keywords)) + 'ess-%op%-face + nil))) + ((save-excursion + (and (cdr (assq 'ess-R-fl-keyword:fun-defs ess-R-font-lock-keywords)) + (ess-goto-char string-end) + (ess-looking-at "<-") + (ess-goto-char (match-end 0)) + (ess-looking-at "function\\b" t))) + font-lock-function-name-face) + ((save-excursion + (and (cdr (assq 'ess-fl-keyword:fun-calls ess-R-font-lock-keywords)) + (ess-goto-char string-end) + (ess-looking-at "("))) + ess-function-call-face) + ((eq (nth 3 state) ?`) + nil) + (t + font-lock-string-face))) + font-lock-comment-face)) + +;; Don't fontify backquoted symbols as strings +(defun inferior-ess-r-font-lock-syntactic-face-function (state) + (if (nth 3 state) + (if (eq (nth 3 state) ?`) + nil + font-lock-string-face) + font-lock-comment-face)) + +(defvar ess-r--non-fn-kwds + '("in" "else" "break" "next" "repeat")) + +(defvar-local ess-r--keyword-regexp nil) +(defun ess-r--find-fl-keyword (limit) + "Search for R keyword and set the match data. +To be used as part of `font-lock-defaults' keywords." + (unless ess-r--keyword-regexp + (let (fn-kwds non-fn-kwds) + (dolist (kw ess-R-keywords) + (if (member kw ess-r--non-fn-kwds) + (push kw non-fn-kwds) + (push kw fn-kwds))) + (setq ess-r--keyword-regexp + (concat "\\(" + (regexp-opt non-fn-kwds 'words) + "\\)\\|\\(" + (regexp-opt fn-kwds 'words) + "\\)")))) + (let (out) + (while (and (not out) + (re-search-forward ess-r--keyword-regexp limit t)) + (save-match-data + (setq out (if (match-beginning 1) + ;; Non-function-like keywords: Always fontified + ;; except for `in` for which we check it's part + ;; of a `for` construct. Ideally we'd check that + ;; other keywords like `break` or `next` are + ;; part of the right syntactic construct but + ;; that requires robust and efficient detection + ;; of complete expressions. + (if (string= (match-string 1) "in") + (save-excursion + (goto-char (match-beginning 1)) + (and (ess-backward-up-list) + (forward-word -1) + (looking-at "for\\s-*("))) + t) + ;; Function-like keywords: check if they are + ;; followed by an open paren + (looking-at "\\s-*("))))) + out)) + +(define-obsolete-variable-alias 'R-customize-alist 'ess-r-customize-alist "ESS 18.10.2") +(defvar ess-r-customize-alist + (append + '((ess-local-customize-alist . 'ess-r-customize-alist) + (ess-dialect . "R") + (ess-suffix . "R") + (ess-traceback-command . ess-r-traceback-command) + (ess-call-stack-command . ess-r-call-stack-command) + (ess-mode-completion-syntax-table . ess-r-completion-syntax-table) + (ess-build-eval-message-function . #'ess-r-build-eval-message) + (ess-dump-filename-template . ess-r-dump-filename-template) + (ess-change-sp-regexp . ess-r-change-sp-regexp) + (ess-help-sec-regex . ess-help-r-sec-regex) + (ess-help-sec-keys-alist . ess-help-r-sec-keys-alist) + (ess-function-pattern . ess-r-function-pattern) + (ess-object-name-db-file . "ess-r-namedb.el") + (ess-smart-operators . ess-r-smart-operators) + (inferior-ess-program . inferior-ess-r-program) + (inferior-ess-objects-command . inferior-ess-r-objects-command) + (inferior-ess-search-list-command . "search()\n") + (inferior-ess-help-command . inferior-ess-r-help-command) + (inferior-ess-exit-command . "q()") + (ess-error-regexp-alist . ess-r-error-regexp-alist) + (ess-describe-object-at-point-commands . 'ess-r-describe-object-at-point-commands) + (ess-STERM . "iESS") + (ess-editor . ess-r-editor) + (ess-pager . ess-r-pager)) + S-common-cust-alist) + "Variables to customize for R.") + +(cl-defmethod ess-build-tags-command (&context (ess-dialect "R")) + "Return tags command for R." + "rtags('%s', recursive = TRUE, pattern = '\\\\.[RrSs](rw)?$',ofile = '%s')") + +(defvar ess-r-traceback-command + "local({cat(geterrmessage(), \ +'---------------------------------- \n', \ +fill=TRUE); try(traceback(), silent=TRUE)})\n") + +(defvar ess-r-call-stack-command "traceback(1)\n") + +(defun ess-r-format-command (cmd &rest args) + (let ((sentinel (alist-get 'output-delimiter args))) + (ess-r--format-call ".ess.command(local(%s), '%s')\n" cmd sentinel))) + +(defvar ess-r-format-command-alist + '((fun . ess-r-format-command) + (use-delimiter . t))) + +(defvar ess-r-dump-filename-template + (replace-regexp-in-string + "S$" "R" ess-dump-filename-template-proto)) + +(defvar ess-r-ac-sources + '(ac-source-R)) + +(defvar ess-r-company-backends + '((company-R-library company-R-args company-R-objects :separate))) + +(defconst ess-help-r-sec-regex "^[A-Z][A-Za-z].+:$" + "Reg(ular) Ex(pression) of section headers in help file.") + +(defconst ess-help-r-sec-keys-alist + '((?a . "\\s *Arguments:") + (?d . "\\s *Description:") + (?D . "\\s *Details:") + (?t . "\\s *Details:") + (?e . "\\s *Examples:") + (?n . "\\s *Note:") + (?r . "\\s *References:") + (?s . "\\s *See Also:") + (?u . "\\s *Usage:") + (?v . "\\s *Value[s]?") ; + ) + "Alist of (key . string) pairs for use in help section searching.") + +(defvar ess-r-error-regexp-alist '(R R1 R2 R3 R4 R-rlang R-recover) + "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.") + +(dolist (l '(;; Takes precedence over R1 below in English locales, and allows spaces in file path + (R "\\(\\(?: at \\|(@\\)\\([^#()\n:]+\\)[#:]\\([0-9]+\\)\\)" 2 3 nil 2 1) + ;; valgrind, testthat, rlang/shiny style + ;; e.g. (stl_numeric.h:183), (test-parsers.R:238:3) [.../R/file.R#158] + (R1 "\\s(\\([^0-9][^ ():\n]+\\)[#:]\\([0-9]+\\)[#:]?\\([0-9]+\\)?\\s)" 1 2 nil 2) + (R2 "(\\(\\w+ \\([^())\n]+\\)#\\([0-9]+\\)\\))" 2 3 nil 2 1) + ;; Precedes R4 and allows spaces in file path, Starts at bol or with ": " (patterns 3,4,5,6,9) + (R3 "\\(?:^ *\\|: ?\\)\\([^-+[:digit:] \t\n]:?[^: \t\n]*\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\)?" 1 2 3 2 1) + ;; Don't start with digit; no spaces + (R4 "\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1) + (R-rlang "^ *[0-9]+\\..* \\(\\([^ :]+\\):\\([0-9]+\\):\\([0-9]+\\)\\)$" 2 3 4 nil 1) + (R-recover " *[0-9]+: +\\([^:\n\t]+?\\)#\\([0-9]+:\\)" 1 2 nil 2 1))) + (cl-pushnew l compilation-error-regexp-alist-alist)) + +(define-obsolete-variable-alias 'ess-r-versions-created 'ess-r-created-runners "ESS 18.10") +(defvar ess-r-created-runners nil + "List of R-versions found from `ess-r-runner-prefixes' on the system.") + + +;;;*;;; Mode init + +(define-obsolete-variable-alias 'ess-R-post-run-hook 'ess-r-post-run-hook "ESS 18.10.2") + +;; We moved the set-wd instruction from `inferior-ess' to here to +;; avoid sending R code to gdb or lldb before we had a chance to +;; send "run". So this is no longer generic and inferior modes need +;; to call this manually. One way to fix this would be to make +;; `inferior-ess' a `cl-defgeneric'. +(defvar ess-r-post-run-hook nil + "Functions run in process buffer after the initialization of R process. +Make sure to call blocking commands (e.g. based on `ess-command') +first. Streaming commands (e.g. based on `ess-send-string') +should come last, otherwise they will make R busy and the +blocking commands will throw an error.") + +;;;###autoload +(defun run-ess-r (&optional start-args) + "Call 'R', the 'GNU S' system from the R Foundation. +Optional prefix (\\[universal-argument]) allows to set command line arguments, such as +--vsize. This should be OS agnostic. +If you have certain command line arguments that should always be passed +to R, put them in the variable `inferior-R-args'. + +START-ARGS can be a string representing an argument, a list of +such strings, or any other non-nil value. In the latter case, you +will be prompted to enter arguments interactively." + (interactive "P") + (ess-write-to-dribble-buffer ;; for debugging only + (format + "\n(R): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n" + ess-dialect (current-buffer) start-args current-prefix-arg)) + (unless (or (file-remote-p default-directory) + (when ess-startup-directory + (file-remote-p (if (symbolp ess-startup-directory) + (symbol-value ess-startup-directory) + ess-startup-directory))) + ;; TODO: Once we drop Emacs 26 support, can probably + ;; just use the REMOTE argument of `executable-find'. + (executable-find inferior-ess-r-program)) + (display-warning 'ess (format "%s could not be found on the system. Try running `run-ess-r-newest' instead, which searches your system for R." inferior-ess-r-program) :error) + (user-error "%s program not found" inferior-ess-r-program)) + (let* ((r-always-arg + (if (or ess-microsoft-p (eq system-type 'cygwin)) + "--ess " + ;; else: "Unix alike" + (if (not ess-R-readline) "--no-readline "))) + (start-args + (cond ((stringp start-args) + start-args) + ((and start-args + (listp start-args) + (cl-every #'stringp start-args)) + (mapconcat #'identity start-args " ")) + (start-args + (read-string + (concat "Starting Args" + (if r-always-arg + (concat " [other than '" r-always-arg "']")) + " ? "))))) + (r-start-args + (concat r-always-arg + inferior-R-args " " ; add space just in case + start-args)) + (debug (string-match-p " -d \\| --debugger=" r-start-args)) + use-dialog-box) + (when (or ess-microsoft-p + (eq system-type 'cygwin)) + (setq use-dialog-box nil) + (when ess-microsoft-p ;; default-process-coding-system would break UTF locales on Unix + (setq default-process-coding-system '(undecided-dos . undecided-dos)))) + + (let ((inf-buf (inferior-ess r-start-args ess-r-customize-alist debug))) + (with-current-buffer inf-buf + (ess-process-put 'funargs-pre-cache ess-r--funargs-pre-cache) + (if debug + (progn + ;; We need to use callback, because R might start with a gdb process + (ess-process-put 'callbacks '(inferior-ess-r--init-callback)) + ;; Trigger the callback + (process-send-string (get-buffer-process inf-buf) "r\n")) + (ess-r-initialize) + (comint-goto-process-mark))) + inf-buf))) + +;;;###autoload +(defun R (&optional start-args) + (interactive "P") + ;; FIXME: Current ob-R expects current buffer set to process buffer + (set-buffer (run-ess-r start-args))) + +(defun inferior-ess-r--init-callback (_proc _name) + (ess-r-initialize)) + +(defvar ess-r--init-timeout 5 + "Maximum time for R to become available on startup. +If the timeout is reached, an error is thrown advising the user +to run `ess-r-initialize' again.") + +(define-obsolete-function-alias 'R-initialize-on-start + #'ess-r-initialize "ESS 19.04") + +(defun ess-r-initialize () + "This function is run after the first R prompt. +Executed in process buffer." + (interactive) + (condition-case err + (progn + (unless (ess-wait-for-process nil nil nil nil ess-r--init-timeout) + (error "Process is busy")) + (ess-command (ess-r--init-options-command)) + (ess-r-load-ESSR)) + (error (ess-r--init-error-handler err)) + (quit (ess-r--init-error-handler))) + (ess-process-put 'format-command-alist ess-r-format-command-alist) + (ess-process-put 'bg-eval-disabled nil) + (ess-execute-screen-options t) + (ess-set-working-directory default-directory) + (when ess-use-tracebug + (ess-tracebug 1)) + (add-hook 'ess-presend-filter-functions #'ess-R-scan-for-library-call nil 'local) + ;; Wait before running user hook so they can call blocking commands + (ess-wait-for-process) + (run-hooks 'ess-r-post-run-hook) + (ess-wait-for-process)) + +(defun ess-r--init-error-handler (&optional err) + (ess-write-to-dribble-buffer "Failed to start ESSR\n") + (when-let ((proc (and ess-local-process-name + (get-process ess-local-process-name)))) + (process-put proc 'bg-eval-disabled t)) + (let ((msgs `("ESSR failed to start, please call `ess-r-initialize' to recover" + ,@(when err + (concat "Caused by error: " (error-message-string err)))))) + (error (mapconcat 'identity msgs "\n")))) + +;; FIXME: Should we stop setting `str.dendogram.last`? See: +;; https://emacs.stackexchange.com/questions/27673/ess-dendrograms-appearance-of-last-branch/27729#27729 +;; +;; FIXME: We don't use `ess-r-pager`? It's nil by default and +;; documented that this should not normally be set +(defun ess-r--init-options-command () + (let ((args (list (format "STERM = '%s'" ess-STERM) + "str.dendrogram.last = '\\''" + (format "editor = '%s'" ess-r-editor) + (ess-r--update-opt-if-eq "pager" + "file.path(R.home(), 'bin', 'pager')" + (format "'%s'" inferior-ess-pager)) + "show.error.locations = TRUE"))) + (format "options(%s)\n" (mapconcat 'identity args ", ")))) + +(defun ess-r--update-opt-if-eq (opt old new) + (let ((actual (format "getOption('%s')" opt))) + (format "%s = if (identical(%s, %s)) %s else %s" + opt + actual + old + new + actual))) + +(defun ess-r--skip-function () + ;; Assumes the point is at function start + (if (looking-at-p ess-r-set-function-start) + (forward-list 1) ; get over the entire setXyz(...) + (forward-list 1) ; get over arguments + (if (looking-at-p "[ \t\n]*{") + (forward-sexp 1) ;; move over {...} + ;; {..}-less case + (skip-chars-forward " \t\n") + (goto-char (cadr (ess-continuations-bounds)))))) + +;; `beginning-of-defun' protocol: +;; 1) assumes that defuns are at the top level (e.g. always moves to bol) +(defun ess-r-beginning-of-defun (&optional arg) + "Move to beginning a top level function. +ARG is as in `beginning-of-defun'." + (ess-r-beginning-of-function arg t)) + +;; `end-of-defun' protocol: +;; 1) Uses beginning-of-defun-function with negative arg +;; 2) Assumes that beginning-of-defun-function with -1 arg finds current defun +;; when point is just in front of the function +(defun ess-r-end-of-defun (&optional arg) + "End of top level function. +ARG is as in `end-of-defun'." + (ess-r-end-of-function arg t)) + +(defun ess-r-beginning-of-function (&optional arg top-level) + "Leave (and return) the point at the beginning of the current ESS function. +When ARG is positive, search for beginning of function backward, +otherwise forward. Value of ARG is currently ignored. Return the +new position, or nil if no-match. If TOP-LEVEL is non-nil, search +for top-level functions only." + (setq arg (or arg 1)) + (let ((start-point (point)) + done) + ;; In case we are at the start of a function, skip past new lines. + (when (> arg 0) + ;; Start search from a forward position in order to capture current + ;; function start. But not when arg < 0; see end-of-defun protocol above. + (forward-line 2)) + (while (and (not done) + (re-search-backward ess-r-function-pattern nil t arg)) + (unless (ess-inside-string-or-comment-p) + (setq done + (if top-level + (= (car (syntax-ppss (match-beginning 0))) 0) + t)) + (if (< arg 0) + ;; move to match-end to avoid the infloop in re-search-backward + (goto-char (if done (match-beginning 0) (match-end 0))) + ;; Backward regexp match stops at the minimal match (e.g. partial + ;; function name), so we need a bit more work here. + (beginning-of-line) + (re-search-forward ess-r-function-pattern) + (goto-char (match-beginning 0)) + (when (<= start-point (point)) + (setq done nil))))) + (if done + (point) + (goto-char start-point) + nil))) + +(defun ess-r-end-of-function (&optional arg top-level) + "Leave the point at the end of the current function. +When ARG is positive, search for end of function forward, +otherwise backward. Move to point and return point if search was +successful, otherwise nil. If TOP-LEVEL is non-nil, search for +top level functions only." + (setq arg (or arg 1)) + (let* ((start-pos (point)) + (search-fn (lambda (lim) + (let ((foundp nil)) + (while (and (not foundp) + (re-search-forward ess-r-function-pattern nil t)) + (when (< arg 0) + ;; re-search-backward is a forward search + ;; internally, so we need to bol in order to avoid + ;; the infloop + (beginning-of-line)) + (setq foundp + (unless (ess-inside-string-or-comment-p) + (if top-level + (= 0 (car (save-excursion (syntax-ppss (match-beginning 0))))) + (>= (point) lim))))) + (if foundp + (progn (goto-char (match-beginning 0)) + (ess-r--skip-function)) + (goto-char start-pos)))))) + (ess-r-beginning-of-function 1 top-level) + (if (< (point) start-pos) + ;; Moved back. We were either inside a function or after a function. + (progn + (ess-r--skip-function) + ;; For negative ARG we are done. + (when (and (> arg 0) + (<= (point) start-pos)) + (funcall search-fn start-pos))) + ;; No function before point; search forward on positive ARG. + (when (> arg 0) + (funcall search-fn start-pos))))) + +;;;###autoload +(define-derived-mode ess-r-mode ess-mode "ESS[R]" + "Major mode for editing R source. See `ess-mode' for more help." + :group 'ess-R + (set-syntax-table ess-r-mode-syntax-table) + (ess-setq-vars-local ess-r-customize-alist) + (setq-local ess-font-lock-keywords 'ess-R-font-lock-keywords) + (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-ignore-fill-prefix t) + (setq-local indent-line-function #'ess-r-indent-line) + (setq-local comment-indent-function #'ess-calculate-indent) + (setq-local add-log-current-defun-header-regexp "^\\(.+\\)\\s-+<-[ \t\n]*function") + (setq-local font-lock-syntactic-face-function #'ess-r-font-lock-syntactic-face-function) + (setq-local syntax-propertize-function ess-r--syntax-propertize-function) + (setq-local electric-layout-rules '((?{ . after))) + ;; indentation + (add-hook 'hack-local-variables-hook #'ess-set-style nil t) + ;; eldoc + (ess--setup-eldoc #'ess-r-eldoc-function) + ;; auto-complete + (ess--setup-auto-complete ess-r-ac-sources) + ;; company + (ess--setup-company ess-r-company-backends) + (setq-local prettify-symbols-alist ess-r-prettify-symbols) + (setq font-lock-defaults '(ess-build-font-lock-keywords nil nil ((?\. . "w") (?\_ . "w")))) + (remove-hook 'completion-at-point-functions #'ess-filename-completion 'local) ;; should be first + (add-hook 'completion-at-point-functions #'ess-r-object-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-r-package-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-filename-completion nil 'local) + (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local) + (add-hook 'project-find-functions #'ess-r-project nil 'local) + + (if (fboundp 'ess-add-toolbar) (ess-add-toolbar)) + ;; imenu is needed for `which-function' + (setq imenu-generic-expression ess-imenu-S-generic-expression) + (when ess-imenu-use-S + (imenu-add-to-menubar "Imenu-R")) + (setq-local beginning-of-defun-function #'ess-r-beginning-of-defun) + (setq-local end-of-defun-function #'ess-r-end-of-defun) + (ess-roxy-mode)) +;;;###autoload +(defalias 'R-mode #'ess-r-mode) +;;;###autoload +(defalias 'r-mode #'ess-r-mode) + + +;;;###autoload +(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . ess-r-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . ess-r-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . ess-r-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . ess-r-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("CITATION\\'" . ess-r-mode)) + + +;;;*;;; Project detection + +(defvar-local ess-r-project--info-cache nil + "Current package info cache. +See `ess-r-project-info' for its structure.") + +(defun ess-r-project (&optional dir) + "Return the current project as an Emacs project instance. +R project is a directory XYZ containing either .Rprofile, +DESCRIPTION or XYZ.Rproj file. Return a list of the form (:name +\"XYZ\" :root \"/path/to/project\"). If DIR is provided, the +project is searched from that directory instead of +`default-directory'." + (let ((info (ess-r-project-info dir))) + (when (car info) + (cons 'ess-r-project (plist-get info :root))))) + +;; FIXME: remove when emacs 27 is dropped +(unless (eval-when-compile + (get 'project-roots 'byte-obsolete-info)) + (cl-defmethod project-roots ((project (head ess-r-project))) + "Return the project root for ESS R projects." + (list (cdr project)))) + +(cl-defmethod project-root ((project (head ess-r-project))) + "Return the project root for ESS R projects." + (cdr project)) + +(defun ess-r-project-info (&optional dir) + "Get the description of the R project in directory DIR. +Return an plist with the keys :name and :root. When not in a +project return \\='(nil). This value is cached buffer-locally for +efficiency reasons." + (let ((do-cache (null dir))) + (if (and do-cache ess-r-project--info-cache) + ess-r-project--info-cache + (setq dir (or dir (buffer-file-name) default-directory)) + (let ((out (or + (unless (file-remote-p dir) + (let ((dir (locate-dominating-file + dir + (lambda (dir) + (or (file-exists-p (expand-file-name ".Rprofile" dir)) + (file-exists-p (expand-file-name "DESCRIPTION" dir)) + (let ((nm (file-name-nondirectory (directory-file-name dir)))) + (file-exists-p (expand-file-name (concat nm ".Rproj") dir)))))))) + (when dir + (let ((dir (directory-file-name dir))) + (unless (member dir (list "~" (getenv "HOME"))) + (list :name (file-name-nondirectory dir) + :root (expand-file-name dir))))))) + '()))) + (when do-cache + (setq ess-r-project--info-cache out)) + out)))) + + + +;;*;; Miscellaneous + +(defun ess-R-arch-2-bit (arch) + "Translate R's architecture shortcuts/directory names to `bits'. +ARCH \"32\" or \"64\" (for now)." + (if (string= arch "i386") "32" + ;; else: + "64")) + +(defun ess-rterm-arch-version (long-path &optional give-cons) + "Find a name for LONG-PATH, an absolute path to R on Windows. +Returns either Name, a string, or a (Name . Path) cons, such as + +(\"R-2.12.1-64bit\" . \"C:/Program Files/R/R-2.12.1/bin/x64/Rterm.exe\") + +\"R-x.y.z/bin/Rterm.exe\" will return \"R-x.y.z\", for R-2.11.x and older. +\"R-x.y.z/bin/i386/Rterm.exe\" return \"R-x.y.z-32bit\", for R-2.12.x and newer. +\"R-x.y.z/bin/x64/Rterm.exe\" return \"R-x.y.z-64bit\", for R-2.12.x and newer." + (let* ((dir (directory-file-name (file-name-directory long-path))) + (dir2 (directory-file-name (file-name-directory dir))) + (v-1up (file-name-nondirectory dir));; one level up + (v-2up (file-name-nondirectory dir2));; two levels up; don't want "bin" ... + (v-3up (file-name-nondirectory ;; three levels up; no "bin" for i386, x64 ... + (directory-file-name (file-name-directory dir2)))) + (val (if (string= v-2up "bin") + (concat v-3up "-" (ess-R-arch-2-bit v-1up) "bit") + ;; pre R-2.12.x, or when there's no extra arch-specific sub directory: + v-2up))) + (if give-cons + (cons val long-path) + val))) + +(defun ess-r-define-runners (&optional verbose) + "Generate functions for starting other versions of R. +See `ess-r-runner-prefixes' for strings that determine which functions +are created. On MS Windows, this works using +`ess-rterm-version-paths' instead. + +The functions will normally be placed on the menubar and stored +as `ess-r-created-runners' upon ESS initialization." + (when ess-r-runner-prefixes + (let ((versions + ;; Find which versions of R we want. Remove the pathname, leaving just + ;; the name of the executable. + (if ess-microsoft-p + (mapcar (lambda (v) (car (ess-rterm-arch-version v 'give-cons))) + ess-rterm-version-paths) + (delete-dups + (mapcar #'file-name-nondirectory + (apply #'nconc + (mapcar #'ess-find-exec-completions + ess-r-runner-prefixes))))))) + ;; Iterate over each string in VERSIONS, creating a new defun each time. + (setq ess-r-created-runners versions) + (if verbose + (message "Recreated %d R versions known to ESS: %s" + (length versions) versions)) + (if ess-microsoft-p + (cl-mapcar (lambda (v p) (ess-define-runner v "R" p)) versions ess-rterm-version-paths) + (mapc (lambda (v) (ess-define-runner v "R")) versions)) + ;; Add to menu + (when ess-r-created-runners + ;; new-menu will be a list of 3-vectors, of the form: + ;; ["R-1.8.1" R-1.8.1 t] + (let ((new-menu (mapcar (lambda(x) (vector x (intern x) t)) + ess-r-created-runners))) + (easy-menu-add-item ess-mode-menu '("Start Process") + (cons "Other" new-menu)) + (easy-menu-add-item inferior-ess-mode-menu '("Process") + (cons "R processes" new-menu))))))) + +(defun ess-r-redefine-runners (&optional verbose) + "Regenerate runners, i.e. `M-x R-*` possibilities. + Call `fmakunbound' on all elements of `ess-r-created-runners', + then define new runners." + (interactive "P") + (dolist (f ess-r-created-runners) + (fmakunbound (intern f))) + (setq ess-r-created-runners nil) + (ess-r-define-runners verbose)) + +(defun ess-r-runners-reset (sym val) + "Regenerate runners. +Set SYM to VAL and call `ess-r-redefine-runners'." + (set-default sym val) + (ess-r-redefine-runners)) + +(define-obsolete-function-alias + 'ess-r-versions-create #'ess-r-define-runners "ESS 18.10") + +(defvar ess-newest-R nil + "Stores the newest version of R that has been found. +Used as a cache, within `ess-find-newest-R'. Do not use this value +directly, but instead call the function \\[ess-find-newest-R].") + + +(defcustom ess-prefer-higher-bit t + "Non-nil means prefer higher bit architectures of R. +e.g. prefer 64 bit over 32 bit. This is currently used only +by the code on Windows for finding the newest version of R." + :group 'ess-R + :type 'boolean) + +(defun ess-rterm-prefer-higher-bit () + "Optionally remove 32bit Rterms from being candidate for `run-ess-r-newest'. +Return the list of candidates for being `run-ess-r-newest'. Filtering is +done iff `ess-prefer-higher-bit' is non-nil. This is used only by +Windows when running `ess-find-newest-R'." + (if ess-prefer-higher-bit + ;; filter out 32 bit elements + (let ((filtered + (delq nil + (mapcar (lambda (x) (unless (string-match "/i386/Rterm.exe" x) x)) + ess-rterm-version-paths)))) + (if (null filtered) + ;; if none survived filtering, keep the original list + ess-rterm-version-paths + filtered)) + ess-rterm-version-paths)) + +(defun run-ess-r-newest (&optional start-args) + "Find the newest version of R available, and run it. +Subsequent calls to `run-ess-r-newest' will run that version, +rather than searching again for the newest version. Providing +START-ARGS (interactively, with \\[universal-argument]) will +prompt for command line arguments." + (interactive "P") + (unless ess-newest-R + (message "Finding all versions of R on your system...") + (setq ess-newest-R + (ess-find-newest-date + (mapcar #'ess-r-version-date + (if ess-microsoft-p + (ess-rterm-prefer-higher-bit) + (add-to-list 'ess-r-created-runners inferior-ess-r-program)))))) + (let ((inferior-ess-r-program ess-newest-R)) + (run-ess-r start-args))) + +(defun R-newest (&optional start-args) + (interactive "P") + ;; FIXME: Current ob-R expects current buffer set to process buffer + (set-buffer (run-ess-r-newest start-args))) + +;; (ess-r-version-date "R-2.5.1") (ess-r-version-date "R-patched") +;; (ess-r-version-date "R-1.2.1") (ess-r-version-date "R-1.8.1") +;; Windows: +;; (ess-r-version-date "C:/Program Files (x86)/R/R-2.11.1/bin/Rterm.exe") +;; Note that for R-devel, ver-string is something like +;; R version 2.6.0 Under development (unstable) (2007-07-14 r42234) +;; Antique examples are 'R 1.0.1 (April 14, 2000)' or 'R 1.5.1 (2002-06-17).' +(defun ess-r-version-date (rver) + "Return the date of the version of R named RVER. +The date is returned as a date string. If the version of R could +not be found from the output of the RVER program, \"-1\" is +returned." + (let ((date "-1") + (ver-string (shell-command-to-string + ;; here, MS Windows (shell-command) needs a short name: + (concat (if (and ess-microsoft-p + ;; silence byte compiler warns about w32-fns + (fboundp 'w32-short-file-name)) + (w32-short-file-name rver) + rver) + " --version")))) + (when (string-match + "R \\(version \\)?[1-9][^\n]+ (\\(2[0-9-]+\\)\\( r[0-9]+\\)?" + ver-string) + (setq date (match-string 2 ver-string))) + (cons date rver))) + +(defun ess-current-R-version () + "Get the version of R currently running in the ESS buffer as a string." + (ess-make-buffer-current) + (car (ess-get-words-from-vector (format "base::as.character(%s)\n" + (ess-r--format-call ".ess.Rversion"))))) + +(defun ess-current-R-at-least (version) + "Is the version of R (in the ESS buffer) at least (\">=\") VERSION ? +Examples: (ess-current-R-at-least '2.7.0) + or (ess-current-R-at-least \"2.5.1\")" + (ess-make-buffer-current) + (string= "TRUE" + (car (ess-get-words-from-vector + (format "base::as.character(%s >= \"%s\")\n" + (ess-r--format-call ".ess.Rversion") + version))))) +(defun ess-find-newest-date (rvers) + "Find the newest version of R given in the a-list RVERS. +Each element of RVERS is a dotted pair (date . R-version), where +date is given as e.g.\"2007-11-30\" so that we can compare dates +as strings. If a date is listed as \"-1\", that version of R +could not be found. + +If the value returned is nil, no valid newest version of R could be found." + (let (new-r this-r + (new-time "0")) + (while rvers + (setq this-r (car rvers) + rvers (cdr rvers)) + (when (string< new-time (car this-r)) + (setq new-time (car this-r) + new-r (cdr this-r)))) + new-r)) + +(defun ess-find-rterm (&optional ess-R-root-dir bin-Rterm-exe) + "Find the full path of all occurrences of Rterm.exe under the ESS-R-ROOT-DIR. +If ESS-R-ROOT-DIR is nil, construct it by looking for an +occurrence of Rterm.exe in the `exec-path'. If there are no +occurrences of Rterm.exe in the `exec-path', then use +`ess-program-files' (which evaluates to something like +\"c:/progra~1/R/\" in English locales) which is the default +location for the R distribution. If BIN-RTERM-EXE is nil, then +use \"bin/Rterm.exe\"." + (if (not ess-R-root-dir) + (let ((Rpath (executable-find "Rterm"))) + (setq ess-R-root-dir + (expand-file-name + (if Rpath + (concat (file-name-directory Rpath) "../../") + (concat ess-program-files "/R/")))) + (ess-write-to-dribble-buffer + (format "(ess-find-rterm): ess-R-root-dir = '%s'\n" ess-R-root-dir)))) + + (if (not bin-Rterm-exe) (setq bin-Rterm-exe "bin/Rterm.exe")) + + (when (file-directory-p ess-R-root-dir) ; otherwise file-name-all-.. errors + (setq ess-R-root-dir + (replace-regexp-in-string "[\\]" "/" ess-R-root-dir)) + (let ((R-ver + (ess-drop-non-directories + (ess-flatten-list + (mapcar (lambda (r-prefix) + (file-name-all-completions r-prefix ess-R-root-dir)) + (append '("rw") ess-r-runner-prefixes)))))) + (mapcar (lambda (dir) + (let ((R-path + (concat ess-R-root-dir + (replace-regexp-in-string "[\\]" "/" dir) + bin-Rterm-exe))) + (if (file-exists-p R-path) R-path))) + R-ver)))) + +;;;###autoload +(define-derived-mode ess-r-transcript-mode ess-transcript-mode "ESS R Transcript" + "A Major mode for R transcript files." + :syntax-table ess-r-mode-syntax-table + :group 'ess + (ess-setq-vars-local ess-r-customize-alist) + (setq-local comint-prompt-regexp inferior-S-prompt) + (setq-local ess-font-lock-keywords 'ess-R-font-lock-keywords) + (setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-separate (concat "\\s-*$\\|" page-delimiter)) + (setq-local paragraph-ignore-fill-prefix t) + (setq-local indent-line-function #'ess-r-indent-line) + (setq-local add-log-current-defun-header-regexp "^\\(.+\\)\\s-+<-[ \t\n]*function") + (setq-local font-lock-syntactic-face-function #'ess-r-font-lock-syntactic-face-function) + (setq-local prettify-symbols-alist ess-r-prettify-symbols) + (setq font-lock-defaults '(ess-build-font-lock-keywords + nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))) + +(defalias 'r-transcript-mode #'ess-r-transcript-mode) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Rr]out\\'" . ess-r-transcript-mode)) +;;;###autoload +(add-to-list 'interpreter-mode-alist '("Rscript" . ess-r-mode)) +;;;###autoload +(add-to-list 'interpreter-mode-alist '("r" . ess-r-mode)) + +(defun ess-r-fix-T-F (&optional from quietly) + "Change T/F into TRUE and FALSE cautiously. +Do not change in comments and strings. Start at FROM, which +defaults to point, and change to end of buffer. When QUIETLY, do +not issue messages." + (interactive "d\nP"); point and prefix (C-u) + (save-excursion + (goto-char from) + (ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)T\\>" "\\1TRUE" + 'fixcase nil (not quietly)) + (goto-char from) + (ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)F\\>" "\\1FALSE" + 'fixcase nil (not quietly)))) +(define-obsolete-function-alias 'R-fix-T-F #'ess-r-fix-T-F + "ESS 18.10") + +(defvar ess--packages-cache nil + "Cache var to store package names. +Used by `ess-r-install-library'.") + +(defvar ess--CRAN-mirror nil + "CRAN mirror name cache.") + +(cl-defmethod ess-install-library--override (update package &context (ess-dialect "R")) + "Prompt and install R PACKAGE. +With argument UPDATE, update cached packages list." + (inferior-ess-r-force) + (when (equal "@CRAN@" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n"))) + (ess-set-CRAN-mirror ess--CRAN-mirror) + (ess-wait-for-process (get-process ess-current-process-name)) + (unless package (setq update t))) + (when (or update + (not ess--packages-cache)) + (message "Fetching R packages ... ") + (setq ess--packages-cache + (ess-get-words-from-vector--foreground "print(rownames(available.packages()), max=1e6)\n"))) + (let* ((ess-eval-visibly-p t) + (package (or package + (ess-completing-read "Package to install" ess--packages-cache)))) + (process-send-string (get-process ess-current-process-name) + (format "install.packages('%s')\n" package)) + (display-buffer (buffer-name (ess-get-process-buffer))))) + +(defun ess-setRepositories () + "Call setRepositories()." + (interactive) + (if (not (string-match "^R" ess-dialect)) + (message "Sorry, not available for %s" ess-dialect) + (ess-eval-linewise "setRepositories(FALSE)\n"))) + +(defun ess-set-CRAN-mirror (&optional mirror) + "Set cran MIRROR." + (interactive) + (let ((mirror-cmd "local({r <- getOption('repos'); r['CRAN'] <- '%s';options(repos=r)})\n")) + (if mirror + (ess-command (format mirror-cmd mirror)) + (when-let ((M1 (ess-get-words-from-vector "local({out <- getCRANmirrors(local.only=TRUE); print(paste(out$Name,'[',out$URL,']', sep=''))})\n")) + (mirror (ess-completing-read "Choose CRAN mirror" M1 nil t)) + (url (car (cl-member mirror M1 :test #'string=)))) + (setq ess--CRAN-mirror (progn (string-match "\\(.*\\)\\[\\(.*\\)\\]$" url) + (match-string 2 url))) + (ess-command (format mirror-cmd ess--CRAN-mirror))))) + (message "CRAN mirror: %s" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n")))) +(define-obsolete-function-alias 'ess-setCRANMiror #'ess-set-CRAN-mirror "ESS 18.10") + +(defun ess-r-check-install-package (pkg) + "Check if package PKG is installed and offer to install if not." + (unless (ess-boolean-command (format "print(requireNamespace('%s', quietly = TRUE))\n" pkg)) + (if (y-or-n-p (format "Package '%s' is not installed. Install? " pkg)) + (ess-eval-linewise (format "install.packages('%s')\n" pkg)) + (signal 'quit nil)))) + +(define-obsolete-function-alias 'ess-r-sos #'ess-help-web-search "ESS 19.04") + +(cl-defmethod ess--help-web-search-override (cmd &context (ess-dialect "R")) + (ess-r-check-install-package "sos") + (ess-eval-linewise (format "sos::findFn(\"%s\", maxPages=10)" cmd))) + + +(defun ess-R-scan-for-library-call (string) + "Detect `library/require' call in STRING and update tracking vars. +Placed into `ess-presend-filter-functions' for R dialects." + (when (string-match-p "\\blibrary(\\|\\brequire(" string) + (ess--mark-search-list-as-changed)) + string) + +(cl-defmethod ess-installed-packages (&context (ess-dialect "R")) + ;;; FIXME? .packages() does not cache; installed.packages() does but is slower first time + (ess-get-words-from-vector--foreground "print(.packages(TRUE), max=1e6)\n")) + +(cl-defmethod ess-load-library--override (pack &context (ess-dialect "R")) + "Load an R package." + (ess-eval-linewise (format "library('%s')\n" pack))) + +(define-obsolete-function-alias 'ess-library #'ess-load-library "ESS[12.09-1]") + +;;; smart-comma was a bad idea +(eval-after-load "eldoc" + '(eldoc-add-command "ess-smart-comma")) + + +;;*;; Interaction with R + +;;;*;;; Evaluation + +(defun ess-r-arg (param value &optional wrap) + (let ((value (if wrap + (concat "'" value "'") + value))) + (concat ", " param " = " value))) + +(defun ess-r-build-args (visibly output namespace) + (let ((visibly (ess-r-arg "visibly" (if visibly "TRUE" "FALSE"))) + (output (ess-r-arg "output" (if output "TRUE" "FALSE"))) + (pkg (when namespace (ess-r-arg "package" namespace t))) + (verbose (when (and namespace + ess-r-namespaced-load-verbose) + (ess-r-arg "verbose" "TRUE")))) + (concat visibly output pkg verbose))) + +(defun ess-r--format-call (cmd &rest objects) + "Prefix an ESSR command with a namespace qualifier. +CMD is formatted with OBJECTS using `format'." + (concat "base::as.environment('ESSR')$" + (apply #'format cmd objects))) + +(cl-defmethod ess-build-eval-command--override (string &context (ess-dialect "R") + &optional visibly output file &rest args) + "R method to build eval command." + (let* ((namespace (caar args)) + (namespace (unless ess-debug-minor-mode + (or namespace (ess-r-get-evaluation-env)))) + (cmd (ess-r--format-call (if namespace ".ess.ns_eval" ".ess.eval"))) + (file (when file (ess-r-arg "file" file t))) + (rargs (ess-r-build-args visibly output namespace))) + (concat cmd "(\"" string "\"" rargs file ")\n"))) + +(cl-defmethod ess-build-load-command (string &context (ess-dialect "R") + &optional visibly output file &rest _args) + (let* ((namespace (or file (ess-r-get-evaluation-env))) + (cmd (ess-r--format-call (if namespace ".ess.ns_source" ".ess.source"))) + (rargs (ess-r-build-args visibly output namespace))) + (concat cmd "('" string "'" rargs ")\n"))) + +(defun ess-r-build-eval-message (message) + (let ((env (cond (ess-debug-minor-mode + (substring-no-properties ess-debug-indicator 1)) + ((ess-r-get-evaluation-env))))) + (if env + (format "[%s] %s" env message) + message))) + +(defvar-local ess-r-evaluation-env nil + "Environment into which code should be evaluated. +When this variable is nil, code is evaluated in the current +environment. Currently only packages can be set as evaluation +environments. Use `ess-r-set-evaluation-env' to set this +variable.") + +(defun ess-r-get-evaluation-env () + "Get current evaluation env." + ess-r-evaluation-env) + +(defun ess-r-set-evaluation-env (&optional arg) + "Select a package namespace for evaluation of R code. + +Call interactively with a prefix argument to disable evaluation +in a namespace. When calling from a function, ARG can be a +string giving the package to select, any other non-nil value to +disable, or nil to prompt for a package. + +If `ess-r-prompt-for-attached-pkgs-only' is non-nil, prompt only for +attached packages." + (interactive "P") + (let ((env (cond ((stringp arg) arg) + ((null arg) (ess-r--select-package-name)) + (t "*none*")))) + (if (equal env "*none*") + (let ((cur-env (ess-r-get-evaluation-env))) + (setq ess-r-evaluation-env nil) + (delq 'ess-r--evaluation-env-mode-line ess--local-mode-line-process-indicator) + (message (format "Evaluation in %s disabled" (propertize cur-env 'face font-lock-function-name-face)))) + (setq ess-r-evaluation-env env) + (add-to-list 'ess--local-mode-line-process-indicator 'ess-r--evaluation-env-mode-line t) + (message (format "Evaluating in %s" (propertize env 'face font-lock-function-name-face)))) + (force-mode-line-update))) + +(defvar-local ess-r--evaluation-env-mode-line + '(:eval (let ((env (ess-r-get-evaluation-env))) + (if env + (format " %s" + (propertize (if (equal env (ess-r-package-name)) + "pkg" + env) + 'face 'mode-line-emphasis)) + "")))) +(put 'ess-r--evaluation-env-mode-line 'risky-local-variable t) + +(defvar ess-r-namespaced-load-only-existing t + "Whether to load only objects already existing in a namespace.") + +(cl-defmethod ess-load-file--override (file &context (ess-dialect "R")) + (cond + ;; Namespaced evaluation + ((ess-r-get-evaluation-env) + (ess-r-load-file-namespaced file)) + ;; Evaluation into current env via .ess.source() + (t + (let ((command (ess-build-load-command file nil t))) + (ess-send-string (ess-get-process) command))))) + +(defun ess-r-load-file-namespaced (&optional file) + "Load FILE into a package namespace. + +This prompts for a package when no package is currently +selected (see `ess-r-set-evaluation-env')." + (ess-force-buffer-current "R process to use: ") + (let* ((pkg-name (ess-r-get-evaluation-env)) + (command (ess-build-load-command file nil t pkg-name))) + (ess-send-string (ess-get-process) command))) + +(cl-defmethod ess-send-region--override (process start end visibly message type + &context (ess-dialect "R")) + (cond + ;; Namespaced evaluation + ((ess-r-get-evaluation-env) + (ess-r-send-region-namespaced process start end visibly message)) + ;; Evaluation into current env + (t + (ess-send-string process (buffer-substring start end) visibly message type)))) + +(defun ess-r-send-region-namespaced (proc start end &optional visibly message) + "Ask for for the package and devSource region into it." + (or (ess-r-get-evaluation-env) + (ess-r-set-evaluation-env)) + (message (ess-r-build-eval-message (or message "Eval region"))) + (ess-send-string proc (buffer-substring start end) visibly message)) + + +;;;*;;; Help + +(cl-defmethod ess-build-help-command (object &context (ess-dialect "R")) + (let ((info (ess-r--split-namespace object))) + (if info + (ess-r-help--build-help-command--qualified (car info) (cdr info)) + (ess-r-help--build-help-command--unqualified object)))) + +(defun ess-r--split-namespace (sym) + (when (string-match "^[[:alnum:].]+::" sym) + (let ((pkg (substring-no-properties sym (match-beginning 0) (- (match-end 0) 2))) + (obj (substring-no-properties sym (match-end 0)))) + (cons pkg obj)))) + +(defvar-local ess-r-help--local-object nil) +(defvar-local ess-r-help--local-package nil) +(put 'ess-r-help--local-object 'permanent-local t) +(put 'ess-r-help--local-package 'permanent-local t) + +(defun ess-r-help--build-help-command--qualified (pkg obj) + (setq ess-r-help--local-package pkg) + (setq ess-r-help--local-object obj) + (let ((obj-arg (concat "'" obj "'")) + (pkg-arg (ess-r-arg "package" pkg t))) + (ess-r--format-call ".ess.help(%s%s)\n" obj-arg pkg-arg))) + +(defun ess-r-help--build-help-command--unqualified (obj) + (if (eq ess-help-type 'index) + ;; We are in index page, qualify with namespace + (ess-r-help--build-help-command--qualified ess-help-object obj) + (let ((pkg (ess-r-help--find-package obj))) + (unless pkg + (error "Can't find documentation for `%s'" obj)) + (ess-r-help--build-help-command--qualified pkg obj)))) + +(defun ess-r-help--find-package (object) + "Find package where to find OBJECT. +If there are multiple packages attached to the search path, the +user is prompted for a package location. If OBJECT is not +documented, returns nil." + (let* ((paths (ess-get-words-from-vector + (format "as.character(utils::help('%s'))\n" object))) + (paths (if (> (length paths) 1) + (cl-delete-if + (lambda (x) (string-match-p "reexports$" x)) + paths) + paths))) + (cond ((not paths) + nil) + ((and (> (length paths) 1) + (not noninteractive)) + (let ((path (ess-completing-read "Choose location" paths nil t))) + (ess-r-help--get-pkg-from-help-path path))) + (t + (ess-r-help--get-pkg-from-help-path (car paths)))))) + +(defun ess-r-help--get-pkg-from-help-path (path) + (file-name-nondirectory + (directory-file-name + (file-name-directory + (directory-file-name + (file-name-directory + path)))))) + +(defconst inferior-ess-r--input-help (format "^ *help *(%s)" ess-help-arg-regexp)) +(defconst inferior-ess-r--input-?-help-regexp "^ *\\(?:\\(?1:[a-zA-Z ]*?\\?\\{1,2\\}\\) *\\(?2:.+\\)\\)") +(defconst inferior-ess-r--page-regexp (format "^ *page *(%s)" ess-help-arg-regexp)) + +(defun ess-help-r--process-help-input (proc string) + (let ((help-match (and (string-match inferior-ess-r--input-help string) + (match-string 2 string))) + (help-?-match (and (string-match inferior-ess-r--input-?-help-regexp string) + string)) + (page-match (and (string-match inferior-ess-r--page-regexp string) + (match-string 2 string)))) + (when (or help-match help-?-match page-match) + (cond (help-match + (ess-display-help-on-object help-match) + (process-send-string proc "\n")) + (help-?-match + (ess-help-r--display-help-? string help-?-match) + (process-send-string proc "\n")) + (page-match + (switch-to-buffer-other-window + (ess-command (concat page-match "\n") + (get-buffer-create (concat page-match ".rt")))) + (ess-r-transcript-mode) + (process-send-string proc "\n"))) + t))) + +(defun ess-help-r--display-help-? (string help-?-match) + (cond ((string-match "\\?\\?\\(.+\\)" help-?-match) + (ess--display-indexed-help-page (concat help-?-match "\n") + "^\\([^ \t\n]+::[^ \t\n]+\\)[ \t\n]+" + (format "*ess-apropos[%s](%s)*" + ess-current-process-name (match-string 1 help-?-match)) + 'apropos)) + ((string-match "^ *\\? *\\([^ \t]+\\)$" help-?-match) + (ess-display-help-on-object (match-string 1 help-?-match))) + ;; Anything else we send to process almost unchanged + (t + (let ((help-?-match (and (string-match inferior-ess-r--input-?-help-regexp string) + (format "%s%s" (match-string 1 string) + (ess-help-r--sanitize-topic (match-string 2 string)))))) + (ess-display-help-on-object help-?-match "%s\n"))))) + +(defun ess-help-r--sanitize-topic (string) + "Enclose help topic STRING into `` to avoid ?while ?if etc hangs." + (if (string-match "\\([^:]*:+\\)\\(.*\\)$" string) ; treat foo::bar correctly + (format "%s`%s`" (match-string 1 string) (match-string 2 string)) + (format "`%s`" string))) + + +;;;*;;; Utils for inferior R process + +(defun inferior-ess-r-input-sender (proc string) + (save-current-buffer + (or (ess-help-r--process-help-input proc string) + (inferior-ess-input-sender proc string)))) + +(defun ess-r-load-ESSR () + "Load ESSR functionality into ESSR environment. +On remotes, when `ess-r-fetch-ESSR-on-remotes' is non-nil we +fetch ESSR environment from github to the remote machine. +Otherwise (the default) we source ESSR files into the remote +process." + (interactive) + ;; `.ess.command()` is not defined until ESSR is loaded so disable + ;; it temporarily. Would be helpful to implement an `inferior-ess-let' + ;; macro . + (cond + ((file-remote-p (ess-get-process-variable 'default-directory)) + (if (eq ess-r-fetch-ESSR-on-remotes t) + (or (ess-r--fetch-ESSR-remote) + (ess-r--load-ESSR-remote)) + (ess-r--load-ESSR-remote))) + ((and (bound-and-true-p ess-remote)) + ;; NB: With ess-remote we send by chunks because sending large sources is + ;; fragile + (if ess-r-fetch-ESSR-on-remotes + (or (ess-r--fetch-ESSR-remote) + (ess-r--load-ESSR-remote t)) + (ess-r--load-ESSR-remote t))) + (t (ess-r--load-ESSR-local)))) + +(defun ess-r--load-ESSR-local () + "Load ESSR into a local process. +Source the etc/ESSR/.load.R file into the R process. The +.ess.ESSR.load function sources all of the contents of the +etc/ESSR/R directory into the ESSR environment and attaches the +environment to the search path." + (let* ((src-dir (expand-file-name "ESSR/R" ess-etc-directory)) + (buf (ess-command (ess-r--load-ESSR-command src-dir)))) + (with-current-buffer buf + (let ((msg (buffer-string))) + (when (> (length msg) 1) + (message (format "Messages while loading ESSR: %s" msg))))))) + +(defun ess-r--load-ESSR-command (src-dir) + (format "base::tryCatch( + base::local({ + base::source('%s/.load.R', local=TRUE) #define load.ESSR + .ess.ESSR.load('%s') + }), + error = function(cnd) { + msg <- paste0('ESSR::ERROR \"', conditionMessage(cnd), '\"') + writeLines(msg) + } + )\n" + src-dir + src-dir)) + +(defun ess-r--load-ESSR-remote (&optional chunked) + "Load ESSR into a remote process through the process connection. +Send the contents of the etc/ESSR/R directory to the remote +process through the process connection file by file. Then, +collect all the objects into an ESSR environment and attach to +the search path. If CHUNKED is non-nil, split each file by +separators and send chunk by chunk." + (ess-command (format ".ess.ESSRversion <<- '%s'\n" essr-version)) + (with-temp-message "Loading ESSR into remote ..." + (let ((src-dir (expand-file-name "ESSR/R" ess-etc-directory))) + (dolist (file (directory-files src-dir t "\\.R\\'")) + (ess--inject-code-from-file file chunked)) + (ess-command ".ess.collect.ESSR.objects()\n")))) + +(defun ess-r--fetch-ESSR-remote () + "Load ESSR into a remote process through a GitHub download. +Downloads a file with a serialized version of the R ESSR +environment from GitHub and attaches it to the search path. If +the file already exists on disk from a previous download then the +download step is omitted. This function returns t if the ESSR +load is successful, and nil otherwise." + (let ((loader (ess-file-content (expand-file-name "ESSR/LOADREMOTE" ess-etc-directory))) + (essr (or essr-version + ;; FIXME: Hack: on MELPA essr-version is not set + (lm-with-file (expand-file-name "ess.el" ess-lisp-directory) + (lm-header "ESSR-Version")) + (error "`essr-version' could not be automatically inferred from ess.el file")))) + (or (with-temp-message "Fetching and loading ESSR into the remote ..." + (ess-boolean-command (format loader essr))) + (let ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string)))) + (message (format "Couldn't load or download ESSR.rds on the remote.\n Error: %s\n Injecting local copy of ESSR." errmsg)) + nil)))) + +(cl-defmethod ess-quit--override (arg &context (ess-dialect "R")) + "With ARG, do not offer to save the workspace." + (let ((cmd (format "base::q('%s')\n" (if arg "no" "default"))) + (sprocess (ess-get-process ess-current-process-name))) + (when (not sprocess) (error "No ESS process running")) + (ess-cleanup) + (ess-send-string sprocess cmd))) + +(defcustom inferior-ess-r-reload-hook nil + "Hook run when reloading the R inferior buffer." + :type 'hook + :group 'ess-R) + +(cl-defmethod inferior-ess-reload--override (start-name start-args &context (ess-dialect "R")) + "Call `run-ess-r' with START-ARGS. +Then run `inferior-ess-r-reload-hook'." + (let ((inferior-ess-r-program start-name)) + (run-ess-r start-args)) + (run-hooks 'inferior-ess-r-reload-hook)) + +(defun inferior-ess-r-force (&optional prompt force no-autostart ask-if-1) + (setq-local ess-dialect "R") + (ess-force-buffer-current prompt force no-autostart ask-if-1)) + + +;;*;; Editing Tools + +;;;*;;; Indentation Engine + +;; Written by Lionel Henry in mid 2015 + +(defun ess-r-indent-line () + "Indent current line as ESS R code. +Return the amount the indentation changed by." + (when-let ((indent (ess-calculate-indent))) + (let ((case-fold-search nil) + (pos (- (point-max) (point))) + beg shift-amt) + (beginning-of-line) + (setq beg (point)) + (skip-chars-forward " \t") + (setq shift-amt (- indent (current-column))) + (if (zerop shift-amt) + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos))) + (delete-region beg (point)) + (indent-to indent) + ;; If initial point was within line's indentation, + ;; position after the indentation. + ;; Else stay at same point in text. + (when (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos)))) + shift-amt))) + +(defun ess-r-indent-exp () + (save-excursion + (when current-prefix-arg + (ess-climb-to-top-level)) + (let* ((bounds (ess-continuations-bounds)) + (end (cadr bounds)) + (beg (if current-prefix-arg + (car bounds) + (forward-line) + (point)))) + (indent-region beg end)))) + +(defun ess-indent-call (&optional start) + (save-excursion + (when (ess-escape-calls) + (setq start (or start (point))) + (skip-chars-forward "^[(") + (forward-char) + (ess-up-list) + (indent-region start (point))))) + +(defun ess-offset (offset) + (setq offset + (symbol-value (intern (concat "ess-offset-" (symbol-name offset))))) + (when (and (not (eq offset nil)) + (listp offset) + (or (numberp (cadr offset)) + (eq (cadr offset) t) + (error "Malformed offset"))) + (setq offset (cadr offset))) + (cond ((numberp offset) + offset) + ((null offset) + 0) + (t + ess-indent-offset))) + +(defun ess-offset-type (offset) + (setq offset + (symbol-value (intern (concat "ess-offset-" (symbol-name offset))))) + (if (listp offset) + (car offset) + offset)) + +(defun ess-overridden-blocks () + (append (when (memq 'fun-decl ess-align-blocks) + (list (car ess-prefixed-block-patterns))) + (when (memq 'control-flow ess-align-blocks) + (append (cdr ess-prefixed-block-patterns) + '("}?[ \t]*else"))))) + +(defun ess-calculate-indent () + "Return appropriate indentation for current line as ESS code. +In usual case returns an integer: the column to indent to. +Returns nil if line starts inside a string, t if in a comment." + (save-excursion + (beginning-of-line) + (let* ((indent-point (point)) + (state (syntax-ppss)) + (containing-sexp (cadr state)) + (prev-containing-sexp (car (last (butlast (nth 9 state)))))) + (back-to-indentation) + (cond + ;; Strings + ((ess-inside-string-p) + (current-indentation)) + ;; Comments + ((ess-calculate-indent--comments)) + ;; Indentation of commas + ((looking-at ",") + (ess-calculate-indent--comma)) + ;; Arguments: Closing + ((ess-call-closing-p) + (ess-calculate-indent--call-closing-delim)) + ;; Block: Contents (easy cases) + ((ess-calculate-indent--block-relatively)) + ;; Block: Prefixed block + ((ess-calculate-indent--prefixed-block-curly)) + ;; Continuations + ((ess-calculate-indent--continued)) + ;; Block: Overridden contents + ((ess-calculate-indent--aligned-block)) + ;; Block: Opening + ((ess-block-opening-p) + (ess-calculate-indent--block-opening)) + ;; Bare line + ((and (null containing-sexp) + (not (ess-unbraced-block-p))) + 0) + ;; Block: Closing + ((ess-block-closing-p) + (ess-calculate-indent--block 0)) + ;; Block: Contents + ((ess-block-p) + (ess-calculate-indent--block)) + ;; Arguments: Nested calls override + ((ess-calculate-indent--nested-calls)) + ;; Arguments: Contents + (t + (ess-calculate-indent--args)))))) + +(defun ess-calculate-indent--comments () + (when ess-indent-with-fancy-comments + (cond + ;; ### or #! + ((or (looking-at "###") + (and (looking-at "#!") + (= 1 (line-number-at-pos)))) + 0) + ;; Single # comment + ((looking-at "#[^#']") + comment-column)))) + +(defun ess-calculate-indent--comma () + (when (ess-inside-call-p) + (let ((indent (save-excursion + (ess-calculate-indent--args))) + (unindent (progn (skip-chars-forward " \t") + ;; return number of skipped chars + (skip-chars-forward ", \t")))) + (- indent unindent)))) + +(defun ess-calculate-indent--call-closing-delim () + (cond ((save-excursion + (ess-skip-blanks-backward t) + (eq (char-before) ?,)) + (ess-calculate-indent--args nil)) + ((save-excursion + (and (ess-ahead-operator-p) + (or (ess-ahead-definition-op-p) + (not ess-align-continuations-in-calls)))) + (ess-calculate-indent--continued)) + (t + (ess-calculate-indent--args 0)))) + +(defun ess-calculate-indent--block-opening () + (cond + ;; Block is an argument in a function call + ((when containing-sexp + (ess-at-containing-sexp + (ess-behind-call-opening-p "[[(]"))) + (ess-calculate-indent--block 0)) + ;; Top-level block + ((null containing-sexp) 0) + ;; Block is embedded in another block + ((ess-at-containing-sexp + (+ (current-indentation) + (ess-offset 'block)))))) + +(defun ess-calculate-indent--aligned-block () + ;; Check for `else' opening + (if (and (memq 'control-flow ess-align-blocks) + (looking-at "else\\b") + (ess-climb-if-else)) + (progn + (when (looking-at "else\\b") + (ess-skip-curly-backward)) + (current-column)) + ;; Check for braced and unbraced blocks + (ess-save-excursion-when-nil + (let ((offset (if (looking-at "[{})]") + 0 (ess-offset 'block)))) + (when (and (cond + ;; Unbraced blocks + ((ess-climb-block-prefix)) + ;; Braced blocks + (containing-sexp + (when (ess-at-containing-sexp + (looking-at "{")) + (ess-escape-prefixed-block)))) + (cl-some #'looking-at + (ess-overridden-blocks))) + (+ (current-column) offset)))))) + +(defun ess-calculate-indent--block-relatively () + (ess-save-excursion-when-nil + (let ((offset (if (looking-at "[})]") 0 (ess-offset 'block))) + (start-line (line-number-at-pos))) + (cond + ;; Braceless block continuations: only when not in a call + ((ess-save-excursion-when-nil + (and (not (looking-at "{")) + (ess-goto-char (ess-unbraced-block-p)) + (not (looking-at "function\\b")) + (or (null containing-sexp) + (ess-at-containing-sexp + (not (looking-at "(")))))) + (ess-maybe-climb-broken-else 'same-line) + (ess-skip-curly-backward) + (+ (current-column) + (ess-offset 'block))) + ;; Don't indent relatively other continuations + ((ess-ahead-continuation-p) + nil) + ;; If a block already contains an indented line, we can indent + ;; relatively from that first line + ((ess-save-excursion-when-nil + (and (not (looking-at "}")) + containing-sexp + (goto-char containing-sexp) + (looking-at "{") + (progn + (forward-line) + (back-to-indentation) + (/= (line-number-at-pos) start-line)) + (not (looking-at "[ \t]*\\(#\\|$\\)")) + (save-excursion + (or (ess-jump-expression) + (ess-jump-continuations)) + (< (line-number-at-pos) start-line)))) + (current-column)) + ;; If a block is not part of a call, we can indent relatively + ;; from the opening {. First check that enclosing { is first + ;; thing on line + ((and containing-sexp + (not (ess-unbraced-block-p)) + (goto-char containing-sexp) + (ess-block-opening-p) + (equal (point) (save-excursion + (back-to-indentation) + (point)))) + (+ (current-column) offset)))))) + +(defun ess-arg-block-p () + (unless (or (null containing-sexp) + ;; Unbraced blocks in a { block are not arg blocks + (and (ess-unbraced-block-p) + (ess-at-containing-sexp + (looking-at "{")))) + (cond + ;; Unbraced body + ((ess-at-indent-point + (and (ess-unbraced-block-p) + (goto-char containing-sexp) + (ess-behind-call-opening-p "[[(]"))) + 'body) + ;; Indentation of opening brace as argument + ((ess-at-containing-sexp + (ess-behind-call-opening-p "[[(]")) + 'opening) + ;; Indentation of body or closing brace as argument + ((ess-at-containing-sexp + (and (or (looking-at "{") + (ess-behind-block-paren-p)) + prev-containing-sexp + (goto-char prev-containing-sexp) + (ess-behind-call-opening-p "[[(]"))) + 'body)))) + +(defun ess-calculate-indent--block (&optional offset) + (let ((arg-block (ess-arg-block-p))) + (cond (arg-block + (ess-calculate-indent--arg-block offset arg-block)) + (t + ;; Block is not part of an arguments list. Climb over any + ;; block opening (function declaration, etc) to indent from + ;; starting indentation. + (or (ess-climb-block-prefix) + (and (goto-char containing-sexp) + (ess-climb-block-prefix))) + (+ (current-indentation) (or offset (ess-offset 'block))))))) + +(defun ess-calculate-indent--arg-block (offset arg-block) + (let* ((block-type (cond ((or (ess-at-containing-sexp + (and (eq arg-block 'body) + (ess-climb-block-prefix "function"))) + (ess-at-indent-point + (and (eq arg-block 'opening) + (ess-backward-sexp 2) + (looking-at "function\\b")))) + 'fun-decl) + ((ess-at-indent-point + (ess-unbraced-block-p)) + 'unbraced) + ((ess-at-containing-sexp + (not (ess-ahead-attached-name-p))) + 'bare-block) + (t))) + (call-pos (if (and (not (eq block-type 'unbraced)) + (not (eq arg-block 'opening))) + (goto-char prev-containing-sexp) + (prog1 containing-sexp + (goto-char indent-point))))) + (ess-calculate-indent--args offset (ess-offset-type 'block) + call-pos indent-point block-type))) + +;; This function is currently the speed bottleneck of the indentation +;; engine. This is due to the need to call (ess-maximum-args-indent) +;; to check if some previous arguments have been pushed off from their +;; natural indentation: we need to check the whole call. This is very +;; inefficient especially when indenting a region containing a large +;; function call (e.g. some dplyr's data cleaning code). Should be +;; solved by implementing a cache as in (syntax-ppss), though it's +;; probably not worth the work. +(defun ess-calculate-indent--args (&optional offset type call-pos to block) + (let* ((call-pos (or call-pos containing-sexp)) + (max-col (prog1 (unless (eq type 'prev-line) + (ess-maximum-args-indent call-pos to)) + (goto-char call-pos))) + (override (and ess-align-arguments-in-calls + (save-excursion + (ess-climb-object) + (cl-some #'looking-at + ess-align-arguments-in-calls)))) + (type-sym (cond (block 'block) + ((looking-at "[[:blank:]]*[([][[:blank:]]*\\($\\|#\\)") + 'arguments-newline) + (t 'arguments))) + (type (or type + (and override 'open-delim) + (ess-offset-type type-sym))) + (offset (or offset + (and (not block) (eq type 'open-delim) 0) + (ess-offset type-sym))) + (indent + (cond + ;; Indent from opening delimiter + ((eq type 'open-delim) + (ess-calculate-indent--args-open-delim)) + ;; Indent from attached name + ((eq type 'prev-call) + (ess-calculate-indent--args-prev-call block)) + ;; Indent from previous line indentation + ((eq type 'prev-line) + (let ((out (ess-calculate-indent--args-prev-line type block offset))) + (setq offset (pop out)) + (pop out))) + (t + (error "Malformed offset"))))) + (if max-col + (ess-adjust-argument-indent indent offset max-col block) + (+ indent offset)))) + +(defun ess-calculate-indent--args-open-delim () + (forward-char) + (current-column)) + +(defun ess-calculate-indent--args-prev-call (block) + ;; Handle brackets chains such as ][ (cf data.table) + (ess-climb-chained-delims) + ;; Handle call chains + (if ess-indent-from-chain-start + (while (and (ess-backward-sexp) + (when (looking-back "[[(][ \t,]*" (line-beginning-position)) + (goto-char (match-beginning 0))))) + (ess-backward-sexp)) + (when ess-indent-from-lhs + (ess-climb-lhs)) + (if (and nil + (eq block 'fun-decl) + (not (eq arg-block 'opening)) + (not (eq (ess-offset-type type-sym) 'open-delim))) + (+ (ess-offset 'block) (current-column)) + (current-column))) + +(defun ess-calculate-indent--args-prev-line (type block offset) + (ess-at-indent-point + (cond + ;; Closing delimiters are actually not indented at + ;; prev-line, but at opening-line + ((looking-at "[]})]") + (ess-up-list -1) + (when (looking-at "{") + (ess-climb-block-prefix)) + (list offset (current-indentation))) + ;; Function blocks need special treatment + ((and (eq type 'prev-line) + (eq block 'fun-decl)) + (goto-char containing-sexp) + (ess-climb-block-prefix) + (list offset (current-indentation))) + ;; Regular case + (t + ;; Find next non-empty line to indent from + (while (and (= (forward-line -1) 0) + (looking-at "[ \t]*\\($\\|#\\)"))) + (goto-char (ess-code-end-position)) + ;; Climb relevant structures + (unless (ess-climb-block-prefix) + (when (eq (char-before) ?,) + (forward-char -1)) + (ess-climb-expression) + (ess-climb-continuations)) + ;; The following ensures that only the first line + ;; counts. Otherwise consecutive statements would get + ;; increasingly more indented. + (let ((offset (if (and block + containing-sexp + (not (eq block 'unbraced)) + (save-excursion + (/= (line-number-at-pos) + (progn (goto-char containing-sexp) + (line-number-at-pos))))) + 0 + offset))) + (list offset (current-indentation))))))) + +;; Indentation of arguments needs to keep track of how previous +;; arguments are indented. If one of those has a smaller indentation, +;; we push off the current line from its natural indentation. For +;; block arguments, we still need to push off this column so we ignore +;; it. +(defun ess-adjust-argument-indent (base offset max-col push) + (if push + (+ (min base max-col) offset) + (min (+ base offset) max-col))) + +;; When previous arguments are shifted to the left (can happen in +;; several situations) compared to their natural indentation, the +;; following lines should not get indented past them. The following +;; function checks the minimum indentation for all arguments of the +;; current function call or bracket indexing. +(defun ess-maximum-args-indent (&optional from to) + (let* ((to (or to (point))) + (to-line (line-number-at-pos to)) + (from-line (progn + (goto-char (1+ (or from containing-sexp))) + (line-number-at-pos))) + max-col) + (while (< (line-number-at-pos) to-line) + (forward-line) + (back-to-indentation) + ;; Ignore the line with the function call, the line to be + ;; indented, and empty lines. + (unless (or (>= (line-number-at-pos) to-line) + (looking-at "[ \t]*\\($\\|#\\)")) + (let ((indent (cond + ;; First line: minimum indent is right after ( + ((= (line-number-at-pos) from-line) + (save-excursion + (goto-char (1+ containing-sexp)) + (current-column))) + ;; Handle lines starting with a comma + ((save-excursion + (looking-at ",")) + (+ (current-indentation) 2)) + (t + (current-indentation))))) + (setq max-col (min indent (or max-col indent)))))) + max-col)) + +;; Move to leftmost side of a call (either the first letter of its +;; name or its closing delim) +(defun ess-move-to-leftmost-side () + (when (or (looking-at "[({]") + (ess-behind-call-p)) + (ess-save-excursion-when-nil + (let ((start-col (current-column))) + (skip-chars-forward "^{[(") + (forward-char) + (ess-up-list) + (forward-char -1) + (< (current-column) start-col))))) + +(defun ess-max-col () + (let ((max-col (point))) + (save-excursion + (while (< (point) indent-point) + (unless (and ess-indent-with-fancy-comments + (looking-at "### ")) + (setq max-col (min max-col (current-column)))) + (forward-line) + (back-to-indentation))) + max-col)) + +(defun ess-calculate-indent--prefixed-block-curly () + (when (looking-at "{") + (ess-save-excursion-when-nil + (let ((block-type (ess-climb-block-prefix))) + (cond ((ess-save-excursion-when-nil + (and (memq 'fun-decl-opening ess-indent-from-lhs) + (string= block-type "function") + (ess-climb-operator) + (ess-behind-assignment-op-p) + (ess-climb-expression))) + (current-column)) + ((= (save-excursion + (back-to-indentation) + (point)) + (point)) + (ess-calculate-indent--continued))))))) + +(defun ess-calculate-indent--continued () + "If a continuation line, return an indent of this line, otherwise nil." + (save-excursion + (let* ((cascade (eq (ess-offset-type 'continued) 'cascade)) + (climbed (ess-climb-continuations cascade)) + max-col) + (when climbed + (cond + ;; Overridden calls + ((and ess-align-continuations-in-calls + (not (eq climbed 'def-op)) + containing-sexp + (save-excursion + (goto-char containing-sexp) + (looking-at "[[(]"))) + (setq max-col (ess-max-col)) + (ess-move-to-leftmost-side) + (+ (min (current-column) max-col) + (if (eq climbed 'def-op) + (ess-offset 'continued) + 0))) + ;; Regular case + (t + (let ((first-indent (or (eq climbed 'def-op) + (save-excursion + (when (ess-ahead-closing-p) + (ess-climb-expression)) + (not (ess-climb-continuations cascade)))))) + ;; Record all indentation levels between indent-point and + ;; the line we climbed. Some lines may have been pushed off + ;; their natural indentation. These become the new + ;; reference. + (setq max-col (ess-max-col)) + ;; Indenting continuations from the front of closing + ;; delimiters looks better + (when + (ess-ahead-closing-p) + (backward-char)) + (+ (min (current-column) max-col) + (cond + ((eq (ess-offset-type 'continued) 'cascade) + (ess-offset 'continued)) + (first-indent + (ess-offset 'continued)) + (t + 0)))))))))) + +(defun ess-calculate-indent--nested-calls () + (when ess-align-nested-calls + (let ((calls (mapconcat #'identity ess-align-nested-calls "\\|")) + match) + (save-excursion + (and containing-sexp + (looking-at (concat "\\(" calls "\\)(")) + (setq match (match-string 1)) + (goto-char containing-sexp) + (looking-at "(") + (ess-backward-sexp) + (looking-at (concat match "(")) + (current-column)))))) + + +;;;*;;; Call filling engine + +;; Unroll arguments to a single line until closing marker is found. +(defun ess-fill--unroll-lines (bounds &optional jump-cont) + (let* ((last-pos (point-min)) + (containing-sexp (ess-containing-sexp-position))) + (goto-char (car bounds)) + (goto-char (ess-code-end-position)) + (while (and (/= (point) last-pos) + (< (line-end-position) + (cadr bounds))) + (setq last-pos (point)) + ;; Check whether we ended up in a sub call. In this case, jump + ;; over it, otherwise, join lines. + (let ((contained-sexp (ess-containing-sexp-position))) + (cond ((and contained-sexp + containing-sexp + (not (= containing-sexp contained-sexp))) + (goto-char (1+ contained-sexp)) + (ess-up-list)) + ;; Jump over continued statements + ((and jump-cont (ess-ahead-operator-p 'strict)) + (ess-climb-token) + (ess-jump-continuations)) + ;; Jump over comments + ((looking-at "#") + (forward-line) + (funcall indent-line-function)) + (t + (join-line 1)))) + (goto-char (ess-code-end-position))) + (goto-char (car bounds)))) + +(defvar ess-fill--orig-pos nil + "Original position of cursor.") + +(defvar ess-fill--orig-state nil + "Backup of original code to cycle back to original state.") + +(defvar ess-fill--second-state nil + "Backup of code produce by very first cycling. +If this is equal to orig-state, no need to cycle back to original +state.") + +(defvar ess-fill--style-level nil + "Filling style used in last cycle.") + +(defun ess-fill--substring (bounds) + (buffer-substring (car bounds) (marker-position (cadr bounds)))) + +;; Detect repeated commands +(defun ess-fill-style (type bounds) + (let ((max-level + ;; This part will be simpler once we have the style alist + (cond ((eq type 'calls) + ;; No third style either when ess-offset-arguments is + ;; set to 'open-delim, or when ess-fill-calls-newlines + ;; is nil and no numeric prefix is given + (if (and (not (eq (ess-offset-type 'arguments) + 'open-delim)) + (or ess-fill-calls-newlines + (numberp current-prefix-arg))) + 3 + 2)) + ((eq type 'continuations) + 2)))) + (if (not (memq last-command '(fill-paragraph-or-region + fill-paragraph))) + (progn + ;; Record original state on first cycling + (setq ess-fill--orig-state (ess-fill--substring bounds)) + (setq ess-fill--orig-pos (point)) + (setq ess-fill--second-state nil) + (setq ess-fill--style-level 1)) + ;; Also record state on second cycling + (when (and (= ess-fill--style-level 1) + (null ess-fill--second-state)) + (setq ess-fill--second-state (ess-fill--substring bounds))) + (cond ((>= ess-fill--style-level max-level) + (let ((same-last-and-orig (string= (ess-fill--substring bounds) + ess-fill--orig-state)) + (same-2nd-and-orig (string= ess-fill--orig-state + ess-fill--second-state))) + ;; Avoid cycling to the same state twice + (cond ((and same-last-and-orig + same-2nd-and-orig) + (setq ess-fill--style-level 2)) + ((or same-last-and-orig + same-2nd-and-orig) + (setq ess-fill--style-level 1)) + (t + (setq ess-fill--style-level 0))))) + (ess-fill--style-level + (setq ess-fill--style-level (1+ ess-fill--style-level)))))) + ess-fill--style-level) + +(let (_) + ;; FIXME: Transform these dynamic bindings to a state object + (defvar ess--infinite) + (defvar ess--prefix-break) + (defvar ess--start-pos) + (defvar ess--last-pos) + (defvar ess--last-newline) + + (declare-function ess-fill-args--roll-lines "ess-r-mode") + + (defun ess-fill-args (&optional style) + (let ((ess--start-pos (point-min)) + (bounds (ess-args-bounds 'marker)) + ;; Set undo boundaries manually + (undo-inhibit-record-point t) + ess--last-pos ess--last-newline ess--prefix-break + ess--infinite) + (when (not bounds) + (error "Could not find function bounds")) + (setq style (or style (ess-fill-style 'calls bounds))) + (if (= style 0) + (progn + (delete-region (car bounds) (marker-position (cadr bounds))) + (insert ess-fill--orig-state) + ;; Restore the point manually. (save-excursion) wouldn't + ;; work here because we delete the text rather than just + ;; modifying it. + (goto-char ess-fill--orig-pos) + (message "Back to original formatting")) + (when ess-blink-refilling + (ess-blink-region (nth 2 bounds) + (1+ (marker-position (cadr bounds))))) + (undo-boundary) + (save-excursion + (ess-fill--unroll-lines bounds t) + (cond + ;; Some styles start with first argument on a newline + ((and (memq style '(2 4)) + ess-fill-calls-newlines + (not (looking-at "[ \t]*#"))) + (newline-and-indent)) + ;; Third level, start a newline after N arguments + ((and (= style 3) + (not (looking-at "[ \t]*#"))) + (let ((i (if (numberp current-prefix-arg) + current-prefix-arg + 1))) + (while (and (> i 0) + (ess-jump-arg) + (ess-jump-char ",")) + (setq i (1- i)))) + (newline-and-indent))) + (ess-fill-args--roll-lines style) + ;; Reindent surrounding context + (ess-indent-call (car bounds))) + ;; Signal marker for garbage collection + (set-marker (cadr bounds) nil) + (undo-boundary)))) + + (defun ess-fill-args--roll-lines (style) + (while (and (not (looking-at "[])]")) + (/= (point) (or ess--last-pos 1)) + (not ess--infinite)) + (setq ess--prefix-break nil) + ;; Record ess--start-pos as future breaking point to avoid breaking + ;; at `=' sign + (while (looking-at "[ \t]*[\n#]") + (forward-line) + (back-to-indentation)) + (setq ess--start-pos (point)) + (while (and (< (current-column) fill-column) + (not (looking-at "[])]")) + (/= (point) (or ess--last-pos 1)) + ;; Break after one pass if prefix is active + (not ess--prefix-break)) + (when (memq style '(2 3)) + (setq ess--prefix-break t)) + (ess-jump-token ",") + (setq ess--last-pos (point)) + ;; Jump expression and any continuations. Reindent all lines + ;; that were jumped over + (let ((cur-line (line-number-at-pos)) + end-line) + (cond ((ess-jump-arg) + (setq ess--last-newline nil)) + ((ess-token-after= ",") + (setq ess--last-newline nil) + (setq ess--last-pos (1- (point))))) + (save-excursion + (when (< cur-line (line-number-at-pos)) + (setq end-line (line-number-at-pos)) + (ess-goto-line (1+ cur-line)) + (while (and (<= (line-number-at-pos) end-line) + (/= (point) (point-max))) + (funcall indent-line-function) + (forward-line)))))) + (when (or (>= (current-column) fill-column) + ess--prefix-break + ;; Ensures closing delim on a newline + (and (= style 4) + (looking-at "[ \t]*[])]") + (setq ess--last-pos (point)))) + (if (and ess--last-pos (/= ess--last-pos ess--start-pos)) + (goto-char ess--last-pos) + (ess-jump-char ",")) + (cond ((looking-at "[ \t]*[#\n]") + (forward-line) + (funcall indent-line-function) + (setq ess--last-newline nil)) + ;; With levels 2 and 3, closing delim goes on a newline + ((looking-at "[ \t]*[])]") + (when (and (memq style '(2 3 4)) + ess-fill-calls-newlines + (not ess--last-newline)) + (newline-and-indent) + ;; Prevent indenting infinitely + (setq ess--last-newline t))) + ((not ess--last-newline) + (newline-and-indent) + (setq ess--last-newline t)) + (t + (setq ess--infinite t))))))) + +(defun ess-fill-continuations (&optional style) + (let ((bounds (ess-continuations-bounds 'marker)) + (undo-inhibit-record-point t) + (last-pos (point-min)) + last-newline infinite) + (when (not bounds) + (error "Could not find statements bounds")) + (setq style (or style (ess-fill-style 'continuations bounds))) + (if (= style 0) + (progn + (delete-region (car bounds) (marker-position (cadr bounds))) + (insert ess-fill--orig-state) + (goto-char ess-fill--orig-pos) + (message "Back to original formatting")) + (when ess-blink-refilling + (ess-blink-region (car bounds) (marker-position (cadr bounds)))) + (undo-boundary) + (save-excursion + (ess-fill--unroll-lines bounds) + (while (and (< (point) (cadr bounds)) + (/= (point) (or last-pos 1)) + (not infinite)) + (setq last-pos (point)) + (when (and (ess-jump-expression) + (indent-according-to-mode) + (not (> (current-column) fill-column))) + (setq last-newline nil)) + (ess-jump-operator) + (if (or (and (> (current-column) fill-column) + (goto-char last-pos)) + (= style 2)) + (progn + (ess-jump-operator) + (unless (= (point) (cadr bounds)) + (when last-newline + (setq infinite t)) + (newline-and-indent) + (setq last-newline t))) + (setq last-newline nil))) + (ess-indent-call (car bounds))) + (set-marker (cadr bounds) nil) + (undo-boundary)))) + + + +;;;*;;; Inferior R mode + +(defvar inferior-ess-r-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\M-\r" #'ess-dirs) + (define-key map (kbd "C-c C-=") #'ess-cycle-assign) + (define-key map (kbd "C-c C-.") 'ess-rutils-map) + map) + "Keymap for `inferior-ess-r-mode'.") + +;; TOTHINK: Prevent string delimiting characters from messing up output in the +;; inferior buffer +(defvar inferior-ess-r-mode-syntax-table + (let ((table (copy-syntax-table ess-r-mode-syntax-table))) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?\' "." table) + table) + "Syntax table for `inferior-ess-r-mode'.") + +(define-derived-mode inferior-ess-r-mode inferior-ess-mode "iESS" + "Major mode for interacting with inferior R processes." + :group 'ess-proc + (ess-setq-vars-local ess-r-customize-alist) + (setq-local ess-font-lock-keywords 'inferior-ess-r-font-lock-keywords) + (setq-local font-lock-syntactic-face-function #'ess-r-font-lock-syntactic-face-function) + (setq-local comint-process-echoes (eql ess-eval-visibly t)) + (setq-local comint-prompt-regexp inferior-S-prompt) + (setq-local syntax-propertize-function ess-r--syntax-propertize-function) + (setq comint-input-sender 'inferior-ess-r-input-sender) + (remove-hook 'completion-at-point-functions #'ess-filename-completion 'local) ;; should be first + (add-hook 'completion-at-point-functions #'ess-r-object-completion nil 'local) + (add-hook 'completion-at-point-functions #'ess-filename-completion nil 'local) + (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local) + (add-hook 'project-find-functions #'ess-r-project nil 'local) + ;; eldoc + (ess--setup-eldoc #'ess-r-eldoc-function) + ;; auto-complete + (ess--setup-auto-complete ess-r-ac-sources t) + ;; company + (ess--setup-company ess-r-company-backends t) + (setq comint-get-old-input #'inferior-ess-get-old-input) + (add-hook 'comint-input-filter-functions #'ess-search-path-tracker nil 'local)) + + + +;;;*;;; R Help mode + +(defvar ess-r-help-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map (make-composed-keymap button-buffer-map + ess-help-mode-map)) + (define-key map "s<" #'beginning-of-buffer) + (define-key map "s>" #'end-of-buffer) + (define-key map "sa" #'ess-skip-to-help-section) + (define-key map "sd" #'ess-skip-to-help-section) + (define-key map "sD" #'ess-skip-to-help-section) + (define-key map "st" #'ess-skip-to-help-section) + (define-key map "se" #'ess-skip-to-help-section) + (define-key map "sn" #'ess-skip-to-help-section) + (define-key map "sr" #'ess-skip-to-help-section) + (define-key map "ss" #'ess-skip-to-help-section) + (define-key map "su" #'ess-skip-to-help-section) + (define-key map "sv" #'ess-skip-to-help-section) + map) + "Keymap for `ess-r-help-mode'.") + +(cl-defmethod ess--help-major-mode (&context (ess-dialect "R")) + (ess-r-help-mode)) + +(define-derived-mode ess-r-help-mode ess-help-mode "R Help" + "Major mode for help buffers." + :group 'ess-help + (setq ess-dialect "R" + ess-help-sec-regex ess-help-r-sec-regex + ess-help-sec-keys-alist ess-help-r-sec-keys-alist ; TODO: Still necessary? + inferior-ess-help-command inferior-ess-r-help-command) + (ess-r-help--add-links)) + +(define-button-type 'ess-r-help--link + 'follow-link t + 'action (lambda (_) (ess-r-help--button-action))) + +(defun ess-r-help--button-action () + "Display help for button at point." + (let ((text (get-text-property (point) 'ess-r-help--link-text))) + (ess-display-help-on-object text))) + +(defun ess-r-help--add-links () + "Add links to the help buffer." + (let ((links (when (ess-process-live-p) + (ess-get-words-from-vector + (ess-r--format-call + ".ess.helpLinks('%s' %s)\n" + ess-r-help--local-object + (ess-r-arg "package" ess-r-help--local-package t))))) + (inhibit-read-only t)) + (save-excursion + ;; Search for fancy quotes only. If users have + ;; options(useFancyQuotes) set to something other than TRUE this + ;; probably won't work. If it's FALSE, R outputs ascii ', but + ;; searching through the whole buffer takes too long. + (while (re-search-forward "‘\\([^[:space:]]+?\\)’" nil t) + (let* ((text (match-string 1)) + (text-stripped (if (string-match-p ".*()\\'" text) + (substring text nil (- (length text) 2)) + text))) + (when (member text-stripped links) + (delete-region (match-beginning 0) (match-end 0)) + (insert-text-button text + 'ess-r-help--link-text text-stripped + 'type 'ess-r-help--link + 'help-echo (format "mouse-2, RET: Help on %s" text)))))))) + +(cl-defmethod ess--display-vignettes-override (all &context (ess-dialect "R")) + "Display R vignettes in ess-help-like buffer.. +With (prefix) ALL non-nil, use `vignette(*, all=TRUE)`, i.e., +from all installed packages, which can be very slow." + (inferior-ess-r-force) + (let* ((vslist (with-current-buffer + (ess-command + (format ".ess_vignettes(%s)\n" (if all "TRUE" ""))) + (goto-char (point-min)) + (when (re-search-forward "(list" nil t) + (goto-char (match-beginning 0)) + (ignore-errors (eval (read (current-buffer)) t))))) + (proc-name ess-current-process-name) + (alist ess-local-customize-alist) + (remote (file-remote-p default-directory)) + (buff (get-buffer-create (format "*[%s]vignettes*" ess-dialect))) + (inhibit-modification-hooks t) + (inhibit-read-only t)) + (with-current-buffer buff + (setq buffer-read-only nil) + (delete-region (point-min) (point-max)) + (ess-setq-vars-local (eval alist t)) + (setq ess-local-process-name proc-name) + (ess--help-major-mode) + (setq ess-help-sec-regex "^\\w+:$" + ess-help-type 'vignettes) + (set-buffer-modified-p 'nil) + (goto-char (point-min)) + (dolist (el vslist) + (let ((pack (car el))) + (insert (format "\n\n%s:\n\n" (propertize pack 'face 'underline))) + (dolist (el2 (cdr el)) + (let ((path (if remote + (with-no-warnings + ;; Have to wrap this in with-no-warnings because + ;; otherwise the byte compiler complains about + ;; calling tramp-make-tramp-file-name with an + ;; incorrect number of arguments on Both 26+ and 25 emacses. + (if (>= emacs-major-version 26) + (with-parsed-tramp-file-name default-directory nil + (tramp-make-tramp-file-name method user domain host port (nth 1 el2))) + (with-parsed-tramp-file-name default-directory nil + (tramp-make-tramp-file-name method user host (nth 1 el2))))) + (nth 1 el2)))) + (insert-text-button "doc" + 'mouse-face 'highlight + 'action (if remote + #'ess--action-open-in-emacs + #'ess--action-R-open-vignette) + 'follow-link t + 'vignette (file-name-sans-extension (nth 2 el2)) + 'package pack + 'help-echo (concat path "/doc/" (nth 2 el2))) + (insert " ") + (insert-text-button "source" + 'mouse-face 'highlight + 'action #'ess--action-open-in-emacs + 'follow-link t + 'help-echo (concat path "/doc/" (nth 3 el2))) + (insert " ") + (insert-text-button "R" + 'mouse-face 'highlight + 'action #'ess--action-open-in-emacs + 'follow-link t + 'help-echo (concat path "/doc/" (nth 4 el2))) + (insert (format "\t%s\n" (nth 0 el2))))))) + (goto-char (point-min)) + (insert (propertize "\t\t**** Vignettes ****\n" 'face 'bold-italic)) + (unless (eobp) (delete-char 1)) + (setq buffer-read-only t)) + (ess-display-help buff))) + + + +;; Support for listing R packages + +(define-obsolete-variable-alias 'ess-rutils-buf 'ess-r-package-menu-buf "ESS 19.04") +(define-obsolete-variable-alias 'ess-rutils-mode-map 'ess-r-package-menu-mode-map "ESS 19.04") +(define-obsolete-function-alias 'ess-rutils-mode #'ess-r-package-menu-mode "ESS 19.04") + +(defvar ess-rutils-map + (let ((map (define-prefix-command 'ess-rutils-map))) + (define-key map "l" #'ess-r-package-list-local-packages) + (define-key map "r" #'ess-r-package-list-available-packages) + (define-key map "u" #'ess-r-package-update-packages) + (define-key map "a" #'ess-display-help-apropos) + (define-key map "m" #'ess-rutils-rm-all) + (define-key map "o" #'ess-rdired) + (define-key map "w" #'ess-rutils-load-workspace) + (define-key map "s" #'ess-rutils-save-workspace) + (define-key map "d" #'ess-change-directory) + (define-key map "H" #'ess-rutils-html-docs) + map)) + +(easy-menu-define ess-rutils-mode-menu inferior-ess-mode-menu + "Package management." + '("Package management" + ["List local packages" ess-r-package-list-local-packages t] + ["List available packages" ess-r-package-list-available-packages t] + ["Update packages" ess-r-package-update-packages t])) + +(easy-menu-add-item inferior-ess-mode-menu nil ess-rutils-mode-menu "Utils") +(easy-menu-add-item ess-mode-menu nil ess-rutils-mode-menu "Process") + +(defvar ess-r-package-menu-buf "*R packages*" + "Name of buffer to display R packages in.") + +(defvar ess-r-package-menu-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "l" #'ess-r-package-load) + (define-key map "i" #'ess-r-package-mark-install) + (define-key map "x" #'ess-r-package-execute-marks) + (define-key map "u" #'ess-r-package-unmark) + map) + "Keymap for `ess-rutils-mode'.") + +(define-derived-mode ess-r-package-menu-mode tabulated-list-mode "R utils" + "Major mode for `ess-rutils-local-pkgs' and `ess-rutils-repos-pkgs'." + :group 'ess-R + (setq ess-dialect "R") + (setq mode-name (concat "R packages: " ess-local-process-name)) + (setq tabulated-list-padding 2) + (setq tabulated-list-format + `[("Name" 10 t) + ("Description" 50 nil) + ("Version" 5 t)]) + (tabulated-list-init-header)) + +(define-obsolete-function-alias 'ess-rutils-local-pkgs #'ess-r-package-list-local-packages "ESS 19.04") + +(defun ess-r-package-list-local-packages () + "List all packages in all libraries." + (interactive) + (ess-r-package--list-packages (concat ".ess.rutils.ops <- options(width = 10000);" + "print(installed.packages(fields=c(\"Title\"))[, c(\"Title\", \"Version\")]);" + "options(.ess.rutils.ops); rm(.ess.rutils.ops);" + "\n"))) + +(defun ess-r-package--list-packages (cmd) + "Use CMD to list packages." + (let ((process ess-local-process-name) + des-col-beginning des-col-end entries) + (with-current-buffer (ess-command cmd (get-buffer-create " *ess-rutils-pkgs*")) + (goto-char (point-min)) + (delete-region (point) (1+ (line-end-position))) + ;; Now we have a buffer with package name, description, and + ;; version. description and version are surrounded by quotes, + ;; description is separated by whitespace. + (re-search-forward "\\>[[:space:]]+") + (setq des-col-beginning (current-column)) + (goto-char (line-end-position)) + ;; Unless someone has a quote character in their package version, + ;; two quotes back will be the end of the package description. + (dotimes (_ 2) (search-backward "\"")) + (re-search-backward "[[:space:]]*") + (setq des-col-end (current-column)) + (beginning-of-line) + (while (not (eobp)) + (beginning-of-line) + (let* ((name (string-trim (buffer-substring + (point) + (progn (forward-char (1- des-col-beginning)) + (point))))) + (description (string-trim (buffer-substring + (progn (forward-char 1) + (point)) + (progn (forward-char (- des-col-end des-col-beginning)) + (point))))) + (version (buffer-substring + (progn (end-of-line) + (search-backward "\"") + (search-backward "\"") + (forward-char 1) + (point)) + (progn (search-forward "\"") + (backward-char 1) + (point))))) + (push + (list name + `[(,name + help-echo "mouse-2, RET: help on this package" + action ess-rutils-help-on-package) + ,description + ,version]) + entries) + (forward-line))) + (pop-to-buffer ess-rutils-buf) + (setq ess-local-process-name process) + (setq tabulated-list-entries entries) + (ess-r-package-menu-mode) + (tabulated-list-print)))) + +(define-obsolete-function-alias 'ess-rutils-loadpkg #'ess-r-package-load "ESS 19.04") +(defun ess-r-package-load () + "Load package from a library." + (interactive) + (ess-execute (concat "library('" (tabulated-list-get-id) + "', character.only = TRUE)") + 'buffer)) + +(defun ess-rutils-help-on-package (&optional _button) + "Display help on the package at point." + (interactive) + ;; FIXME: Should go to a help buffer + (ess-execute (concat "help(" (tabulated-list-get-id) ", package = '" + (tabulated-list-get-id)"')") + 'buffer)) + +(define-obsolete-function-alias 'ess-rutils-repos-pkgs #'ess-r-package-list-available-packages "ESS 19.04") +(defun ess-r-package-list-available-packages () + "List available packages. +Use the repositories as listed by getOptions(\"repos\") in the +current R session." + (interactive) + (ess-r-package--list-packages + "{ + .ess.rutils.ops <- options(width = 10000) + print(available.packages(fields=c(\"Title\"))[, c(\"Title\", \"Version\")]) + options(.ess.rutils.ops); rm(.ess.rutils.ops) + }\n")) + +(define-obsolete-function-alias 'ess-rutils-mark-install #'ess-r-package-mark-install "ESS 19.04") +(defun ess-r-package-mark-install () + "Mark the current package for installing." + (interactive) + (tabulated-list-put-tag "i" t)) + +(define-obsolete-function-alias 'ess-rutils-unmark #'ess-r-package-unmark "ESS 19.04") +(defun ess-r-package-unmark () + "Unmark the packages." + (interactive) + (tabulated-list-put-tag " " t)) + +(define-obsolete-function-alias 'ess-rutils-execute-marks #'ess-r-package-execute-marks "ESS 19.04") +(defun ess-r-package-execute-marks () + "Perform all marked actions." + (interactive) + ;; Install + (save-excursion + (let ((cmd "install.packages(c(") + pkgs) + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at-p "i") + (setq pkgs (concat "\"" (tabulated-list-get-id) "\", " pkgs)) + (tabulated-list-put-tag " ")) + (forward-line)) + (if pkgs + (progn (setq pkgs (substring pkgs 0 (- (length pkgs) 2))) + (setq cmd (concat cmd pkgs "))")) + (ess-execute cmd 'buffer)) + (message "No packages marked for install"))))) + +(define-obsolete-function-alias 'ess-rutils-update-pkgs #'ess-r-package-update-packages "ESS 19.04") +(defun ess-r-package-update-packages (lib repo) + "Update packages in library LIB and repo REPO. +This also uses checkBuilt=TRUE to rebuild installed packages if +needed." + (interactive + (list (ess-completing-read "Library to update: " (ess-get-words-from-vector + "as.character(.libPaths())\n")) + (ess-completing-read "Repo: " (ess-get-words-from-vector + "as.character(getOption(\"repos\"))\n")))) + (ess-execute (format "update.packages(lib.loc='%s', repos='%s', ask=FALSE, checkBuilt=TRUE)" lib repo) 'buffer)) + +(define-obsolete-function-alias 'ess-rutils-apropos #'ess-display-help-apropos "ESS 19.04") + +;; Miscellaneous helper functions + +(defun ess-rutils-rm-all () + "Remove all R objects." + (interactive) + (when (y-or-n-p "Delete all objects? ") + (ess-execute "rm(list=ls())" 'buffer))) + +(defun ess-rutils-load-workspace (file) + "Load workspace FILE into R." + (interactive "fFile with workspace to load: ") + (ess-execute (concat "load('" file "')") 'buffer)) +(define-obsolete-function-alias 'ess-rutils-load-wkspc #'ess-rutils-load-workspace "ESS 19.04") + +(defun ess-rutils-save-workspace (file) + "Save FILE workspace as file.RData." + (interactive "FSave workspace to file (no extension): ") + (ess-execute (concat "save.image('" file ".RData')") 'buffer)) +(define-obsolete-function-alias 'ess-rutils-save-wkspc #'ess-rutils-save-workspace "ESS 19.04") + +(defun ess-rutils-quit () + "Kill the ess-rutils buffer and return to the iESS buffer." + (interactive) + (ess-switch-to-end-of-ESS) + (kill-buffer ess-rutils-buf)) + +(defun ess-rutils-html-docs (&optional remote) + "Use `browse-url' to navigate R html documentation. +Documentation is produced by a modified help.start(), that +returns the URL produced by GNU R's http server. If called with a +prefix, the modified help.start() is called with update=TRUE. The +optional REMOTE argument should be a string with a valid URL for +the 'R_HOME' directory on a remote server (defaults to NULL)." + (interactive) + (let* ((update (if current-prefix-arg "update=TRUE" "update=FALSE")) + (remote (if (or (and remote (not (string= "" remote)))) + (concat "remote=" remote) "remote=NULL")) + (proc ess-local-process-name) + (rhtml (format ".ess_help_start(%s, %s)\n" update remote))) + (with-temp-buffer + (ess-command rhtml (current-buffer) nil nil nil (get-process proc)) + (let* ((begurl (search-backward "http://")) + (endurl (search-forward "index.html")) + (url (buffer-substring-no-properties begurl endurl))) + (browse-url url))))) + +(defun ess-rutils-rsitesearch (string) + "Search the R archives for STRING, and show results using `browse-url'. +If called with a prefix, options are offered (with completion) +for matches per page, sections of the archives to search, +displaying results in long or short formats, and sorting by any +given field. Options should be separated by value of +`crm-default-separator'." + (interactive "sSearch string: ") + (let ((site "https://search.r-project.org/cgi-bin/namazu.cgi?query=") + (okstring (replace-regexp-in-string " +" "+" string))) + (browse-url + (if current-prefix-arg + (let ((mpp (concat + "&max=" + (completing-read + "Matches per page: " + '(("20" 1) ("30" 2) ("40" 3) ("50" 4) ("100" 5))))) + (format (concat + "&result=" + (completing-read + "Format: " '(("normal" 1) ("short" 2)) + nil t "normal" nil "normal"))) + (sortby (concat + "&sort=" + (completing-read + "Sort by: " + '(("score" 1) ("date:late" 2) ("date:early" 3) + ("field:subject:ascending" 4) + ("field:subject:descending" 5) + ("field:from:ascending" 6) ("field:from:descending" 7) + ("field:size:ascending" 8) ("field:size:descending" 9)) + nil t "score" nil "score"))) + (restrict (concat + "&idxname=" + (mapconcat + #'identity + (completing-read-multiple + "Limit search to: " + '(("Rhelp02a" 1) ("functions" 2) + ("docs" 3) ("Rhelp01" 4)) + nil t "Rhelp02a,functions,docs" nil + "Rhelp02a,functions,docs") + "&idxname=")))) + (concat site okstring mpp format sortby restrict)) + (concat site okstring "&max=20&result=normal&sort=score" + "&idxname=Rhelp02a&idxname=functions&idxname=docs"))))) + +(defun ess-rutils-help-search (string) + "Search for STRING using help.search()." + (interactive "sString to search for? ") + (let ((proc ess-local-process-name)) + (pop-to-buffer "foobar") + (ess-command (concat "help.search('" string "')\n") + (current-buffer) nil nil nil (get-process proc)))) + +(make-obsolete 'ess-rutils-rhtml-fn "overwrite .ess_help_start instead." "ESS 18.10") + + +;; Create functions that can be called for running different versions +;; of R. +;; FIXME: Should be set in ess-custom +(setq ess-rterm-version-paths + (ess-flatten-list + (delete-dups + (if (not ess-directory-containing-R) + (if (getenv "ProgramW6432") + (let ((P-1 (getenv "ProgramFiles(x86)")) + (P-2 (getenv "ProgramW6432"))) + (nconc + ;; Always 32 on 64 bit OS, nil on 32 bit OS + (ess-find-rterm (concat P-1 "/R/") "bin/Rterm.exe") + (ess-find-rterm (concat P-1 "/R/") "bin/i386/Rterm.exe") + + ;; Keep this both for symmetry and because it can happen: + (ess-find-rterm (concat P-1 "/R/") "bin/x64/Rterm.exe") + + ;; Always 64 on 64 bit OS, nil on 32 bit OS + (ess-find-rterm (concat P-2 "/R/") "bin/Rterm.exe") + (ess-find-rterm (concat P-2 "/R/") "bin/i386/Rterm.exe") + (ess-find-rterm (concat P-2 "/R/") "bin/x64/Rterm.exe"))) + (let ((PF (getenv "ProgramFiles"))) + (nconc + ;; Always 32 on 32 bit OS, depends on 32 or 64 process on 64 bit OS + (ess-find-rterm (concat PF "/R/") "bin/Rterm.exe") + (ess-find-rterm (concat PF "/R/") "bin/i386/Rterm.exe") + (ess-find-rterm (concat PF "/R/") "bin/x64/Rterm.exe")))) + (let ((PF ess-directory-containing-R)) + (nconc + (ess-find-rterm (concat PF "/R/") "bin/Rterm.exe") + (ess-find-rterm (concat PF "/R/") "bin/i386/Rterm.exe") + (ess-find-rterm (concat PF "/R/") "bin/x64/Rterm.exe"))))))) +(ess-r-define-runners) + +;;*;; Provide and auto-loads + +;;;###autoload +(add-to-list 'auto-mode-alist '("/Makevars\\(\\.win\\)?\\'" . makefile-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("DESCRIPTION\\'" . conf-colon-mode)) + +(provide 'ess-r-mode) + +;;; ess-r-mode.el ends here diff --git a/elpa/ess-20230419.1527/ess-r-package.el b/elpa/ess-20230419.1527/ess-r-package.el new file mode 100644 index 00000000..3513cc46 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-package.el @@ -0,0 +1,598 @@ +;;; ess-r-package.el --- Package development mode for R. -*- lexical-binding: t; -*- + +;; Copyright (C) 2011-2022 Free Software Foundation, Inc. +;; Author: Lionel Henry, Vitalie Spinu +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; see appropriate documentation section of ESS user manual + +;;; Code: +(require 'cl-lib) +(require 'ess-inf) + +(eval-when-compile + (require 'subr-x) + (require 'tramp)) +;; Silence the byte compiler, OK because this file is only loaded by +;; ess-r-mode and has no autoloads. +(defvar ess-r-customize-alist) +(declare-function ess-r-project "ess-r-mode") +(declare-function inferior-ess-r-force "ess-r-mode") +(declare-function ess-r-get-evaluation-env "ess-r-mode") +(declare-function ess-r-set-evaluation-env "ess-r-mode") +(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) +;; This can be drop after dropping support for Emacs 25: +(declare-function tramp-file-name-localname "tramp" (cl-x)) + +(defvar ess-r-prompt-for-attached-pkgs-only nil + "If nil provide completion for all installed R packages. +If non-nil, only look for attached packages.") + +(define-obsolete-variable-alias 'ess-r-package-auto-set-evaluation-env 'ess-r-package-auto-enable-namespaced-evaluation "18.04") +(define-obsolete-variable-alias 'ess-r-package-auto-set-evaluation-env 'ess-r-package-auto-enable-namespaced-evaluation "18.04") +(defcustom ess-r-package-auto-enable-namespaced-evaluation t + "If non-nil, evaluation env is set to package env automatically. +See also `ess-r-set-evaluation-env' and `ess-r-evaluation-env'." + :group 'ess-r-package + :type 'boolean) + +(defvar-local ess-r-package--info-cache nil + "Current package info cache. +See `ess-r-package-info' for its structure.") + +(defcustom ess-r-package-library-paths nil + "Default path to find user packages. +Can be either a string specifying a directory or a list of +directories. This variable is also consulted by +`xref-find-definitions' in R buffers. See `ess-r-xref-backend'." + :group 'ess-r-package-library-paths + :type `(choice string (repeat string))) + +(defvar ess-r-package-root-file "DESCRIPTION" + "Presence of this file indicates the project's root.") + +(defvar ess-r-package-dirs + '(("R" . 1) + ("r" . 1) + ("tests" . 1) + ("testthat" . 2) + ("inst" . 1) + ("include" . 2) + ("src" . 1)) + "Alist of directories names and their depth in R package hierarchy. +This list is used to figure out whether the current file belongs +to an R package. If the file specified in `ess-r-package-root-file' +\(DESCRIPTION by default) is found at the presumed root directory +of the package, the current directory is considered to be part of +a R package.") + +(defvar ess-r-package-source-roots + '("R" "src" "tests" "inst/include") + "List of sub-directories within R package where source files are located. +All children of these directories are also considered source +containing directories. Use `ess-r-package-source-dirs' to get +all source dirs recursively within the current package.") + + +;;;*;;; Package Detection + +(defun ess-r-package-project (&optional dir) + "Return the current package as an Emacs project instance. +A project instance is a cons cell of the project type as symbol +and the project path as string. If DIR is provided, the package +is searched from that directory instead of `default-directory'." + (let ((pkg-info (ess-r-package-info dir))) + (when (car pkg-info) + (cons 'ess-r-package (plist-get pkg-info :root))))) + + +;; FIXME: remove when emacs 27 is dropped +(unless (eval-when-compile + (get 'project-roots 'byte-obsolete-info)) + (cl-defmethod project-roots ((project (head ess-r-package))) + "Return the project root for ESS R packages" + (list (cdr project)))) + +(cl-defmethod project-root ((project (head ess-r-package))) + "Return the project root for ESS R packages" + (cdr project)) + +(defun ess-r-package-name (&optional dir) + "Return the name of the current package as a string." + (plist-get (ess-r-package-info dir) :name)) + +(defun ess-r-package-info (&optional dir) + "Get the description of the R project in directory DIR. +Return an plist with the keys :name and :root. When not in a +package return \\='(nil). This value is cached buffer-locally for +efficiency reasons." + (if (and (null dir) (car ess-r-package--info-cache)) + ess-r-package--info-cache + (let* ((path (ess-r-package--find-package-path (or dir default-directory))) + (name (when path + (ess-r-package--find-package-name path))) + (local (if (and path (file-remote-p path)) + (tramp-file-name-localname (tramp-dissect-file-name path)) + path)) + (info (if name + (list :name name + :root local) + '(nil)))) + ;; If DIR was supplied we cannot cache in the current buffer. + (if dir + info + (setq-local ess-r-package--info-cache info))))) + +(defun ess-r-package--all-source-dirs (dir) + (when (file-directory-p dir) + (cl-loop for f in (directory-files-and-attributes dir t "\\`[^.]") + if (cadr f) + append (cons (car f) (ess-r-package--all-source-dirs (car f)))))) + +(defun ess-r-package-source-dirs () + "Get paths within current R package with source files. +Return nil if not in a package. Search sub-directories listed in +`ess-r-package-source-roots' are searched recursively and +return all physically present directories." + (let ((pkg-root (plist-get (ess-r-package-info) :root))) + (when pkg-root + (let ((files (directory-files-and-attributes pkg-root t "\\`[^.]"))) + (cl-loop for f in files + if (and (cadr f) + (cl-some (lambda (el) (string-match-p (concat "/" el "$") (car f))) + ess-r-package-source-roots)) + append (cons (car f) + (ess-r-package--all-source-dirs (car f)))))))) + +(defun ess-r--select-package-name () + (inferior-ess-r-force) + (let ((pkgs (ess-get-words-from-vector + (format "print(.packages(%s), max = 1e6)\n" + (if ess-r-prompt-for-attached-pkgs-only "FALSE" "TRUE")))) + (current-pkg (ess-r-package-name))) + (let ((env (ess-r-get-evaluation-env))) + (when env + (setq pkgs (append '("*none*") pkgs)) + (when (equal env current-pkg) + (setq current-pkg "*none*")))) + (ess-completing-read "Package" pkgs nil nil nil nil current-pkg))) + +(defun ess-r-package--find-package-path (&optional dir) + "Get the root of R package in directory DIR. +DIR defaults to the current buffer's file name (if non-nil) or +`default-directory'. Root is determined by locating +`ess-r-package-root-file'." + (when-let ((path (cond + (dir) + ((buffer-file-name) + (file-name-directory (buffer-file-name))) + (t + default-directory))) + (pkg-path + (when path + (or + ;; First check current directory + (and (file-exists-p (expand-file-name ess-r-package-root-file path)) + path) + ;; Check for known directories in current path + (let ((current-dir (file-name-nondirectory (directory-file-name path))) + known-pkg-dir known-path presumptive-path) + (while (and path (not presumptive-path)) + (setq current-dir (file-name-nondirectory (directory-file-name path))) + (if (and (setq known-pkg-dir (assoc current-dir ess-r-package-dirs)) + (setq known-path (ess--parent-dir path (cdr known-pkg-dir))) + (file-exists-p (expand-file-name ess-r-package-root-file known-path))) + (setq presumptive-path known-path) + (setq path (ess--parent-dir path 1)))) + presumptive-path))))) + (directory-file-name pkg-path))) + +(defun ess-r-package--find-package-name (path) + (let ((file (expand-file-name ess-r-package-root-file path)) + (case-fold-search t)) + (when (file-exists-p file) + (with-temp-buffer + (insert-file-contents-literally file) + (goto-char (point-min)) + (when (re-search-forward "package: \\(.*\\)" nil t) + (match-string 1)))))) + + +;;;*;;; UI + +(defun ess-r-package-use-dir () + "Set process directory to current package directory." + (interactive) + (let ((pkg-root (plist-get (ess-r-package-info) :root))) + (if pkg-root + (ess-set-working-directory (abbreviate-file-name pkg-root)) + (user-error "Not in a project")))) + + +;;;*;;; Evaluation + +(defun ess-r-package-enable-namespaced-evaluation () + "Enable namespaced evaluation in current buffer. +Namespaced evaluation is enabled if +`ess-r-package-auto-enable-namespaced-evaluation' is non-nil." + (when ess-r-package-auto-enable-namespaced-evaluation + (let ((root (plist-get (ess-r-package-info) :root))) + ;; Check that we are in a file within R/ + (when (and root + default-directory + (> (length default-directory) (1+ (length root))) + (let ((subpath (substring default-directory + (1+ (length root)) + (length default-directory)))) + (string= (directory-file-name subpath) "R"))) + (ess-r-set-evaluation-env (ess-r-package-name)))))) + +(add-hook 'ess-r-mode-hook #'ess-r-package-enable-namespaced-evaluation) + +(defun ess-r-package-eval-linewise (command &optional msg p actions) + "Send COMMAND to R process. +COMMAND is a command string with %s placeholder for the +arguments. MSG is the message displayed in minibuffer with %s +placeholder for the package name. P is the value of universal +argument usually received from the upstream command and indicates +which action in ACTIONS list to perform; if 0 or nil, first +action, if 1 or (4) second if 2 or (16) third etc. ACTIONS is a +list of strings (R arguments), or functions which return R +arguments, or expressions which return R arguments." + (inferior-ess-r-force) + (let ((pkg-info (ess-r-package-info)) + (args (ess-r-command--build-args p actions))) + (unless (car pkg-info) + (user-error "Not in a package")) + (ess-project-save-buffers) + (message msg (plist-get pkg-info :name)) + (display-buffer (ess-get-process-buffer)) + (let ((pkg-path (concat "'" (abbreviate-file-name (plist-get pkg-info :root)) "'"))) + (ess-eval-linewise (format command (concat pkg-path args)))))) + +(defun ess-r-command--build-args (ix &optional actions) + (let* ((n (cond ((null ix) 0) + ((listp ix) (round (log (car ix) 4))) + ((integerp ix) ix) + (t (error "Invalid index")))) + (action (nth n actions)) + (args (cond ((null action) "") + ((stringp action) action) + ((functionp action) (funcall action)) + ((listp action) (eval action t)) + (t (error "Invalid action"))))) + (if (string= "" args) + args + (concat ", " args)))) + + +;;;*;;; Devtools Integration + +(defun ess-r-devtools-load-package (&optional arg) + "Interface for `devtools::load_all()'. +With prefix ARG ask for extra args." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::load_all(%s)\n" "Loading %s" arg + '("" (read-string "Arguments: " "recompile = TRUE")))) + +(defun ess-r-devtools-unload-package () + "Interface to `devtools::unload()'." + (interactive) + (ess-r-package-eval-linewise + "devtools::unload(%s)\n" "Unloading %s")) + +(defun ess-r-devtools-check-package (&optional arg) + "Interface for `devtools::check()'. +With prefix ARG ask for extra args." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::check(%s)\n" "Checking %s" arg + '("" (read-string "Arguments: " "vignettes = FALSE")))) + +(defun ess-r-devtools-check-with-winbuilder (&optional arg) + "Interface for `devtools::check_win_XYZ()'. +With prefix argument, as for arguments to `devtools::check_win_XYZ()' function." + (interactive "P") + (let ((type (completing-read "Release: " '("devel" "release" "oldrelease") nil t))) + (ess-r-package-eval-linewise + (format "devtools:::check_win_%s(%%s)\n" type) + "Checking %s on CRAN's Windows server" arg + '("" (read-string "Arguments: "))))) + +(defvar ess-r-rhub--history nil) +(declare-function ess-r-check-install-package "ess-r-mode.el") +(defun ess-r-rhub-check-package (&optional arg) + "Interface for `rhub::check()'. +With prefix ARG allow for editing of the `rhub::check_for_cran()' arguments." + (interactive "P") + (inferior-ess-r-force) + (ess-r-check-install-package "rhub") + (let* ((platforms (cons "RECOMMENDED" (ess-get-words-from-vector "rhub::platforms()$name\n"))) + (platform (completing-read "Platform: " platforms nil t nil + ess-r-rhub--history (car ess-r-rhub--history))) + (cmd (if (string= "RECOMMENDED" platform) + "rhub::check_for_cran(%s)\n" + (format "rhub::check_for_cran(%%s, platforms = '%s')\n" platform))) + (msg (format "Checking %%s on RHUB (%s)" platform)) + ;; Solaris check is flaky and it seems that solaris check is not run on + ;; CRAN itself with --as-cran options https://github.com/r-hub/rhub/issues/339 + (args (cond ((string-match-p "solaris" platform) + "check_args = c('--no-stop-on-test-error', '--no-vignettes')") + (t "check_args = c('--as-cran', '--no-stop-on-test-error')")))) + (ess-r-package-eval-linewise cmd msg arg + `(,args (read-string "Arguments: " ,(concat args ", valgrind = FALSE")))))) + +(defun ess-r-devtools-build (&optional arg) + "Interface for `devtools::build()'. +With prefix ARG, build with `vignettes = FALSE'." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::build(%s)\n" "Building %s" arg + '("" "vignettes = FALSE"))) + +(defun ess-r-devtools-test-package (&optional arg) + "Interface for `devtools::test()'. +With prefix argument ARG, run tests on current file only." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::test(%s)\n" "Testing %s" arg + '("" ess-r-devtools--cur-file-filter))) + +(defun ess-r-devtools--cur-file-filter () + (let ((file (or (and buffer-file-name + (file-name-nondirectory buffer-file-name)) + (error "Buffer not visiting a file")))) + (format "filter = \"%s\"" + (if (string-match "test-\\([[:alnum:]_-]+\\)\\.[rR]" file) + (match-string-no-properties 1 file) + (file-name-base buffer-file-name))))) + +(defvar ess-r-devtools-revdep-check-cmd + "local({ + pkg_path <- %s + res <- devtools::revdep_check(pkg_path) + + if (file.exists(file.path(pkg_path, 'revdep'))) { + save_path <- file.path(pkg_path, 'revdep') + } else { + save_path <- file.path(pkg_path, '.metadata', 'revdep') + } + devtools::revdep_check_save_summary(res, save_path) + + logs_path <- file.path(save_path, 'logs') + if (!dir.exists(logs_path)) { + dir.create(logs_path) + } + devtools::revdep_check_save_logs(res, logs_path) +}) +") + +(defun ess-project-save-buffers () + "Offer to save modified files in the current project. +Respects `ess-save-silently', which see." + (let ((cur-proj ess-r-package--info-cache)) + (dolist (buf (buffer-list)) + (when-let ((file (buffer-file-name buf)) + (buf-proj (buffer-local-value 'ess-r-package--info-cache buf))) + (when (equal cur-proj buf-proj) + (ess-save-file file)))))) + +(defun ess-r-devtools-document-package (&optional arg) + "Interface for `devtools::document()'. +With prefix ARG ask for extra arguments." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::document(%s)\n" "Documenting %s" arg + '("" (read-string "Arguments: ")))) + +(defun ess-r-devtools-install-package (&optional arg) + "Interface to `devtools::install()'. +By default the installation is \"quick\" with arguments quick = +TRUE, upgrade = FALSE, build = FALSE. On prefix ARG +\\[universal-argument] install with the default +`devtools::install()' arguments." + (interactive "P") + (ess-r-package-eval-linewise + "devtools::install(%s)\n" "Installing %s" arg + '("quick = TRUE, build = FALSE, upgrade = FALSE, keep_source = TRUE" + (read-string "Arguments: " "keep_source = TRUE, force = TRUE")))) + +(defvar ess-r-devtools--install-github-history nil) +(defun ess-r-devtools-install-github (&optional arg) + "Interface to `devtools::install_github()'. +Asks for GitHub repository in the form of user/repo. Force +re-installation when called with a prefix ARG." + (interactive "P") + (let ((command "devtools::install_github(%s%s)") + (repo (format "'%s'" + (read-string "User/Repo: " nil + 'ess-r-devtools--install-github-history + (car ess-r-devtools--install-github-history)))) + (args (if arg + (ess-r-command--build-args 0 '((read-string "Arguments: " "force = TRUE"))) + ""))) + (inferior-ess-r-force) + (unless (derived-mode-p 'inferior-ess-mode) + (display-buffer (ess-get-process-buffer) + '(nil . ((inhibit-same-window . t))))) + (message "Installing %s from github" repo) + (ess-eval-linewise (format command repo args)))) + +(defun ess-r-devtools-create-package () + "Interface to `devtools::create()'. +Default location is determined by the first element of +`ess-r-package-library-paths'." + (interactive) + (let* ((command "devtools::create(\"%s\")") + (default-path (if (stringp ess-r-package-library-paths) + ess-r-package-library-paths + (car ess-r-package-library-paths))) + (path (read-directory-name "Path: " default-path))) + (ess-eval-linewise (format command path)))) + +(defun ess-r-devtools-execute-command (&optional arg) + "Asks with completion for a devtools command. +When called with prefix ARG asks for additional arguments." + (interactive "P") + (inferior-ess-r-force) + (let* ((devtools-funs (ess-get-words-from-vector ".ess_devtools_functions()\n")) + (fun (completing-read "Function: " devtools-funs)) + (command (format "devtools::%s(%%s)\n" fun))) + (ess-r-package-eval-linewise + command (format "Running %s" fun) arg + '("" (read-string "Arguments: "))))) + + +;;;*;;; Minor Mode + +(defcustom ess-r-package-auto-activate t + "If non-nil, `ess-r-package-mode' is turned on within R packages. +If `t' the minor mode auto-activates in R packages. See +`ess-r-package-exclude-modes' if you wish to inhibit +`ess-r-package-mode' in specific buffers." + :group 'ess-r-package + :type 'boolean) + +(defcustom ess-r-package-exclude-modes '(fundamental-mode) + "A list of modes where `ess-r-package' must not be activated. +The check is done with `derived-mode-p'." + :group 'ess-r-package + :type '(repeat symbol) + :package-version '(ess "18.10")) + +(defcustom ess-r-package-enter-hook nil + "Normal hook run on entering `ess-r-package-mode'." + :group 'ess-r-package + :type 'hook) + +(defcustom ess-r-package-exit-hook nil + "Normal hook run on exiting `ess-r-package-mode'." + :group 'ess-r-package + :type 'hook) + +(defcustom ess-r-package-mode-line + ;; FIXME Emacs 25.1: Use `when-let' + '(:eval (let ((pkg-name (ess-r-package-name))) + (when pkg-name + (format " [pkg:%s]" pkg-name)))) + "Mode line for ESS developer. +Set this variable to nil to disable the mode line entirely." + :group 'ess-r-package + :type 'sexp + :risky t) + +(defvar ess-r-package-mode-map + (let ((ess-r-package-mode-map (make-sparse-keymap))) + (define-key ess-r-package-mode-map "\C-c\C-w" 'ess-r-package-dev-map) + ess-r-package-mode-map)) + +(define-minor-mode ess-r-package-mode + "Minor mode for enabling R package development features. + +\\{ess-r-package-mode-map}" + :init-value nil + :keymap ess-r-package-mode-map + :lighter ess-r-package-mode-line + (if ess-r-package-mode + (progn + ;; Forward relevant R settings for interacting with inferior + ;; processes from any mode + (let ((vars '(ess-dialect + ess-setwd-command + ess-getwd-command + ess-quit-function + inferior-ess-reload-function))) + (mapc (lambda (var) + (set (make-local-variable var) + (eval (cdr (assq var ess-r-customize-alist)) t))) + vars)) + (add-hook 'project-find-functions #'ess-r-project nil 'local) + (run-hooks 'ess-r-package-enter-hook)) + (remove-hook 'project-find-functions #'ess-r-project) + (run-hooks 'ess-r-package-exit-hook))) + +(add-hook 'after-change-major-mode-hook #'ess-r-package-auto-activate) + + +;;;*;;; Activation + +(defun ess-r-package-auto-activate () + "Activate developer if current file is part of a package." + (when (and ess-r-package-auto-activate + (or (buffer-name) default-directory) + (not (eq major-mode 'minibuffer-inactive-mode)) + (or + ;; users probably have these in fundamental mode + (member (buffer-name) '("DESCRIPTION" "NAMESPACE")) + (if ess-r-package-exclude-modes + (not (apply #'derived-mode-p ess-r-package-exclude-modes)) + t))) + (when (car (ess-r-package-info)) + (ess-r-package-mode 1)))) + +(defun ess-r-package-re-activate () + "Restart `ess-r-package-mode'. +First, deactivate package mode if active, and activate if in +package mode. Use this function if state of the buffer such as +`default-directory' has changed." + (when ess-r-package-mode + (ess-r-package-mode -1)) + (setq ess-r-package--info-cache nil) + (ess-r-package-auto-activate)) + +(defvar-local ess-r--old-default-dir nil) +(defun ess-r-package-default-directory-tracker (&rest _) + (unless (equal ess-r--old-default-dir default-directory) + (setq ess-r--old-default-dir default-directory) + (ess-r-package-re-activate))) + +(defun ess-r-package-activate-directory-tracker () + (add-hook 'after-change-functions #'ess-r-package-default-directory-tracker t t)) + +(add-hook 'shell-mode-hook #'ess-r-package-activate-directory-tracker t) +(add-hook 'eshell-mode-hook #'ess-r-package-activate-directory-tracker t) +;; (require 'shell) +(advice-add 'shell-resync-dirs :after #'ess-r-package-re-activate) + + +;;;*;;; Deprecated variables and functions +(defun ess-developer (&optional _val) + (error "As of ESS 16.04, `ess-developer' is deprecated. Use `ess-r-set-evaluation-env' instead")) + +(defalias 'ess-toggle-developer #'ess-developer) +(define-obsolete-function-alias 'ess-r-devtools-check-package-buildwin #'ess-r-devtools-check-with-winbuilder "18.04") +(define-obsolete-function-alias 'ess-r-devtools-ask #'ess-r-devtools-execute-command "18.04") + +(make-obsolete-variable 'ess-developer "Please use `ess-developer-select-package' and `ess-r-set-evaluation-env' instead." "16.04") +(make-obsolete-variable 'ess-developer-root-file "Please use `ess-r-package-root-file' instead." "16.04") +(make-obsolete-variable 'ess-developer-packages "Please use `ess-r-package-set-package' and `ess-r-set-evaluation-env' instead." "16.04") +(make-obsolete-variable 'ess-developer-load-on-add-commands "Please use `ess-r-package-set-package' and `ess-r-set-evaluation-env' instead." "16.04") +(make-obsolete-variable 'ess-developer-activate-in-package "Please use `ess-r-package-auto-activate' instead." "16.04") +(make-obsolete-variable 'ess-developer-enter-hook "Please use `ess-r-package-enter-hook' instead." "16.04") +(make-obsolete-variable 'ess-developer-exit-hook "Please use `ess-r-package-exit-hook' instead." "16.04") + + +(provide 'ess-r-package) + +;;; ess-r-package.el ends here diff --git a/elpa/ess-20230419.1527/ess-r-syntax.el b/elpa/ess-20230419.1527/ess-r-syntax.el new file mode 100644 index 00000000..8b11f022 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-syntax.el @@ -0,0 +1,1250 @@ +;;; ess-r-syntax.el --- Utils to work with R code -*- lexical-binding: t; -*- + +;; Copyright (C) 2015-2022 Free Software Foundation, Inc. +;; Author: Lionel Henry +;; Created: 12 Oct 2015 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; API is not yet stable. + +;;; Code: + +(require 'ess-utils) +(require 'regexp-opt) + +(eval-when-compile + (require 'cl-lib)) + + +;;*;; Utils + +;; The three following wrappers return t if successful, nil on error +(defun ess-backward-sexp (&optional N) + (ess-forward-sexp (- (or N 1)))) + +(defun ess-forward-sexp (&optional N) + (or N (setq N 1)) + (condition-case nil + (prog1 t + (goto-char (or (scan-sexps (point) N) + (buffer-end N)))) + (error nil))) + +(defun ess-up-list (&optional N) + (condition-case nil + (let (forward-sexp-function) + (progn (up-list N) t)) + (error nil))) + +(defun ess-backward-up-list (&optional N) + (ess-up-list (- (or N 1)))) + +(defun ess-forward-char (&optional N) + (unless (= (point) (point-max)) + (forward-char (or N 1)) + t)) + +(defun ess-backward-char (&optional N) + (unless (bobp) + (forward-char (- (or N 1))) + t)) + +(defun ess-goto-char (pos) + "Go to POS if it is non-nil. +If POS is nil, return nil. Otherwise return position itself." + (when pos + (goto-char pos))) + +(defun ess-looking-at (regex &optional newlines) + "Like `looking-at' but consumes blanks and comments first." + (save-excursion + (ess-skip-blanks-forward newlines) + (looking-at regex))) + +(defmacro ess-save-excursion-when-nil (&rest body) + (declare (indent 0) + (debug (&rest form))) + `(let ((orig-point (point))) + (cond ((progn ,@body)) + (t (prog1 nil + (goto-char orig-point)))))) + +(defmacro ess-while (test &rest body) + "Like `while' for TEST but return t when BODY gets executed once." + (declare (indent 1) + (debug (&rest form))) + `(let (executed) + (while ,test + (setq executed t) + ,@body) + executed)) + +(defmacro ess-at-indent-point (&rest body) + (declare (indent 0) + (debug (&rest form))) + `(save-excursion + (goto-char indent-point) + (back-to-indentation) + (progn ,@body))) + +(defvar containing-sexp) +(defmacro ess-at-containing-sexp (&rest body) + (declare (indent 0) + (debug (&rest form))) + '(when (not (bound-and-true-p containing-sexp)) + (error "Internal error: containing-sexp is nil or undefined")) + `(save-excursion + (goto-char containing-sexp) + (progn ,@body))) + +(defmacro ess-any (&rest forms) + "Evaluate all arguments and return non-nil if one of the arguments is non-nil. +This is useful to trigger side-effects. FORMS follows the same +syntax as arguments to `cond'." + (declare (indent 0) (debug nil)) + `(let ((forms (list ,@(mapcar (lambda (form) `(progn ,@form)) forms)))) + (cl-some #'identity (mapcar (lambda (e) (eval e t)) forms)))) + +(defun ess-char-syntax (string) + (char-to-string (char-syntax (string-to-char string)))) + + +;;*;; Tokenisation + +(defun ess-token-type (token) (car (nth 0 token))) +(defun ess-token-value (token) (cdr (nth 0 token))) +(defun ess-token-start (token) (car (nth 1 token))) +(defun ess-token-end (token) (cdr (nth 1 token))) + +(defun ess-token-refined-type (token) + (ess-token-type (ess-refine-token token))) + +(defun ess-token-after (&optional token) + "Return next TOKEN. +Cons cell containing the token type and string representation." + (save-excursion + (when token + (goto-char (ess-token-end token))) + (ess-jump-token))) + +(defun ess-token-before (&optional token) + "Return previous TOKEN. +Cons cell containing the token type and string representation." + (save-excursion + (when token + (goto-char (ess-token-start token))) + (ess-climb-token))) + +(defun ess-climb-token (&optional type string) + (ess-save-excursion-when-nil + (ess-escape-comment) + (ess-skip-blanks-backward t) + (let ((token (or (ess-climb-token--back) + (ess-climb-token--back-and-forth) + (progn (forward-char -1) (ess-token-after))))) + (if (or type string) + (when (ess-token= token type string) + token) + token)))) + +(defun ess-token--cons (type value) + (if (eq type 'self) + (cons value nil) + (cons type value))) + +(defun ess-climb-token--back () + (let* ((token-end (point)) + (token-type (if (bobp) + "buffer-start" + (ess-climb-token--operator))) + (token-value (buffer-substring-no-properties (point) token-end))) + (unless (null token-type) + (list (ess-token--cons token-type token-value) + (cons (point) token-end))))) + +(defsubst ess-climb-token--char (&rest chars) + (ess-while (and chars + (eq (char-before) (car chars)) + (ess-backward-char)) + (setq chars (cdr chars)))) + +;; Difficult to use regexps here because we want to match greedily +;; backward +(defun ess-climb-token--operator () + (when (pcase (char-before) + ((or `?+ `?/ `?^ `?~ `?? `?!) + (ess-backward-char)) + (`?= + (prog1 (ess-backward-char) + (or (ess-climb-token--char ?=) + (ess-climb-token--char ?!) + (ess-climb-token--char ?:) + (ess-climb-token--char ?>) + (ess-climb-token--char ?<)))) + ((or `?& `?| `?* `?@ `?$) + (prog1 (ess-backward-char) + (ess-climb-token--char (char-after)))) + (`?< + (ess-backward-char)) + (`?> + (prog1 (ess-backward-char) + (or (ess-climb-token--char ?|) + (ess-climb-token--char ?=) + (ess-climb-token--char ?-) + (and (looking-back "->" (- (point) 2)) + (goto-char (- (point) 2)))))) + (`?- + (prog1 (ess-backward-char) + (ess-climb-token--char ?< ?<))) + (`?: + (prog1 (ess-backward-char) + (ess-climb-token--char ?: ?:)))) + 'self)) + +(defun ess-climb-token--back-and-forth () + (let ((limit (point))) + (when (ess-skip-token-backward) + (save-restriction + (narrow-to-region (point) limit) + (ess-token-after))))) + +(defun ess-skip-token-backward () + (ess-save-excursion-when-nil + (cond + ;; Punctuation + ((memq (char-before) '(?, ?\;)) + (ess-backward-char)) + ;; Quoting delimiters + ((memq (char-syntax (char-before)) '(?\" ?$)) + (ess-backward-sexp)) + ;; Syntaxic delimiters + ((memq (char-syntax (char-before)) '(?\( ?\))) + (prog1 (ess-backward-char) + ;; Also skip double brackets + (ess-save-excursion-when-nil + (when (let ((current-delim (char-after))) + (ess-skip-blanks-backward) + (and (memq (char-before) '(?\[ ?\])) + (eq current-delim (char-before)))) + (ess-backward-char))))) + ;; Identifiers and numbers + ((/= (skip-syntax-backward "w_") 0))))) + +(defun ess-jump-token (&optional type string) + "Consume a token forward. +Return a cons cell containing the token type and the token string +content. Return nil when the end of the buffer is reached." + (ess-save-excursion-when-nil + (ess-skip-blanks-forward t) + (let* ((token-start (point)) + (token-type (or (ess-jump-token--regexps) + (ess-jump-token--literal) + (ess-jump-token--infix-op) + (ess-jump-token--punctuation) + (progn (forward-char) "unknown"))) + (token-value (buffer-substring-no-properties token-start (point)))) + (let ((token (list (ess-token--cons token-type token-value) + (cons token-start (point))))) + (if (or type string) + (when (ess-token= token type string) + token) + token))))) + +(defun ess-jump-token--literal () + (cond + ;; Simply assume anything starting with a digit is a number. May be + ;; too liberal but takes care of fractional numbers, integers such + ;; as 10L, etc. False positives are not valid R code anyway. + ((looking-at "[0-9]") + (ess-forward-sexp) + "number") + ((or (looking-at "\\sw\\|\\s_") + (eq (char-after) ?`)) + (ess-forward-sexp) + "identifier") + ((memq (char-after) '(?\" ?\')) + (ess-forward-sexp) + "string"))) + +(defun ess-jump-token--punctuation () + (or (when (= (point) (point-max)) + "buffer-end") + (pcase (char-after) + (`?\; + (forward-char) + 'self) + (`?, + (forward-char) + ;; Treat blanks after comma as part of an argument + (ess-skip-blanks-forward t) + ",")))) + +(defvar ess-r-prefix-keywords-list + '("if" "for" "while" "function")) + +(defvar ess-r-keywords-list + (append ess-r-prefix-keywords-list '("else"))) + +(defvar ess-r-delimiters-list + '("(" ")" "{" "}" "[" "]" "[[" "]]")) + +(defvar ess-r-operators-list + '("+" "-" "*" "/" "%%" "**" "^" + "&" "&&" "|" "||" "!" "?" "~" + "==" "!=" "<" "<=" ">=" ">" + "=" "<-" "<<-" "->" "->>" + "$" "@" ":" "::" ":::" ":=" + "|>" "=>")) + +(defvar ess-r-keywords-re + (concat (regexp-opt ess-r-keywords-list) "\\_>")) + +(defvar ess-r-delimiters-re + (regexp-opt ess-r-delimiters-list)) + +(defvar ess-r-operators-re + (regexp-opt ess-r-operators-list)) + +(defun ess-jump-token--regexps () + (when (or (looking-at ess-r-keywords-re) + (looking-at ess-r-delimiters-re) + (looking-at ess-r-operators-re)) + (goto-char (match-end 0)) + 'self)) + +(defun ess-jump-token--infix-op () + (or (when (looking-at ess-r-operators-re) + (goto-char (match-end 0)) + 'self) + (when (eq (char-after) ?%) + (ess-forward-sexp) + "%infix%"))) + +(defun ess-refine-token (token) + (let ((refined-type + (pcase (ess-token-type token) + ;; Parameter assignment + (`"=" + (save-excursion + (goto-char (ess-token-start token)) + (let ((containing-sexp (ess-containing-sexp-position))) + (when (and containing-sexp + (ess-at-containing-sexp + (and (ess-token-after= "(") + (ess-token-before= '("identifier" "string")))) + (save-excursion + (and (ess-climb-token) + (ess-token-before= '("," "("))))) + "param-assign")))) + ;; Quoted identifiers + (`"string" + (when (or + ;; Quoted parameter names + (ess-refined-token= (ess-token-after) "param-assign") + ;; Quoted call names + (ess-token-after= "(")) + "identifier")) + ((or `"(" `")") + (or (save-excursion + (if (ess-token-close-delimiter-p token) + (ess-climb-paired-delims nil token) + (goto-char (ess-token-start token))) + (when (ess-token-keyword-p (ess-token-before)) + "prefixed-expr-delimiter")) + ;; Fixme: probably too crude. Better handled in parser + (when (ess-token= token ")") + (save-excursion + (ess-climb-paired-delims ")" token) + (when (ess-token-before= '("identifier" "string" ")" "]" "]]" "}")) + "argslist-delimiter"))))) + ((or `"{" `"}") + (save-excursion + (unless (ess-climb-paired-delims "}" token) + (goto-char (ess-token-start token))) + (when (ess-refined-token= (ess-token-before) "prefixed-expr-delimiter") + "prefixed-expr-delimiter")))))) + (if refined-type + (list (cons refined-type (ess-token-value token)) + (nth 1 token)) + token))) + + +;;;*;;; Token predicates + +(defun ess-token= (token &optional type string) + (when (and (null type) + (null string)) + (error "No condition supplied")) + (let ((type (if (stringp type) (list type) type)) + (string (if (stringp string) (list string) string))) + (and (if type (member (ess-token-type token) type) t) + (if string (member (ess-token-value token) string) t)))) + +(defun ess-refined-token= (token type &optional string) + (ess-token= (ess-refine-token token) type string)) + +(defun ess-token-after= (type &optional string) + (ess-token= (ess-token-after) type string)) + +(defun ess-token-before= (type &optional string) + (ess-token= (ess-token-before) type string)) + +(defun ess-token-open-delimiter-p (token) + (string= (ess-char-syntax (ess-token-type token)) "(")) + +(defun ess-token-close-delimiter-p (token) + (string= (ess-char-syntax (ess-token-type token)) ")")) + +(defun ess-token-delimiter-p (token) + (or (ess-token-open-delimiter-p token) + (ess-token-close-delimiter-p token))) + +(defun ess-token-operator-p (token &optional strict) + (and (or (member (ess-token-type token) ess-r-operators-list) + (string= (ess-token-type token) "%infix%")) + (or (null strict) + (not (ess-refined-token= token "param-assign"))))) + +(defun ess-token-keyword-p (token) + (member (ess-token-type token) ess-r-keywords-list)) + + +;;*;; Point predicates + +(defun ess-inside-call-p (&optional call) + "Return non-nil if point is in a function or indexing call." + (let ((containing-sexp (or (bound-and-true-p containing-sexp) + (ess-containing-sexp-position)))) + (save-excursion + (and (prog1 (ess-goto-char containing-sexp) + (ess-climb-chained-delims)) + (save-excursion + (forward-char) + (ess-up-list)) + (or (ess-behind-call-opening-p "(") + (looking-at "\\[")) + (ess-inside-call-name-p call))))) + +(defun ess-inside-continuation-p () + (unless (or (looking-at ",") + (ess-behind-call-opening-p "[[(]")) + (or (save-excursion + (ess-jump-object) + (and (not (ess-ahead-param-assign-p)) + (ess-behind-operator-p))) + (save-excursion + (ess-climb-object) + (ess-climb-operator) + (and (ess-behind-operator-p) + (not (ess-ahead-param-assign-p))))))) + +(defun ess-inside-call-name-p (&optional call) + (save-excursion + (ess-climb-call-name call))) + +(defun ess-inside-prefixed-block-p (&optional call) + "Return non-nil if point is in a prefixed block. +Prefixed blocks refer to the blocks following function +declarations, control flow statements, etc. + +If CALL is not nil, check if the prefix corresponds to CALL. If +nil, return the prefix." + (save-excursion + (ess-escape-prefixed-block call))) + + +;;*;; Syntactic Travellers and Predicates + +;;;*;;; Blanks, Characters, Comments and Delimiters + +(defun ess-skip-blanks-backward (&optional newlines) + "Skip blanks and newlines backward, taking end-of-line comments into account." + (ess-any ((ess-skip-blanks-backward-1)) + ((when newlines + (ess-while (and (not (bobp)) + (= (point) (line-beginning-position))) + (forward-line -1) + (goto-char (ess-code-end-position)) + (ess-skip-blanks-backward-1)))))) + +(defun ess-skip-blanks-backward-1 () + (and (not (bobp)) + (/= 0 (skip-syntax-backward " ")))) + +(defun ess-skip-blanks-forward (&optional newlines) + "Skip blanks and newlines forward, taking end-of-line comments into account." + (ess-any ((/= 0 (skip-syntax-forward " "))) + ((ess-while (and newlines + (= (point) (ess-code-end-position)) + (when (ess-save-excursion-when-nil + ;; Handles corner cases such as point being on last line + (let ((orig-point (point))) + (forward-line) + (back-to-indentation) + (> (point) orig-point))) + (skip-chars-forward " \t") + t)))))) + +(defun ess-jump-char (char) + (ess-save-excursion-when-nil + (ess-skip-blanks-forward t) + (when (looking-at char) + (goto-char (match-end 0))))) + +(defun ess-escape-comment () + (when (ess-inside-comment-p) + (prog1 (comment-beginning) + (skip-chars-backward "#+[ \t]*")))) + +(defun ess-ahead-closing-p () + (memq (char-before) '(?\] ?\} ?\)))) + +(defun ess-ahead-boundary-p () + (looking-back "[][ \t\n(){},]" (1- (point)))) + +(defun ess-escape-string () + (and (nth 3 (syntax-ppss)) + (ess-goto-char (nth 8 (syntax-ppss))))) + +(defun ess-climb-paired-delims (&optional type token) + (ess-save-excursion-when-nil + (let ((token (or token (ess-token-before)))) + (goto-char (ess-token-end token)) + (when (if type + (ess-token= token type) + (ess-token-delimiter-p token)) + (and (ess-backward-sexp) + (ess-token-after)))))) + +(defun ess-jump-paired-delims (&optional type token) + (ess-save-excursion-when-nil + (let ((token (or token (ess-token-after)))) + (goto-char (ess-token-start token)) + (when (if type + (ess-token= token type) + (ess-token-delimiter-p token)) + (and (ess-forward-sexp) + (ess-token-before)))))) + + +;;;*;;; Blocks + +(defun ess-block-opening-p () + (save-excursion + (cond + ((looking-at "{")) + ;; Opening parenthesis not attached to a function opens up a + ;; block too. Only pick up those that are last on their line + ((ess-behind-block-paren-p))))) + +(defun ess-block-closing-p () + (save-excursion + (cond + ((looking-at "}")) + ((looking-at ")") + (forward-char) + (backward-sexp) + (not (looking-back + (concat ess-r-name-pattern "[[:blank:]]*") + (line-beginning-position))))))) + +(defun ess-block-p () + (or (save-excursion + (when containing-sexp + (goto-char containing-sexp) + (ess-block-opening-p))) + (ess-unbraced-block-p))) + +;; Parenthesised expressions +(defun ess-behind-block-paren-p () + (and (looking-at "(") + (not (ess-ahead-attached-name-p)))) + +(defun ess-climb-block (&optional ignore-ifelse) + (ess-save-excursion-when-nil + (cond + ((and (not ignore-ifelse) + (ess-climb-if-else 'to-start))) + ((and (eq (char-before) ?\}) + (prog2 + (forward-char -1) + (ess-up-list -1) + (ess-climb-block-prefix))))))) + +(defvar ess-prefixed-block-patterns + (mapcar (lambda (fun) (concat fun "[ \t\n]*(")) + '("function" "if" "for" "while"))) + +(defun ess-behind-prefixed-block-p (&optional call) + (if call + (looking-at (concat call "[ \t]*(")) + (cl-some #'looking-at ess-prefixed-block-patterns))) + +(defun ess-unbraced-block-p (&optional ignore-ifelse) + "This indicates whether point is in front of an unbraced +prefixed block following a control flow statement. Returns +position of the control flow function (if, for, while, etc)." + (save-excursion + (and (ess-backward-sexp) + (or (and (looking-at "else\\b") + (not ignore-ifelse)) + (and (looking-at "(") + (ess-backward-sexp) + (cl-some #'looking-at ess-prefixed-block-patterns) + (if ignore-ifelse + (not (looking-at "if\\b")) + t))) + (point)))) + +(defun ess-climb-block-prefix (&optional call ignore-ifelse) + "Climb the prefix of a prefixed block. +Prefixed blocks refer to the blocks following function +declarations, control flow statements, etc. + +Should be called either in front of a naked block or in front +of the curly brackets of a braced block. + +If CALL not nil, check if the prefix corresponds to CALL. If nil, +return the prefix." + (ess-save-excursion-when-nil + (or (and (not ignore-ifelse) + (prog1 (and (ess-climb-if-else-call) + (or (null call) + (looking-at call))) + (when (ess-token-after= "else") + (ess-climb-token "}")))) + (let ((pos (ess-unbraced-block-p ignore-ifelse))) + (and (ess-goto-char pos) + (if call + (looking-at call) + (cond ((looking-at "function") + "function") + ((looking-at "for") + "for") + ((looking-at "if") + "if") + ((looking-at "else") + "else")))))))) + +(defun ess-escape-prefixed-block (&optional call) + "Climb outside of a prefixed block." + (let ((containing-sexp (or (bound-and-true-p containing-sexp) + (ess-containing-sexp-position)))) + (or (ess-save-excursion-when-nil + (and (ess-goto-char containing-sexp) + (looking-at "{") + (ess-climb-block-prefix call))) + (ess-escape-unbraced-block call)))) + +(defun ess-escape-unbraced-block (&optional call) + (ess-save-excursion-when-nil + (while (and (not (ess-unbraced-block-p)) + (or (ess-escape-continuations) + (ess-escape-call)))) + (ess-climb-block-prefix call))) + +(defun ess-jump-block () + (cond + ;; if-else blocks + ((ess-jump-if-else)) + ;; Prefixed blocks such as `function() {}' + ((ess-behind-prefixed-block-p) + (ess-jump-prefixed-block)) + ;; Naked blocks + ((and (or (looking-at "{") + (ess-behind-block-paren-p)) + (ess-forward-sexp))))) + +(defun ess-jump-prefixed-block (&optional call) + (ess-save-excursion-when-nil + (when (ess-behind-prefixed-block-p call) + (ess-forward-sexp 2) + (ess-skip-blanks-forward t) + (if (looking-at "{") + (ess-forward-sexp) + (prog1 (ess-jump-expression) + (ess-jump-continuations)))))) + + +;;;*;;; Calls + +(defun ess-call-closing-p () + (save-excursion + (when (cond ((looking-at ")") + (ess-up-list -1)) + ((looking-at "]") + (when (ess-up-list -1) + (prog1 t (ess-climb-chained-delims))))) + (ess-ahead-attached-name-p)))) + +(defun ess-behind-call-opening-p (pattern) + (and (looking-at pattern) + (ess-ahead-attached-name-p))) + +;; Should be called just before the opening brace +(defun ess-ahead-attached-name-p () + (save-excursion + (ess-climb-object))) + +(defun ess-ahead-param-assign-p () + "Return non-nil if looking at a function argument. +To be called just before the `=' sign." + (ess-refined-token= (ess-token-before) "param-assign")) + +(defun ess-behind-arg-p () + (save-excursion + (ess-jump-arg))) + +(defun ess-behind-parameter-p () + (save-excursion + (ess-jump-parameter))) + +(defun ess-jump-parameter () + (ess-save-excursion-when-nil + (and (ess-jump-name) + (when (looking-at "[ \t]*=\\([^=]\\)") + (goto-char (match-beginning 1)) + (ess-skip-blanks-forward) + t)))) + +(defun ess-jump-arg () + (ess-save-excursion-when-nil + (ess-skip-blanks-forward t) + (ess-any ((ess-jump-parameter)) + ((ess-jump-expression)) + ((ess-jump-continuations))))) + +(defun ess-arg-bounds () + "Should be called in front of the argument." + (save-excursion + (let ((beg (point))) + (and (ess-jump-arg) + (list beg (point)))))) + +(defun ess-climb-call (&optional call) + "Climb functions (e.g. ggplot) and parenthesised expressions." + (or (ess-while (ess-save-excursion-when-nil + (ess-climb-name) + (and (ess-climb-chained-delims ?\]) + ;; (ess-climb-expression) + (if (eq (char-before) ?\)) + (ess-climb-call) + (ess-climb-name)) + ))) + (ess-save-excursion-when-nil + (when (and (memq (char-before) '(?\] ?\) ?\})) + (ess-backward-sexp)) + (if call + (and (ess-climb-name) + (looking-at call))) + (prog1 t + (ess-climb-name)))))) + +(defun ess-climb-call-name (&optional call) + (ess-save-excursion-when-nil + (ess-jump-name) + (ess-skip-blanks-forward) + (and (ess-behind-call-opening-p "[[(]") + (ess-climb-name) + (or (null call) + (looking-at call))))) + +(defun ess-step-to-first-arg () + (let ((containing-sexp (ess-containing-sexp-position))) + (cond ((ess-inside-call-p) + (goto-char containing-sexp) + (forward-char) + t) + ((ess-inside-call-name-p) + (ess-jump-name) + (ess-skip-blanks-forward) + (forward-char) + t)))) + +(defun ess-jump-to-next-arg () + (and (ess-jump-arg) + (prog1 (ess-jump-char ",") + (ess-skip-blanks-forward t)))) + +(defun ess-jump-call () + (ess-save-excursion-when-nil + (or (and (ess-jump-object) + (cond ((eq (char-before) ?\))) + ((looking-at "\\[") + (ess-jump-chained-brackets)) + ((looking-at "(") + (ess-forward-sexp)))) + (and (looking-at "[ \t]*(") + (ess-forward-sexp))))) + +(defun ess-behind-call-p () + (save-excursion + (ess-jump-object) + (ess-skip-blanks-forward) + (looking-at "[[(]"))) + +(defun ess-climb-chained-delims (&optional delim) + "Should be called with point between delims, e.g. `]|['." + (setq delim (if delim + (list delim) + '(?\] ?\)))) + (ess-while (ess-save-excursion-when-nil + (when (memq (char-before) delim) + (ess-backward-sexp))))) + +(defun ess-jump-chained-brackets () + (ess-while (ess-save-excursion-when-nil + (when (eq (char-after) ?\[) + (ess-forward-sexp))))) + +(defun ess-escape-call (&optional call) + (let ((containing-sexp (ess-containing-sexp-position))) + (if (ess-inside-call-p) + (ess-save-excursion-when-nil + (goto-char containing-sexp) + (ess-climb-chained-delims) + (and (ess-climb-name) + (or (null call) + (looking-at call)))) + ;; At top level or inside a block, check if point is on the + ;; function name. + (ess-save-excursion-when-nil + (let ((orig-pos (point))) + (and (ess-jump-name) + (looking-at "[[(]") + (ess-climb-name) + (or (null call) + (looking-at call)) + (/= (point) orig-pos))))))) + +(defun ess-escape-calls () + (ess-while (ess-escape-call))) + +(defun ess-jump-inside-call () + (ess-save-excursion-when-nil + (when (ess-jump-name) + (ess-skip-blanks-forward) + (when (looking-at "(") + (forward-char) + t)))) + +(defun ess-args-bounds (&optional marker) + (let ((containing-sexp (ess-containing-sexp-position))) + (when (ess-inside-call-p) + (save-excursion + (let ((beg (1+ containing-sexp)) + (call-beg (ess-at-containing-sexp + (ess-climb-name) + (point)))) + ;; (ess-up-list) can't find its way when point is on a + ;; backquoted name, so start from `beg'. + (and (goto-char beg) + (ess-up-list) + (prog1 t + (forward-char -1)) + (let ((end (if marker + (point-marker) + (point)))) + (list beg end call-beg)))))))) + +(defun ess-args-alist () + "Return all arguments as an alist with cars set to argument +names and cdrs set to the expressions given as argument. Both +cars and cdrs are returned as strings." + (save-excursion + (when (ess-step-to-first-arg) + (let (args current-arg) + (while (and (setq current-arg (ess-cons-arg)) + (setq args (nconc args (list current-arg))) + (ess-jump-to-next-arg))) + args)))) + +(defun ess-cons-arg () + "Return a cons cell of the current argument with car set to the +parameter name (nil if not specified) and cdr set to the argument +expression." + (save-excursion + (ess-skip-blanks-forward t) + (let ((param (when (ess-behind-parameter-p) + (buffer-substring-no-properties + (point) + (prog2 + (ess-jump-name) + (point) + (ess-jump-char "=") + (ess-skip-blanks-forward))))) + (arg (buffer-substring-no-properties + (point) + (progn + (ess-jump-arg) + (point))))) + (cons param arg)))) + + +;;;*;;; Statements + +(defun ess-behind-operator-p (&optional strict) + (ess-token-operator-p (ess-token-after) strict)) + +(defun ess-ahead-operator-p (&optional strict) + (ess-token-operator-p (ess-token-before) strict)) + +(defun ess-climb-lhs (&optional no-fun-arg climb-line) + (ess-save-excursion-when-nil + (let ((start-line (line-number-at-pos))) + (ess-climb-operator) + (when (and (or climb-line (equal (line-number-at-pos) start-line)) + (ess-behind-definition-op-p no-fun-arg)) + (prog1 t + (ess-climb-expression)))))) + +(defun ess-jump-lhs () + (ess-save-excursion-when-nil + (and (ess-jump-name) + (ess-behind-definition-op-p) + (ess-jump-operator)))) + +(defun ess-climb-operator () + (when (ess-token-operator-p (ess-token-before)) + (prog1 (ess-climb-token) + (ess-skip-blanks-backward)))) + +;; Currently doesn't check that the operator is not binary +(defun ess-climb-unary-operator () + (ess-save-excursion-when-nil + (let ((token (ess-climb-token))) + (member (ess-token-type token) '("+" "-" "!" "?" "~"))))) + +;; Currently returns t if we climbed lines, nil otherwise. +(defun ess-climb-continuations (&optional cascade ignore-ifelse) + (let* ((start-line (line-number-at-pos)) + (state (list :start-line start-line + :last-line start-line + :moved 0 + :last-pos (point) + :prev-point nil + :def-op nil + :expr nil))) + (when (ess-while (and (<= (plist-get state :moved) 1) + (or (ess-save-excursion-when-nil + (and (ess-climb-operator) + (ess-climb-continuations--update-state state cascade 'op) + (ess-climb-expression ignore-ifelse))) + (ess-climb-unary-operator)) + (/= (plist-get state :last-pos) (point))) + (ess-climb-continuations--update-state state cascade nil) + (plist-put state :last-pos (point))) + (when (and (plist-get state :prev-point) + (or (= (plist-get state :moved) 3) + (not (plist-get state :expr)))) + (goto-char (plist-get state :prev-point))) + (if (plist-get state :def-op) + 'def-op + (< (line-number-at-pos) (plist-get state :start-line)))))) + +(defun ess-climb-continuations--update-state (state cascade &optional op) + ;; Climbing multi-line expressions should not count as moving up + (when op + (plist-put state :expr (ess-ahead-closing-p))) + (let ((cur-line (line-number-at-pos))) + (when (and (plist-get state :last-line) + (< cur-line (plist-get state :last-line)) + (or cascade (not (plist-get state :expr)))) + (plist-put state :moved (1+ (plist-get state :moved))) + (plist-put state :last-line cur-line))) + ;; Don't update counter after climbing operator or climbing too high + (when (and (not op) + (<= (plist-get state :moved) 1)) + (plist-put state :prev-point (point))) + (when (and (ess-behind-definition-op-p) + (<= (plist-get state :moved) 1)) + (plist-put state :def-op t)) + t) + +(defun ess-jump-operator () + (when (ess-behind-operator-p) + (ess-jump-token) + (ess-skip-blanks-forward t) + t)) + +(defun ess-jump-continuation () + (and (ess-jump-operator) + (ess-jump-expression))) + +(defun ess-jump-continuations () + (let (last-pos) + (when (ess-while (and (or (null last-pos) + (/= (point) last-pos)) + (setq last-pos (point)) + (ess-jump-continuation))) + ;; In calls, operators can start on newlines + (let ((start-line (line-number-at-pos))) + (when (ess-save-excursion-when-nil + (and (ess-inside-call-p) + (ess-skip-blanks-forward t) + (/= (line-number-at-pos) start-line) + (ess-behind-operator-p))) + (ess-jump-continuations))) + t))) + +(defun ess-ahead-continuation-p (&optional or-parameter) + (or (ess-token-operator-p (ess-token-before) (not or-parameter)) + (save-excursion + (ess-climb-block-prefix)) + (ess-token-after= "else") + (save-excursion + (ess-climb-if-else-call)))) + +(defun ess-token-definition-op-p (token strict) + (and (ess-token= token '("<-" "<<-" ":=" "~" "=")) + (if strict + (not (ess-refined-token= token "param-assign")) + t))) + +(defun ess-behind-definition-op-p (&optional strict) + (ess-token-definition-op-p (ess-token-after) strict)) + +(defun ess-ahead-definition-op-p (&optional strict) + (ess-token-definition-op-p (ess-token-before) strict)) + +(defun ess-behind-assignment-op-p () + (let ((token (ess-token-after))) + (and (ess-token= token '("<-" "=")) + (not (ess-refined-token= token "param-assign"))))) + +(defun ess-escape-continuations () + (ess-any ((unless (ess-ahead-boundary-p) + (ess-climb-expression))) + ((ess-while (ess-climb-continuations))))) + +(defun ess-continuations-bounds (&optional marker) + (save-excursion + (let ((beg (progn + (ess-escape-continuations) + (point)))) + (when beg + (ess-jump-expression) + (ess-jump-continuations) + (let ((end (if marker + (point-marker) + (point)))) + (list beg end)))))) + +(defun ess-climb-to-top-level () + (while (ess-goto-char (ess-containing-sexp-position))) + (ess-escape-continuations)) + + +;;;*;;; Statements: Control Flow + +(defun ess-climb-if-else-call (&optional multi-line) + "Climb if, else, and if else calls." + (ess-save-excursion-when-nil + (cond ((ess-climb-paired-delims ")") + (when (ess-climb-token "if") + ;; Check for `else if' + (prog1 t + (ess-save-excursion-when-nil + (let ((orig-line (line-number-at-pos))) + (and (ess-climb-token "else") + (or multi-line + (eq orig-line (line-number-at-pos))))))))) + ((ess-climb-token "else"))))) + + +(defun ess-climb-if-else-body (&optional from-else) + (cond + ;; Climb braced body + ((ess-save-excursion-when-nil + (and (when (progn (ess-skip-blanks-backward t) + (eq (char-before) ?\})) + (prog1 t (forward-char -1))) + (ess-up-list -1)))) + ;; Climb unbraced body + ((when from-else + (ess-save-excursion-when-nil + (ess-skip-blanks-backward t) + (prog1 (ess-climb-expression 'ignore-ifelse) + (or (ess-climb-continuations nil 'ignore-ifelse) + (ess-climb-block-prefix nil 'ignore-ifelse)))))))) + +(defun ess-climb-if-else (&optional to-start) + "Climb horizontal as well as vertical if-else chains, with or +without curly braces." + ;; Don't climb if we're atop the current chain of if-else + (unless (ess-token-after= "if") + (ess-save-excursion-when-nil + (let ((from-else (ess-token-after= "else"))) + (when (and (ess-climb-if-else-body from-else) + (ess-climb-if-else-call to-start)) + ;; If we start from a final else and climb to another else, we + ;; are in the wrong chain of if-else. In that case, + ;; climb-recurse to the top of the current chain and climb + ;; again to step in the outer chain. + (when (save-excursion (and from-else + (ess-jump-token "else") + (not (ess-jump-token "if")))) + (ess-climb-if-else 'to-start) + (ess-climb-continuations) + (ess-climb-block-prefix nil 'ignore-ifelse) + (ess-climb-if-else-call nil)) + (ess-maybe-climb-broken-else) + (when to-start + (ess-climb-if-else to-start)) + t))))) + +;; Broken else: if \n else +(defun ess-maybe-climb-broken-else (&optional same-line) + (ess-save-excursion-when-nil + ;; Don't record current line if not needed (expensive operation) + (let ((cur-line (when same-line (line-number-at-pos)))) + (and (ess-climb-token "else") + (if same-line + (= cur-line (line-number-at-pos)) + t))))) + +(defun ess-skip-curly-backward () + (re-search-backward "}[ \t]*" (line-beginning-position) t)) + +(defun ess-jump-if-else () + (let (from) + (ess-while (ess-save-excursion-when-nil + (ess-skip-blanks-forward t) + (cond + ((and (not (eq from 'if)) + (ess-jump-if) + (setq from 'if))) + ((looking-at "else") + (ess-forward-sexp) + (or (ess-jump-if) + (progn + (ess-skip-blanks-forward t) + (ess-jump-expression))) + (setq from 'else)) + (t + nil)))))) + +(defun ess-jump-if () + (ess-save-excursion-when-nil + (ess-skip-blanks-forward t) + (and (looking-at "if[ \t\n]*(") + (ess-forward-sexp 2) + (progn + (ess-skip-blanks-forward t) + (ess-jump-expression))))) + + +;;;*;;; Function Declarations + +(defun ess-behind-defun-p () + (or (looking-at "function[ \t]*(") + (ess-behind-enclosed-defun-p))) + +(defun ess-behind-enclosed-defun-p () + (save-excursion + (and (ess-behind-call-p) + (ess-jump-inside-call) + (cl-some (lambda (arg) + (string-match "^function\\b" + (cdr arg))) + (ess-args-alist))))) + + +;;;*;;; Names / Objects / Expressions + +;; Should climb any names, including backquoted ones or those +;; containing `@' or `$'. Difficult to achieve with regexps, but +;; skipping chars is faster anyway. +(defun ess-climb-object () + (ess-save-excursion-when-nil + (let (climbed) + (ess-skip-blanks-backward) + ;; Backquoted names can contain any character + (if (and (memq (char-before) '(?` ?\" ?\')) + (ess-backward-sexp)) + (setq climbed t) + (while (cl-some (apply-partially '/= 0) + `(,(skip-syntax-backward "w_") + ,(skip-chars-backward "\"'"))) + (setq climbed t))) + ;; Recurse if we find an indexing char + (let ((tok (ess-token-before))) + (when (member (ess-token-type tok) '("$" "@" "::" ":::")) + (goto-char (ess-token-start tok)) + (ess-climb-object))) + climbed))) + +;; Todo: split name and object climbing +(defun ess-climb-name () + (ess-climb-object)) + +;; This jumps both object names and atomic objects like strings or +;; numbers. +(defun ess-jump-object () + (cond + ;; Jump over object names + ((ess-jump-name)) + ;; Jump over strings)) + ((ess-save-excursion-when-nil + (skip-chars-forward " \t") + (memq (char-after) '(?\" ?\'))) + (ess-forward-sexp)))) + +(defun ess-jump-name () + (ess-save-excursion-when-nil + (let (climbed) + (skip-chars-forward " \t") + ;; Jump over backquoted names + (cond ((and (eq (char-after) ?`) + (looking-back ess-r-symbol-pattern + (1- (point)))) + (forward-char) + (setq climbed t)) + ((eq (char-after) ?`) + (forward-char) + (when (ess-while (not (memq (char-after) '(?` ?\C-J))) + (forward-char)) + (setq climbed t) + (forward-char))) + ;; Jump over regular names + ((when (/= 0 (skip-syntax-forward "w_")) + ;; Maybe point was inside backticks + (when (eq (char-after) ?`) + (forward-char)) + (setq climbed t)))) + climbed))) + +(defun ess-climb-expression (&optional ignore-ifelse) + (ess-save-excursion-when-nil + (or (ess-climb-block ignore-ifelse) + (ess-climb-call) + (ess-climb-object)))) + +(defun ess-jump-expression () + (or (ess-jump-block) + (ess-jump-call) + (ess-jump-object))) + +(provide 'ess-r-syntax) + +;;; ess-r-syntax.el ends here diff --git a/elpa/ess-20230419.1527/ess-r-xref.el b/elpa/ess-20230419.1527/ess-r-xref.el new file mode 100644 index 00000000..474cf903 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-r-xref.el @@ -0,0 +1,155 @@ +;;; ess-r-xref.el --- An xref backend for R. -*- lexical-binding: t -*- + +;; Copyright (C) 2018-2020 Free Software Foundation, Inc. +;; Author: Aaron Jacobs +;; Created: 21 January 2018 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This file contains an xref backend for `ess-r-mode'. + +;;; Code: + +(require 'xref) +(require 'ess-inf) +(require 'ess-r-package) +(require 'ess-tracebug) +(eval-when-compile + (require 'subr-x)) + +;; Silence the byte compiler. OK because this file is only loaded by ess-r-mode. +(declare-function inferior-ess-r-force "ess-r-mode") + + +(defvar ess-r-xref-pkg-sources nil + "Alist of R package->directory associations. +Each element is a cons cell (PACKAGE . DIRECTORY). This variable +is used as a cache of package->directory associations, but could +be used by the users for a more refined control of package +locations than `ess-r-package-library-paths'.") + +(defun ess-r-xref-backend () + "An `xref-backend-functions' implementation for `ess-r-mode'. +R's xref backend searches for `ess-r-package-library-paths' when +srcrefs point to temporary locations." + 'ess-r) + +(cl-defmethod xref-backend-identifier-at-point ((_backend (eql ess-r))) + (when-let ((sym (ess-symbol-at-point))) + (symbol-name sym))) + +(cl-defmethod xref-backend-definitions ((_backend (eql ess-r)) symbol) + (when-let ((xref (ess-r-xref--xref symbol))) + (list xref))) + +(cl-defmethod xref-backend-apropos ((_backend (eql ess-r))) + ;; Not yet supported. + nil) + +(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql ess-r))) + (inferior-ess-r-force) + (ess-get-words-from-vector--foreground ".ess_all_functions()\n")) + +(defun ess-r-xref--srcref (symbol) + (inferior-ess-r-force) + ;; Look for `symbol' inside the package namespace + (let* ((pkg (ess-r-package-name)) + (pkg (if pkg + (concat "\"" pkg "\"") + "NULL"))) + (with-current-buffer (ess-command (format ".ess_srcref(\"%s\", %s)\n" symbol pkg)) + (goto-char (point-min)) + (if (re-search-forward "Error" nil t) + (progn (message "R srcref lookup failed:\n%s" (buffer-string)) + (sit-for 1) + nil) + (when (re-search-forward "(" nil 'noerror) + (goto-char (match-beginning 0)) + (read (current-buffer))))))) + +(defun ess-r-xref--pkg-srcfile (symbol src-file &optional default-pkg) + "Search the R package containing symbol SYMBOL for file SRC-FILE. +DEFAULT-PKG is the name of the package where presumably SYMBOL is located." + (let* ((pkgs (delq nil + (delete-dups + (or (cons default-pkg + (ess-get-words-from-vector (format ".ess_fn_pkg(\"%s\")\n" symbol))) + (user-error "Can't find package for symbol %s" symbol))))) + (lib-dirs (cond ((stringp ess-r-package-library-paths) + (list ess-r-package-library-paths)) + ((listp ess-r-package-library-paths) + ess-r-package-library-paths) + (t (user-error "Invalid value of `ess-r-package-library-paths'")))) + (loc (or (cl-loop for pkg in pkgs + for dir = (assoc-default pkg ess-r-xref-pkg-sources) + when (and dir (file-exists-p dir)) return (cons pkg dir)) + (cl-some (lambda (dir) + (cl-loop for pkg in pkgs + for path = (expand-file-name pkg dir) + when (file-exists-p path) return (cons pkg path))) + lib-dirs))) + (file (when loc (expand-file-name src-file (cdr loc))))) + (when file + (unless (file-readable-p file) + (error "Can't read %s" file)) + ;; Cache package's source directory. + (unless (assoc (car loc) ess-r-xref-pkg-sources) + (push loc ess-r-xref-pkg-sources)) + file))) + +(defun ess-r-xref--xref (symbol) + "Create an xref for the source file reference of R symbol SYMBOL." + (when-let ((ref (ess-r-xref--srcref symbol))) + (let ((file (nth 0 ref)) + (line (nth 1 ref)) + (col (nth 2 ref))) + (or + ;; 1) Result of ESS evaluation + (let* ((ess-ref (gethash file ess--srcrefs)) + (ess-buff (when ess-ref (ess--dbg-find-buffer (car ess-ref))))) + (when ess-buff + ;; FIXME: this breaks when eval is on larger spans than function + (xref-make symbol (xref-make-buffer-location ess-buff (nth 2 ess-ref))))) + ;; 2) Real file from R proc working directory + (unless (file-name-absolute-p file) + (let ((file (expand-file-name file (ess-get-process-variable 'default-directory)))) + (when (file-readable-p file) + (xref-make symbol (xref-make-file-location file line col))))) + ;; 3) Real file from the R's working directory + (unless (file-name-absolute-p file) + (when-let ((wdir (car (ess-get-words-from-vector ess-getwd-command)))) + (let ((file (expand-file-name file wdir))) + (when (file-readable-p file) + (xref-make symbol (xref-make-file-location file line col)))))) + ;; 4) Real file location from the current directory + (when (file-readable-p file) + (xref-make symbol (xref-make-file-location file line col))) + ;; 5) Temporary sources - truncate and locate in ess-r-package-library-paths + (when (string-match "/\\([^/]+\\)/\\(R/.*\\)$" file) + (when-let ((pkg-file (ess-r-xref--pkg-srcfile + symbol (match-string 2 file) (match-string 1 file)))) + (xref-make symbol (xref-make-file-location + (expand-file-name pkg-file) line col)))))))) + +(provide 'ess-r-xref) + +;;; ess-r-xref.el ends here diff --git a/elpa/ess-20230419.1527/ess-rd.el b/elpa/ess-20230419.1527/ess-rd.el new file mode 100644 index 00000000..05252b23 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-rd.el @@ -0,0 +1,485 @@ +;; ess-rd.el --- Support for editing R documentation (Rd) source -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: KH +;; Created: 25 July 1997 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; + +;;; Code: +(eval-when-compile + (require 'subr-x)) + +(require 'ess-help) +(require 'ess-inf) +;; Silence the byte compiler, see TODO below; can we remove these? +(defvar ess-help-r-sec-regex) +(defvar ess-help-r-sec-keys-alist) +(defvar ess-r-customize-alist) + +(defcustom Rd-mode-hook nil + "Hook to be run when Rd mode is entered." + :type 'hook + :group 'ess-R + :group 'ess-hooks) + +(define-abbrev-table 'Rd-mode-skeleton-abbrev-table + '(("`ag" "\\arguments" nil :system t) + ("`al" "\\alias" nil :system t) + ("`au" "\\author" nil :system t) + ("`bf" "\\bold" nil :system t) + ("`co" "\\code" nil :system t) + ("`de" "\\describe" nil :system t) + ("`dn" "\\description" nil :system t) + ("`dt" "\\details" nil :system t) + ("`em" "\\emph" nil :system t) + ("`en" "\\enumerate" nil :system t) + ("`ex" "\\examples" nil :system t) + ("`fi" "\\file" nil :system t) + ("`fo" "\\format" nil :system t) + ("`it" "\\item" nil :system t) + ("`iz" "\\itemize" nil :system t) + ("`kw" "\\keyword" nil :system t) + ("`li" "\\link" nil :system t) + ("`me" "\\method" nil :system t) + ("`na" "\\name" nil :system t) + ("`no" "\\note" nil :system t) + ("`re" "\\references" nil :system t) + ("`sa" "\\seealso" nil :system t) + ("`se" "\\section" nil :system t) + ("`so" "\\source" nil :system t) + ("`ss" "\\subsection" nil :system t) + ("`sy" "\\synopsis" nil :system t) + ("`ta" "\\tabular" nil :system t) + ("`ti" "\\title" nil :system t) + ("`us" "\\usage" nil :system t) + ("`va" "\\value" nil :system t)) + "Abbrev table for R documentation keywords. +All Rd mode abbrevs start with a grave accent (`)." + :case-fixed t) + +(define-abbrev-table 'Rd-mode-abbrev-table () + "Abbrev table for Rd mode." + :parents (list Rd-mode-skeleton-abbrev-table)) + +(defvar Rd-mode-syntax-table + (let ((tab (copy-syntax-table text-mode-syntax-table))) + (modify-syntax-entry ?\\ "\\" tab) + (modify-syntax-entry ?\{ "(}" tab) + (modify-syntax-entry ?\} "){" tab) + ;; Nice for editing, not for parsing ... + (modify-syntax-entry ?\( "()" tab) + (modify-syntax-entry ?\) ")(" tab) + (modify-syntax-entry ?\[ "(]" tab) + (modify-syntax-entry ?\] ")[" tab) + ;; To get strings right + ;; (modify-syntax-entry ?\' "\"" Rd-mode-syntax-table) + (modify-syntax-entry ?\" "\"" tab) + ;; To make abbrevs starting with a grave accent work ... + (modify-syntax-entry ?\` "w" tab) + ;; Comments + (modify-syntax-entry ?\% "<" tab) + (modify-syntax-entry ?\n ">" tab) + tab) + "Syntax table for `Rd-mode'.") + +(defvar Rd-mode-parse-syntax-table + (let ((tab (copy-syntax-table Rd-mode-syntax-table))) + ;; To make parse-partial-sexps do the thing we want for computing + ;; indentations + (modify-syntax-entry ?\( "_" tab) + (modify-syntax-entry ?\) "_" tab) + (modify-syntax-entry ?\[ "_" tab) + (modify-syntax-entry ?\] "_" tab) + tab) + "Syntax table for parsing Rd mode.") + +(defvar Rd-section-names + '("Rdversion" "arguments" "alias" "author" "concept" "describe" "description" + "details" "docType" "encoding" "enumerate" "examples" "format" + "itemize" "keyword" "name" "note" "preformatted" "references" + "seealso" "section" "source" "subsection" "synopsis" + "tabular" "title" "usage" + "value")) + +(defvar Rd-keywords + '( + ;; the next two lines: only valid in R <= 2.8.1 + ;; commented out on 2011-01-14 for ESS version 5.13: + ;; "Alpha" "Gamma" "alpha" "beta" "epsilon" "lambda" "mu" "pi" "sigma" + ;; "ge" "le" "left" "right" + ;; + "RdOpts" "R" "S3method" "S4method" "Sexpr" "acronym" + "bold" "cite" "code" "command" "cr" "dQuote" "deqn" "dfn" "dontrun" + "dontshow" "donttest" "dots" "email" "emph" "enc" "env" "eqn" "figure" "file" + "href" + "ifelse" "if" + "item" "kbd" "ldots" "linkS4class" "link" "method" + "newcommand" "option" "out" + "pkg" "sQuote" "renewcommand" + "samp" "strong" "tab" "url" "var" "verb" + ;; System macros (from /share/Rd/macros/system.Rd ): + "CRANpkg" "PR" "sspace" "doi" + "LaTeX" + "proglang" + "packageTitle" "packageDescription" "packageAuthor" + "packageMaintainer" "packageDESCRIPTION" "packageIndices" + )) + +(defvar Rd-font-lock-keywords + (list + (cons + (concat "\\\\\\(" + (mapconcat #'identity Rd-section-names "\\|") + "\\>\\)") + 'font-lock-reference-face) ; Rd-bold-face + (cons + (concat "\\\\\\(" + (mapconcat #'identity Rd-keywords "\\|") + "\\>\\)") + 'font-lock-keyword-face) + '("^#\\(ifn?def\\)\\s-+\\(\\sw+\\)" + (1 font-lock-builtin-face) + (2 font-lock-variable-name-face nil t)) + '("^#\\(endif\\)" 1 font-lock-builtin-face)) + "Additional Rd expressions to highlight.") + +(defvar Rd-indent-level 2 + "Indentation of Rd code with respect to containing blocks.") + +(defvar Rd-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\t" #'indent-according-to-mode) + (define-key map "\C-j" #'reindent-then-newline-and-indent) + (define-key map "\C-m" #'reindent-then-newline-and-indent) + (define-key map "\C-c\C-p" #'Rd-preview-help) + (define-key map "\C-c\C-j" #'Rd-mode-insert-item) + (define-key map "\C-c\C-e" #'Rd-mode-insert-skeleton) + (define-key map "\C-c\C-d" #'Rd-mode-insert-data-skeleton) + (define-key map "\C-c\C-f" #'Rd-font) + (define-key map "\C-c\C-s" #'Rd-mode-insert-section) + (define-key map "\C-c\C-n" #'ess-eval-line-visibly-and-step) + (define-key map "\C-c\C-r" #'ess-eval-region) + (define-key map "\C-c\C-c" #'ess-eval-region-or-function-or-paragraph-and-step) + (define-key map "\C-\M-x" #'ess-eval-region-or-function-or-paragraph) + (define-key map "\C-c\C-v" #'ess-display-help-on-object) + (define-key map "\C-c\C-w" #'ess-switch-process) + (define-key map "\C-c\C-y" #'ess-switch-to-ESS) + (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) + map) + "Keymap used in Rd mode.") + +(defvar Rd-mode-menu + (list "Rd" + ["Markup [word]" Rd-font t] + ["Insert Item" Rd-mode-insert-item t] + ["Insert Section" Rd-mode-insert-section t] + ["Insert Skeleton" Rd-mode-insert-skeleton t] + ["Insert Data Skeleton" Rd-mode-insert-data-skeleton t] + "-" + ["Preview" Rd-preview-help t] + "-" + ["Eval Line" ess-eval-line-visibly-and-step t] + ["Eval Region" ess-eval-region t] + ["Switch to ESS Process" ess-switch-to-ESS t] + ["Switch the ESS Process" ess-switch-process t] + ["Switch to end{ESS Pr}" ess-switch-to-end-of-ESS t] + "-" + ["Toggle Abbrev Mode" abbrev-mode t] + ["Toggle Auto-Fill Mode" auto-fill-mode t] + "-" + ["Submit Bug Report" ess-submit-bug-report t] + "-" + ["Describe Rd Mode" describe-mode t]) + "Menu used in Rd mode.") + +(defvar Rd-to-help-command "R CMD Rd2txt" + "Shell command for converting R documentation source to help text.") + +(defvar Rd-font-list + '((?\C-b "\\bold{" "}") + (?\C-c "\\code{" "}") + (?\C-e "\\emph{" "}") + (?\C-l "\\link{" "}") + (?l "\\code{\\link{" "}}") + (?\C-m "\\email{" "}") + (?\C-q "\\eqn{" "}") + (?\C-u "\\url{" "}") + ) + "List of \"fonts\" used by `Rd-font'. +Each entry is a list. The first element is the key to activate +the font. The second element is the string to insert before +point, and the third element is the string to insert after +point.") + + +;;;###autoload +(define-derived-mode Rd-mode text-mode "Rd" + "Major mode for editing R documentation source files. + +Type \\[list-abbrevs] to display the built-in abbrevs for Rd +keywords.To automatically turn on the abbrev(iate) features, add +the following to your Emacs configuration file: + + (add-hook \\='Rd-mode-hook #\\='abbrev-mode)" + (setq ess-language "S" ess-dialect "R") + (require 'ess-r-mode) + (ess-setq-vars-local ess-r-customize-alist) + + (setq-local indent-line-function #'Rd-mode-indent-line) + (setq fill-column 72) + (setq-local comment-start-skip "\\s<+\\s-*") + (setq-local comment-start "% ") + (setq-local comment-end "") + (setq font-lock-defaults + '(Rd-font-lock-keywords nil nil)) + + ;; Here is a workaround for an Emacs bug related to indirect buffers and + ;; spurious lockfiles that rears its ugly head with .Rd files + ;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2013-02/msg01368.html + ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=14328 + (setq-local create-lockfiles nil) + + (easy-menu-define Rd-mode-menu-map Rd-mode-map + "Menu keymap for Rd mode." Rd-mode-menu) + + (turn-on-auto-fill)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode)) + +(defun Rd-describe-major-mode () + "Describe the current major mode." + (declare (obsolete describe-mode "ESS 19.04")) + (describe-function major-mode)) + +(defun Rd-mode-in-verbatim-p () + "Return non-nil if in a usage, examples, or synopsis." + (let ((pos (point))) + (save-excursion + (if (and (re-search-backward + "\\\\\\(usage\\|examples\\|synopsis\\)" nil t) + (re-search-forward "\\s(" nil t)) + (condition-case () + (progn + (up-list 1) + (< pos (point))) + (error t)) + nil)))) + +(defun Rd-mode-in-preprocessor-line-p () + "Return non-nil if in a preprocessor line." + (save-excursion + (beginning-of-line) + (looking-at "[ \t]*#\\(ifdef\\|endif\\)"))) + +(defun Rd-mode-calculate-indent () + "Return appropriate indentation for current line in Rd mode." + (save-excursion + (beginning-of-line) + (cond + ((Rd-mode-in-verbatim-p) + ;; Don't do anything in verbatims + nil) + ((Rd-mode-in-preprocessor-line-p) + ;; Indent to 0 + 0) + (t + (let ((p (progn + (re-search-forward "[ \t]*\\s)*" (line-end-position) t) + (point)))) + (if (or (< (forward-line -1) 0) + (Rd-mode-in-verbatim-p)) + 0 + (set-syntax-table Rd-mode-parse-syntax-table) + (while (and (or (looking-at "[ \t]*$") + (Rd-mode-in-preprocessor-line-p)) + (not (bobp))) + (forward-line -1)) + (re-search-forward "[ \t]*\\s)*" (line-end-position) t) + (prog1 + (+ (current-indentation) + (* (car (parse-partial-sexp (point) p)) + Rd-indent-level)) + (set-syntax-table Rd-mode-syntax-table)))))))) + +(defun Rd-mode-indent-line () + "Indent current line as Rd source." + (when-let ((ic (Rd-mode-calculate-indent)) + (rp (- (current-column) (current-indentation)))) + (when (< ic 0) + (error "Unmatched parenthesis")) + (indent-line-to ic) + (when (> rp 0) + (move-to-column (+ ic rp))))) + +(defun Rd-mode-insert-item () + "Insert \\item{ on a newline." + (interactive) + (reindent-then-newline-and-indent) + (insert "\\item{") + ) + +(defun Rd-mode-insert-section () + "Insert a section from `Rd-section-names'." + (interactive) + (let ((s (ess-completing-read + "Insert section: " + (mapcar (lambda (x) (cons x x)) Rd-section-names) + nil t))) + (if (string= s "") + (progn (insert "\\section{}{") (backward-char 2)) + (insert (format "\\%s{" s))))) + +(defun Rd-mode-insert-skeleton () + "Insert several empty Rd fields." + (interactive) + ;; Hmm: in theory this should be kept in sync with prompt() + ;; --- maybe using prompt() [or promptClass()...] would be better anyway?! + (insert "\\name{}\n") + (insert "\\alias{}\n") + (insert "\\title{}\n") + (insert "\\description{\n}\n") + (insert "\\usage{\n}\n") + (insert "\\arguments{\n}\n") + (insert "\\value{\n}\n") + (insert "\\details{\n}\n") + (insert "\\references{\n}\n") + (insert "\\seealso{\n}\n") + (insert "\\examples{\n}\n") + (insert "\\author{}\n") + (insert "\\keyword{}\n")) + +(defun Rd-mode-insert-data-skeleton () + "Insert several empty Rd fields." + (interactive) + ;; Hmm: in theory this should be kept in sync with prompt() + ;; --- maybe using prompt() [or promptClass()...] would be better anyway?! + (insert "\\name{}\n") + (insert "\\docType{}\n") + (insert "\\alias{}\n") + (insert "\\title{}\n") + (insert "\\description{\n}\n") + (insert "\\usage{\n}\n") + (insert "\\format{\n}\n") + (insert "\\details{\n}\n") + (insert "\\source{}\n") + (insert "\\references{\n}\n") + (insert "\\examples{\n}\n") + (insert "\\keyword{datasets}\n")) + + +;; This is an `easy' version of (defun TeX-font ..) in AUCtex's tex.el ; +;; see TeX-font-list and also LaTeX-font-list in latex.el + +(defun Rd-font (what) + "Insert template for font command. +WHAT determines the font to use, as specified by `Rd-font-list'." + (interactive "c") + ;;TeX had : (Rd-update-style) + (let* ((entry (assoc what Rd-font-list)) + (before (nth 1 entry)) + (after (nth 2 entry))) + (cond ((null entry) ;; help on possibilities : + (let ((help + (concat + "Rd Markup (available from C-c C-f):\n\n\t" + "KEY Rd-Markup\n\n" + (mapconcat + (lambda (entry) + ;; A textual description of an ENTRY in TeX-font-list. + (concat (format "%11s " + (key-description + (char-to-string (nth 0 entry)))) + (format "%14s %-3s" + (nth 1 entry) (nth 2 entry)))) + Rd-font-list "\n")))) + (with-output-to-temp-buffer "*Help*" + (set-buffer "*Help*") + (insert help)))) + + ((region-active-p) + (save-excursion + (cond ((> (mark) (point)) + (insert before) + (goto-char (mark)) + (insert after)) + (t + (insert after) + (goto-char (mark)) + (insert before))))) + (t + (insert before) + (save-excursion + (insert after)))))) + +(defun Rd-preview-help (&optional via-shell) + "Preview the current Rd buffer contents as help. +If the current buffer is not associated with a file, create a +temporary one in variable `temporary-file-directory'." + (declare (advertised-calling-convention () "ESS 19.04")) + (interactive "P") ; If optional VIA-SHELL is set, using `Rd-to-help-command'. + (let ((file buffer-file-name) + (pbuf (get-buffer-create "R Help Preview")) + del-p) + (unless file + (setq file (make-temp-file "RD_" nil ".Rd")) + (write-region (point-min) (point-max) file) + (setq del-p t)) + + (if via-shell ;; FIXME eventually get rid of this option + ;; only method in ESS <= 14.09 -- calls "R" even if in "R-devel"; slower + (let ((shcmd (format "%s '%s'" Rd-to-help-command file))) + (set-buffer pbuf) + (erase-buffer) + (ess-write-to-dribble-buffer + (format "Rd-preview-help: (shell-command |%s| t)" shcmd)) + (shell-command shcmd t)) + ;; else directly: + (ess-force-buffer-current "R process to use: ") + (ess--foreground-command (format ".ess_Rd2txt(\"%s\")\n" file) pbuf) + (set-buffer pbuf)) + + ;; FIXME(2): once got rid of via-shell, consider + ;; (ess--flush-help-into-current-buffer file "tools::Rd2txt(\"%s\")\n") + ;; instead of all this : + (ess-setq-vars-local ess-r-customize-alist) + ;; mostly cut'n'paste from ess--flush-help* (see FIXME(2)): + (ess-help-underline) + (ess--help-major-mode) + ;; FIXME: Is this really needed? + (setq ess-help-sec-regex ess-help-r-sec-regex + ess-help-sec-keys-alist ess-help-r-sec-keys-alist) + (goto-char (point-min)) + (set-buffer-modified-p 'nil) + (setq buffer-read-only t) + (setq truncate-lines nil) + (when del-p (delete-file file)) + (unless (get-buffer-window pbuf 'visible) + (display-buffer pbuf t)))) + +(define-obsolete-function-alias 'Rd-submit-bug-report #'ess-submit-bug-report "2018-08-16") + +(provide 'ess-rd) + +;;; ess-rd.el ends here diff --git a/elpa/ess-20230419.1527/ess-rdired.el b/elpa/ess-20230419.1527/ess-rdired.el new file mode 100644 index 00000000..35449f33 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-rdired.el @@ -0,0 +1,291 @@ +;;; ess-rdired.el --- prototype object browser for R, looks like dired mode. -*- lexical-binding: t; -*- + +;; Copyright (C) 2002-2022 Free Software Foundation, Inc. +;; Author: Stephen Eglen +;; Created: Thu 24 Oct 2002 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This provides a dired-like buffer for R objects. Instead of +;; operating on files, we operate on R objects in the current +;; environment. Objects can be viewed, edited, deleted, plotted and +;; so on. +;; Do "M-x R" to start an R session, then create a few variables: +;; +;; s <- sin(seq(from=0, to=8*pi, length=100)) +;; x <- c(1, 4, 9) +;; y <- rnorm(20) +;; z <- TRUE + +;; Then in Emacs, do "M-x ess-rdired" and you should see the following in +;; the buffer *R dired*: +;; Name Class Length Size +;; s numeric 100 848 bytes +;; x numeric 3 80 bytes +;; y numeric 20 208 bytes +;; z logical 1 56 bytes + +;; Type "?" in the buffer to see the documentation. e.g. when the +;; cursor is on the line for `s', type 'p' to plot it, or `v' to view +;; its contents in a buffer. Then type 'd' to delete it. + +;; How it works. + +;; Most of the hard work is done by the R routine .rdired.objects(), +;; which, when called, produces the list of objects in a tidy format. +;; This function is stored within the Lisp variable `ess-rdired-objects'. + +;; Todo - How to select alternative environments? Currently only +;; shows objects in the .GlobalEnv? See BrowseEnv() in 1.6.x for way +;; of browsing other environments. + +;; Todo - problem with fix -- have to wait for fix() command to return +;; before *R* buffer can be used again. This can get stuck, umm. not +;; sure what is going wrong here. Maybe add a hook to the temp buffer +;; so that when buffer is killed, we send an instruction to R to +;; update the value of the variable to the contents of the buffer. +;; This way *R* doesn't have to wait. + +;; Todo - small bug in .rdired.objects -- if we have a variable called +;; `my.x', its value is replaced by the value of my.x used in the +;; sapply() calls within .rdired.objects(). + +;;; Code: + +(require 'ess-inf) + +(eval-when-compile + (require 'subr-x)) + +(defvar ess-rdired-objects ".ess.rdired()\n" + "Function to call within R to print information on objects.") + +(defvar ess-rdired-buffer "*R dired*" + "Name of buffer for displaying R objects.") + +(defvar ess-rdired-auto-update-timer nil + "The timer object for auto updates.") + +(defcustom ess-rdired-auto-update-interval 5 + "Seconds between refreshes of the `ess-rdired' buffer." + :type '(choice (const nil :tag "No auto updates") (integer :tag "Seconds")) + :group 'ess-R + :package-version '(ess . "19.04")) + +(defvar ess-rdired-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "d" #'ess-rdired-delete) + (define-key map "x" #'ess-rdired-delete) + (define-key map "v" #'ess-rdired-view) + (define-key map "V" #'ess-rdired-View) + (define-key map "p" #'ess-rdired-plot) + (define-key map "y" #'ess-rdired-type) + (define-key map "\C-c\C-s" #'ess-rdired-switch-process) + (define-key map "\C-c\C-y" #'ess-switch-to-ESS) + (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) + map)) + +(define-derived-mode ess-rdired-mode tabulated-list-mode "Rdired" + "Major mode for output from `ess-rdired'. +`ess-rdired' provides a dired-like mode for R objects. It shows the +list of current objects in the current environment, one-per-line. You +can then examine these objects, plot them, and so on." + :group 'ess-R + (setq mode-name (concat "RDired " ess-local-process-name)) + (setq tabulated-list-format + `[("Name" 18 t) + ("Class" 10 t) + ("Length" 10 ess-rdired--length-predicate) + ("Size" 10 ess-rdired--size-predicate)]) + (add-hook 'tabulated-list-revert-hook #'ess-rdired-refresh nil t) + (when (and (not ess-rdired-auto-update-timer) + ess-rdired-auto-update-interval) + (setq ess-rdired-auto-update-timer + (run-at-time t ess-rdired-auto-update-interval #'ess-rdired-refresh))) + (add-hook 'kill-buffer-hook #'ess-rdired-cancel-auto-update-timer nil t) + (tabulated-list-init-header)) + +;;;###autoload +(defun ess-rdired () + "Show R objects from the global environment in a separate buffer. +You may interact with these objects, see `ess-rdired-mode' for +details." + (interactive) + (unless (and (string= "R" ess-dialect) + ess-local-process-name) + (error "Not in an R buffer with attached process")) + (let ((proc ess-local-process-name)) + (pop-to-buffer (get-buffer-create ess-rdired-buffer)) + (setq ess-local-process-name proc) + (ess-rdired-mode) + (ess-rdired-refresh))) + +(defun ess-rdired-refresh () + "Refresh the `ess-rdired' buffer." + (let* ((buff (get-buffer-create ess-rdired-buffer)) + (proc-name (buffer-local-value 'ess-local-process-name buff)) + (proc (get-process proc-name)) + (out-buff (get-buffer-create " *ess-rdired-output*")) + text) + (when (and proc-name proc + (not (process-get proc 'busy))) + (ess--foreground-command ess-rdired-objects out-buff nil nil nil proc) + (with-current-buffer out-buff + (goto-char (point-min)) + ;; Delete two lines. One filled with +'s from R's prompt + ;; printing, the other with the header info from the data.frame + (delete-region (point-min) (1+ (line-end-position 2))) + (setq text (split-string (buffer-string) "\n" t "\n")) + (erase-buffer)) + (with-current-buffer buff + (setq tabulated-list-entries + (mapcar #'ess-rdired--tabulated-list-entries text)) + (let ((entry (tabulated-list-get-id)) + (col (current-column))) + (tabulated-list-print) + (while (not (equal entry (tabulated-list-get-id))) + (forward-line)) + (move-to-column col)))))) + +(defun ess-rdired-cancel-auto-update-timer () + "Cancel the timer `ess-rdired-auto-update-timer'." + (setq ess-rdired-auto-update-timer + (cancel-timer ess-rdired-auto-update-timer))) + +(defun ess-rdired--tabulated-list-entries (text) + "Return a value suitable for `tabulated-list-entries' from TEXT." + (let (name class length size) + (if (not (string-match-p " +\"" text)) + ;; Normal-world + (setq text (split-string text " " t) + name (nth 0 text) + text (cdr text)) + ;; Else, someone has spaces in their variable names + (string-match "\"\\([^\"]+\\)" text) + (setq name (substring (match-string 0 text) 1) + text (split-string (substring text (1+ (match-end 0))) " " t))) + (setq class (nth 0 text) + length (nth 1 text) + size (nth 2 text)) + (list name + `[(,name + help-echo "mouse-2, RET: View this object" + action ess-rdired-view) + ,class + ,length + ,size]))) + +(defun ess-rdired-edit () + "Edit the object at point." + (interactive) + (ess-command (concat "edit(" (tabulated-list-get-id) ")\n"))) + +(defun ess-rdired-view (&optional _button) + "View the object at point." + (interactive) + (ess-execute (ess-rdired-get (tabulated-list-get-id)) + nil "R view" )) + +(defun ess-rdired-get (name) + "Generate R code to get the value of the variable NAME. +This is complicated because some variables might have spaces in their names. +Otherwise, we could just pass the variable name directly to *R*." + (concat "get(" (ess-rdired-quote name) ")") + ) + +(defun ess-rdired-quote (name) + "Quote NAME if not already quoted." + (if (equal (substring name 0 1) "\"") + name + (concat "\"" name "\""))) + +(defun ess-rdired-View () + "View the object at point in its own buffer. +Like `ess-rdired-view', but the object gets its own buffer name." + (interactive) + (let ((objname (tabulated-list-get-id))) + (ess-execute (ess-rdired-get objname) + nil (concat "R view " objname )))) + +(defun ess-rdired-plot () + "Plot the object on current line." + (interactive) + (let ((objname (tabulated-list-get-id))) + (ess-eval-linewise (format "plot(%s)" (ess-rdired-get objname))))) + +(defun ess-rdired-type () + "Run the mode() on command at point." + (interactive) + (let ((objname (tabulated-list-get-id)) + ;; create a temp buffer, and then show output in echo area + (tmpbuf (get-buffer-create "**ess-rdired-mode**"))) + (if objname + (progn + (ess-command (concat "mode(" (ess-rdired-get objname) ")\n") + tmpbuf ) + (set-buffer tmpbuf) + (message "%s" (concat + objname ": " + (buffer-substring (+ 4 (point-min)) (1- (point-max))))) + (kill-buffer tmpbuf))))) + +(defalias 'ess-rdired-expunge #'ess-rdired-delete) + +(defun ess-rdired-delete () + "Delete the object at point." + (interactive) + (let ((objname (tabulated-list-get-id))) + (when (yes-or-no-p (format "Really delete %s? " objname)) + (ess-eval-linewise (format "rm(%s)" (ess-rdired-quote objname)) nil nil nil t) + (revert-buffer)))) + +(defun ess-rdired-switch-process () + "Switch to examine different *R* process. +If you have multiple R processes running, e.g. *R*, *R:2*, *R:3*, you can +use this command to choose which R process you would like to examine. +After switching to a new process, the buffer is updated." + (interactive) + (ess-switch-process) + (ess-rdired)) + +(defun ess-rdired--length-predicate (A B) + "Enable sorting by length in `ess-rdired' buffers. +Return t if A's length is < than B's length." + (let ((lenA (aref (cadr A) 2)) + (lenB (aref (cadr B) 2))) + (< (string-to-number lenA) (string-to-number lenB)))) + +(defun ess-rdired--size-predicate (A B) + "Enable sorting by size in `ess-rdired' buffers. +Return t if A's size is < than B's size." + (let ((lenA (aref (cadr A) 3)) + (lenB (aref (cadr B) 3))) + (< (string-to-number lenA) (string-to-number lenB)))) + +(define-obsolete-function-alias 'ess-rdired-quit #'quit-window "ESS 19.04") +(define-obsolete-function-alias 'ess-rdired-next-line #'forward-to-indentation "ESS 19.04") +(define-obsolete-function-alias 'ess-rdired-previous-line #'backward-to-indentation "ESS 19.04") +(define-obsolete-function-alias 'ess-rdired-move-to-object #'back-to-indentation "ESS 19.04") + +(provide 'ess-rdired) + +;;; ess-rdired.el ends here diff --git a/elpa/ess-20230419.1527/ess-roxy.el b/elpa/ess-20230419.1527/ess-roxy.el new file mode 100644 index 00000000..00b172c2 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-roxy.el @@ -0,0 +1,1038 @@ +;;; ess-roxy.el --- convenient editing of in-code roxygen documentation -*- lexical-binding: t; -*- + +;; Copyright (C) 2009-2022 Free Software Foundation, Inc. +;; Author: Henning Redestig + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Lots of inspiration from doc-mode, +;; https://nschum.de/src/emacs/doc-mode/ +;; +;; Features:: +;; +;; - basic highlighting +;; - generating and updating templates from function definition and customized default template +;; - C-c C-o C-o :: update template +;; - navigating and filling roxygen fields +;; - C-c TAB, M-q, C-a, ENTER, M-h :: advised tag completion, fill-paragraph, +;; ess-roxy-move-beginning-of-line, newline-and-indent +;; - C-c C-o n,p :: next, previous roxygen entry +;; - C-c C-o C-c :: Unroxygen region. Convenient for editing examples. +;; - folding visibility using hs-minor-mode +;; - TAB :: advised ess-indent-command, hide entry if in roxygen doc. +;; - preview +;; - C-c C-o C-r :: create a preview of the Rd file as generated +;; using roxygen +;; - C-c C-o C-t :: create a preview of the Rd HTML file as generated +;; using roxygen and the tools package +;; - C-c C-o t :: create a preview of the Rd text file +;; +;; Known issues: +;; +;; - hideshow mode does not work very well. In particular, if ordinary +;; comments precede a roxygen entry, then both will be hidden in the +;; same overlay from start and not unfoldable using TAB since the +;; roxygen prefix is not present. The planned solution is implement +;; a replacement for hideshow. +;; - only limited functionality for S4 documentation. + +;;; Code: + +(require 'ess-utils) +(require 'hideshow) +(require 'outline) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) +(require 'ess-rd) +(require 'ess-r-syntax) + +(defvar roxy-str) +(defvar ess-r-mode-syntax-table) +(declare-function ess-fill-args "ess-r-mode") +(declare-function ess-fill-continuations "ess-r-mode") +(declare-function inferior-ess-r-force "ess-r-mode") + +(defvar-local ess-roxy-re nil + "Regular expression to recognize roxygen blocks.") + + +;;*;; Roxy Minor Mode + +(defvar ess-roxy-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-o h") #'ess-roxy-hide-all) + (define-key map (kbd "C-c C-o n") #'ess-roxy-next-entry) + (define-key map (kbd "C-c C-o p") #'ess-roxy-previous-entry) + (define-key map (kbd "C-c C-o C-o") #'ess-roxy-update-entry) + (define-key map (kbd "C-c C-o C-r") #'ess-roxy-preview-Rd) + (define-key map (kbd "C-c C-o C-w") #'ess-roxy-preview-HTML) + (define-key map (kbd "C-c C-o C-t") #'ess-roxy-preview-text) + (define-key map (kbd "C-c C-o C-c") #'ess-roxy-toggle-roxy-region) + (define-key map [remap back-to-indentation] #'ess-roxy-goto-end-of-roxy-comment) + (define-key map [remap newline] #'ess-roxy-newline) + (define-key map [remap newline-and-indent] #'ess-roxy-newline) + (define-key map [remap ess-indent-command] #'ess-roxy-ess-indent-command) + (define-key map [remap move-beginning-of-line] #'ess-roxy-move-beginning-of-line) + (define-key map [remap beginning-of-visual-line] #'ess-roxy-move-beginning-of-line) + map)) + +(defvar ess-roxy-font-lock-keywords nil + "Cache set by `ess-roxy-generate-keywords'. +Used to remove keywords added by function `ess-roxy-mode'.") + +(defun ess-roxy-generate-keywords () + "Generate a list of keywords suitable for `font-lock-add-keywords'." + (setq-local ess-roxy-font-lock-keywords + `((,(concat ess-roxy-re " *\\([@\\]" + (regexp-opt ess-roxy-tags-param t) + "\\)\\>") + (1 'font-lock-keyword-face prepend)) + (,(concat ess-roxy-re " *\\(@" + (regexp-opt '("param" "importFrom" "importClassesFrom" + "importMethodsFrom" "describeIn") + 'words) + "\\)\\(?:[ \t]+\\(\\(?:\\sw+,?\\)+\\)\\)") + (1 'font-lock-keyword-face prepend) + (3 'font-lock-variable-name-face prepend)) + (,(concat "[@\\]" (regexp-opt ess-roxy-tags-noparam t) "\\>") + (0 'font-lock-variable-name-face prepend)) + (,(concat ess-roxy-re) + (0 'bold prepend))))) + +(defvar ess-roxy-fold-examples nil + "Whether to fold `@examples' when opening a buffer. +Use you regular key for `outline-show-entry' to reveal it.") + +;;;###autoload +(define-minor-mode ess-roxy-mode + "Minor mode for editing ROxygen documentation." + :keymap ess-roxy-mode-map + (if ess-roxy-mode + ;; Turn on `ess-roxy-mode': + (progn + (setq-local ess-roxy-re (concat "^" (string-trim comment-start) "+'")) + (font-lock-add-keywords nil (ess-roxy-generate-keywords)) + (add-hook 'completion-at-point-functions #'ess-roxy-complete-tag nil t) + ;; Hideshow Integration + (when ess-roxy-hide-show-p + (hs-minor-mode 1) + (when ess-roxy-start-hidden-p + (ess-roxy-hide-all))) + ;; Outline Integration + (when ess-roxy-fold-examples + (ess-roxy-hide-all-examples)) + ;; Autofill + (setq-local paragraph-start (concat "\\(" ess-roxy-re "\\)*" paragraph-start)) + (setq-local paragraph-separate (concat "\\(" ess-roxy-re "\\)*" paragraph-separate)) + (setq-local adaptive-fill-function #'ess-roxy-adaptive-fill-function) + ;; Hooks + (add-hook 'ess-presend-filter-functions #'ess-roxy-remove-roxy-re nil t)) + ;; Turn off `ess-roxy-mode': + ;; Hideshow + (when (and ess-roxy-hide-show-p hs-minor-mode) + (hs-show-all) + (hs-minor-mode)) + ;; Hooks + (remove-hook 'ess-presend-filter-functions #'ess-roxy-remove-roxy-re t) + (font-lock-remove-keywords nil ess-roxy-font-lock-keywords) + ;; (setq-local syntax-propertize-function nil) + ;; (setq-local font-lock-fontify-region-function nil) + ;; (setq-local font-lock-unfontify-region-function nil) + ) + ;; Regardless of turning on or off we need to re-fontify the buffer: + (when font-lock-mode + (font-lock-flush))) + + + +;;*;; Outline Integration + +(defvar ess-roxy-outline-regexp "^#+' +@examples\\|^[^#]") + +(defun ess-roxy-substitute-outline-regexp (command) + (let ((outline-regexp (if (ess-roxy-entry-p "examples") + ess-roxy-outline-regexp + outline-regexp))) + (funcall command))) + +(declare-function outline-cycle "outline-magic") +(defun ess-roxy-cycle-example () + (interactive) + (unless (featurep 'outline-magic) + (error "Please install and load outline-magic")) + ;; Don't show children when cycling @examples + (let ((this-command 'outline-cycle-overview)) + (ess-roxy-substitute-outline-regexp #'outline-cycle))) + +(defun ess-roxy-show-example () + (interactive) + (ess-roxy-substitute-outline-regexp #'outline-show-entry)) + +(defun ess-roxy-hide-example () + (interactive) + (ess-roxy-substitute-outline-regexp #'outline-hide-entry)) + +(defun ess-roxy-hide-all-examples () + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^#+' +@examples\\b" nil t) + ;; Handle edge cases + (when (ess-roxy-entry-p "examples") + (ess-roxy-hide-example))))) + +(substitute-key-definition #'outline-hide-entry + #'ess-roxy-hide-example + ess-roxy-mode-map outline-minor-mode-map) + +(substitute-key-definition #'outline-show-entry + #'ess-roxy-show-example + ess-roxy-mode-map outline-minor-mode-map) + + +;;*;; Function definitions + +(defun ess-back-to-roxy () + "Go to roxy prefix." + (end-of-line) + (re-search-backward (concat ess-roxy-re " ?") (line-beginning-position)) + (goto-char (match-end 0))) + +(defun ess-roxy-beg-of-entry () + "Get point number at start of current entry, 0 if not in entry." + (save-excursion + (let (beg) + (beginning-of-line) + (setq beg -1) + (if (not (ess-roxy-entry-p)) + (setq beg 0) + (setq beg (point))) + (while (and (= (forward-line -1) 0) (ess-roxy-entry-p)) + (setq beg (point))) + beg))) + +(defun ess-roxy-in-header-p () + "True if point is the description / details field." + (save-excursion + (let ((res t) + (cont (ess-roxy-entry-p))) + (beginning-of-line) + (while cont + (if (looking-at (concat ess-roxy-re " *[@].+")) + (progn (setq res nil) + (setq cont nil))) + (setq cont (and (= (forward-line -1) 0) (ess-roxy-entry-p))) + )res))) + +(defun ess-roxy-beg-of-field () + "Get point number at beginning of current field, 0 if not in entry." + (save-excursion + (let (cont beg) + (beginning-of-line) + (setq beg 0) + (setq cont t) + (while (and (ess-roxy-entry-p) cont) + (setq beg (point)) + (if (looking-at (concat ess-roxy-re " *[@].+")) + (setq cont nil)) + (if (ess-roxy-in-header-p) + (if (looking-at (concat ess-roxy-re " *$")) + (progn + (forward-line 1) + (setq beg (point)) + (setq cont nil)))) + (if cont (setq cont (= (forward-line -1) 0)))) + beg))) + +(defun ess-roxy-end-of-entry () + "Get point number at end of current entry, 0 if not in entry." + (save-excursion + (let ((end)) + (end-of-line) + (setq end -1) + (if (not (ess-roxy-entry-p)) + (setq end 0) + (setq end (point))) + (while (and (= (forward-line 1) 0) (ess-roxy-entry-p)) + (end-of-line) + (setq end (point))) + end))) + +(defun ess-roxy-end-of-field () + "Get point number at end of current field, 0 if not in entry." + (save-excursion + (let ((end nil) + (cont nil)) + (setq end 0) + (if (ess-roxy-entry-p) (progn (end-of-line) (setq end (point)))) + (beginning-of-line) + (forward-line 1) + (setq cont t) + (while (and (ess-roxy-entry-p) cont) + (save-excursion + (end-of-line) + (setq end (point))) + (if (or (and (ess-roxy-in-header-p) + (looking-at (concat ess-roxy-re " *$"))) + (looking-at (concat ess-roxy-re " *[@].+"))) + (progn + (forward-line -1) + (end-of-line) + (setq end (point)) + (setq cont nil))) + (if cont (setq cont (= (forward-line 1) 0)))) + end))) + +(defun ess-roxy-entry-p (&optional field) + "Non-nil if point is in a roxy entry. +FIELD allows checking for a specific field with +`ess-roxy-current-field'." + (and ess-roxy-mode + (save-excursion + (beginning-of-line) + (looking-at-p ess-roxy-re)) + (or (null field) + (string= (ess-roxy-current-field) field)))) + +(defun ess-roxy-narrow-to-field () + "Go to to the start of current field." + (interactive) + (let ((beg (ess-roxy-beg-of-field)) + (end (ess-roxy-end-of-field))) + (narrow-to-region beg end))) + +(defun ess-roxy-extract-field () + (let ((field (buffer-substring (ess-roxy-beg-of-entry) + (ess-roxy-end-of-entry))) + (prefix-re (ess-roxy-guess-str)) + (roxy-re ess-roxy-re)) + (with-temp-buffer + (setq ess-roxy-re roxy-re) + (insert field) + (goto-char (point-min)) + (while (re-search-forward prefix-re (point-max) 'noerror) + (replace-match "")) + (buffer-substring (point-min) (point-max))))) + +(defun ess-roxy-adaptive-fill-function () + "Return prefix for filling paragraph or nil if not determined." + (when (ess-roxy-entry-p) + (let ((roxy-str (car (split-string (ess-roxy-guess-str) "'")))) + (if (ess-roxy-in-header-p) + (save-excursion + (ess-back-to-roxy) + (re-search-forward "\\([ \t]*\\)" (line-end-position) t) + (concat roxy-str "' " (match-string 1))) + (concat roxy-str "' " (make-string ess-indent-offset ? )))))) + +(defun ess-roxy-current-field () + "Return the name of the field at point." + (and (not (ess-roxy-in-header-p)) + (save-excursion + (goto-char (ess-roxy-beg-of-field)) + (if (re-search-forward (concat ess-roxy-re + "[ \t]+@\\([[:alpha:]]+\\)") + (line-end-position) t) + (match-string-no-properties 1))))) + +(defun ess-roxy-maybe-indent-line () + "Indent line when point is in a field, but not in its first line." + (when (and (not (ess-roxy-in-header-p)) + (not (equal (ess-roxy-current-field) "examples")) + (save-excursion + (beginning-of-line) + (let ((line-n (count-lines 1 (point)))) + (goto-char (ess-roxy-beg-of-field)) + (not (equal line-n (count-lines 1 (point))))))) + (ess-back-to-roxy) + (delete-region (point) (progn (skip-chars-forward " \t") (point))) + (insert (make-string ess-indent-offset ? )))) + +(defun ess-roxy-goto-func-def () + "Put point at start of function. +Go to the beginning of the current one or below the current +roxygen entry, error otherwise" + (if (ess-roxy-entry-p) + (progn + (ess-roxy-goto-end-of-entry) + (forward-line 1) + (beginning-of-line)) + (unless (looking-at-p ess-function-pattern) + (beginning-of-defun)))) + +(defun ess-roxy-get-args-list-from-def () + "Get args list for current function." + (save-excursion + (ess-roxy-goto-func-def) + (let ((args (ess-roxy-get-function-args))) + (mapcar (lambda (x) (cons x '(""))) args)))) + +(defun ess-roxy-insert-args (args &optional here) + "Insert an ARGS list to the end of the current roxygen entry. +If HERE is supplied start inputting `here'. Finish at end of +line." + (let* ((roxy-str (ess-roxy-guess-str)) + arg-des) + (if (and here (< 1 here)) + (goto-char here) + (ess-roxy-goto-end-of-entry) + (beginning-of-line) + (when (not (looking-at-p "=")) + (end-of-line))) + (while (stringp (caar args)) + (setq arg-des (pop args)) + (unless (string= (car arg-des) "") + (insert (concat "\n" roxy-str " @param " (car arg-des) " ")) + (insert + (ess-replace-in-string (concat (car (cdr arg-des))) "\n" + (concat "\n" roxy-str))) + (when ess-roxy-fill-param-p + (fill-paragraph)))))) + +(defun ess-roxy-merge-args (fun ent) + "Take two args lists (alists) and return their union. +The result holds all keys from both FUN and ENT but no duplicates and +association from ent are preferred over entries from fun. Also, +drop entries from ent that are not in fun and are associated with +the empty string." + (let ((res-arg nil) + (arg-des)) + (while (stringp (caar fun)) + (setq arg-des (pop fun)) + (if (assoc (car arg-des) ent) + (setq res-arg + (cons (cons (car arg-des) (cdr (assoc (car arg-des) ent))) res-arg)) + (setq res-arg (cons (cons (car arg-des) '("")) res-arg)))) + (while (stringp (caar ent)) + (setq arg-des (pop ent)) + (if (and (not (assoc (car arg-des) res-arg)) (not (string= (car (cdr arg-des)) ""))) + (setq res-arg (cons (cons (car arg-des) (cdr arg-des)) res-arg)))) + (nreverse res-arg))) + +(defun ess-roxy-update-entry () + "Update the entry at point or the entry above the current function. +Add a template empty roxygen documentation if no roxygen entry is +available. The template can be customized via the variable +`ess-roxy-template-alist'. The parameter descriptions can are +filled if `ess-roxy-fill-param-p' is non-nil." + (interactive) + (unless (derived-mode-p 'ess-r-mode) + (user-error "%s mode not yet supported" major-mode)) + (save-excursion + (let* ((args-fun (ess-roxy-get-args-list-from-def)) + (args-ent (ess-roxy-get-args-list-from-entry)) + (args (ess-roxy-merge-args args-fun args-ent)) + (roxy-str (ess-roxy-guess-str)) + (line-break "") + template tag-def) + (ess-roxy-goto-func-def) + (when (not (= (forward-line -1) 0)) + (insert "\n") + (forward-line -1)) + (when (and (not (looking-at "^\n")) (not (ess-roxy-entry-p))) + (end-of-line) + (insert "\n")) + (if (ess-roxy-entry-p) + (ess-roxy-insert-args args (1- (ess-roxy-delete-args))) + (setq template (copy-sequence ess-roxy-template-alist)) + (while (stringp (caar template)) + (setq tag-def (pop template)) + (if (string= (car tag-def) "param") + (ess-roxy-insert-args args (point)) + (if (string= (car tag-def) "description") + (insert (concat line-break roxy-str " " + (cdr tag-def) "\n" roxy-str)) + (if (string= (car tag-def) "details") + (insert (concat line-break roxy-str " " (cdr tag-def))) + (insert (concat line-break roxy-str " @" + (car tag-def) " " (cdr tag-def)))))) + (setq line-break "\n")))))) + +(defun ess-roxy-goto-end-of-entry () + "Put point at the bottom of the current entry or above the function at point. +Return t if the point is left in a roxygen entry, otherwise nil. +Error if point is not in function or roxygen entry." + (when (not (ess-roxy-entry-p)) + (beginning-of-defun) + (forward-line -1)) + (if (ess-roxy-entry-p) + (progn (goto-char (ess-roxy-end-of-entry)) + t) + (forward-line) + nil) + (ess-roxy-entry-p)) + +(defun ess-roxy-goto-beg-of-entry () + "Put point at the top of the entry at point or above the function at point. +Return t if the point is left in a roxygen +entry, otherwise nil. Error if point is not in function or +roxygen entry." + (if (not (ess-roxy-entry-p)) + (progn + (goto-char (nth 0 (end-of-defun))) + (forward-line -1))) + (if (ess-roxy-entry-p) + (progn + (goto-char (ess-roxy-beg-of-entry)) + t) + (forward-line) nil)) + +(defun ess-roxy-delete-args () + "Remove all args from the entry at point or above the function at point. +Return 0 if no deletions were made other wise the point at where +the last deletion ended" + (save-excursion + (let* ((cont t) + (field-beg 0) + entry-beg entry-end field-end) + (ess-roxy-goto-end-of-entry) + (setq entry-beg (ess-roxy-beg-of-entry)) + (setq entry-end (ess-roxy-end-of-entry)) + (goto-char entry-end) + (beginning-of-line) + (while (and (<= entry-beg (point)) (> entry-beg 0) cont) + (if (looking-at + (concat ess-roxy-re " *@param")) + (progn + (setq field-beg (ess-roxy-beg-of-field)) + (setq field-end (ess-roxy-end-of-field)) + (delete-region field-beg (+ field-end 1)))) + (setq cont nil) + (if (= (forward-line -1) 0) + (setq cont t))) + field-beg))) + +(defun ess-roxy-get-args-list-from-entry () + "Fill an args list from the entry above the function where the point is." + (save-excursion + (let* (args entry-beg field-beg field-end args-text arg-name desc) + (if (ess-roxy-goto-end-of-entry) + (progn + (setq roxy-str (ess-roxy-guess-str)) + (beginning-of-line) + (setq entry-beg (ess-roxy-beg-of-entry)) + (while (and (< entry-beg (point)) (> entry-beg 0)) + (if (looking-at + (concat ess-roxy-re " *@param")) + (progn + (setq field-beg (ess-roxy-beg-of-field)) + (setq field-end (ess-roxy-end-of-field)) + (setq args-text (buffer-substring-no-properties + field-beg field-end)) + (setq args-text + (ess-replace-in-string args-text roxy-str "")) + (setq args-text + (ess-replace-in-string + args-text "[[:space:]]*@param *" "")) + ;; (setq args-text + ;; (ess-replace-in-string args-text "\n" "")) + (string-match "[^[:space:]]*" args-text) + (setq arg-name (match-string 0 args-text)) + (setq desc (replace-regexp-in-string + (concat "^" (regexp-quote arg-name) " *") "" args-text)) + (setq args (cons (list (concat arg-name) + (concat desc)) + args)))) + (forward-line -1)) + args) + nil)))) + +(defun ess-roxy-toggle-roxy-region (beg end) + "Toggle prefix roxygen string from BEG to END. +Add the prefix if missing, remove if found. BEG and END default +to the region, if active, and otherwise the entire line. This is +convenient for editing example fields." + (interactive "r") + (unless (and beg end) + (setq beg (line-beginning-position) + end (line-end-position))) + (ess-roxy-roxy-region beg end (ess-roxy-entry-p))) + +(defun ess-roxy-roxy-region (beg end &optional on) + (save-excursion + (let (RE to-string + (roxy-str (ess-roxy-guess-str))) + (narrow-to-region beg (- end 1)) + (if on + (progn (setq RE (concat ess-roxy-re " +?")) + (setq to-string "")) + (setq RE "^") + (setq to-string (concat roxy-str " "))) + (goto-char beg) + (while (re-search-forward RE (point-max) 'noerror) + (replace-match to-string)) + (widen)))) + +(defun ess-roxy-preview () + "Generate documentation for roxygen entry at point. +Use a connected R session (starting one if necessary) and +`ess-roxy-package' to generate the Rd code for the entry at +point. Place it in a buffer and return that buffer." + (unless (derived-mode-p 'ess-r-mode) + (user-error "Preview only supported in R buffers, try `ess-r-devtools-document-package' instead")) + (let* ((beg (ess-roxy-beg-of-entry)) + (tmpf (make-temp-file "ess-roxy")) + (roxy-buf (get-buffer-create " *RoxygenPreview*")) + (R-old-roxy + (concat + "..results <- roxygen2:::roc_process(rd_roclet(), parse.files(P), \"\");" + "cat(vapply(..results, function(x) roxygen2:::rd_out_cache$compute(x, format(x)), character(1)), \"\\n\")" )) + (R-new-roxy + (concat + "..results <- roc_proc_text(rd_roclet(), readChar(P, file.info(P)$size));" + "cat(vapply(..results, format, character(1)), \"\\n\")" )) + (out-rd-roclet + (cond ((string= "roxygen" ess-roxy-package) + "make.Rd2.roclet()$parse") + ;; must not line break strings to avoid getting +s in the output + ((string= "roxygen2" ess-roxy-package) + (concat "(function(P) { if(packageVersion('roxygen2') < '3.0.0') {" + R-old-roxy "} else {" R-new-roxy "} })")) + (t (error "Need to hard code the roclet output call for roxygen package '%s'" + ess-roxy-package))))) + (when (= beg 0) + (error "Point is not in a Roxygen entry")) + (save-excursion + (goto-char (ess-roxy-end-of-entry)) + (forward-line 1) + (if (end-of-defun) + (append-to-file beg (point) tmpf) + (while (and (forward-line 1) + (not (looking-at-p "^$")) + (not (eobp)) + (not (looking-at-p ess-roxy-re)))) + (append-to-file beg (point) tmpf)) + (inferior-ess-r-force) + (ess-force-buffer-current) + (unless (ess-boolean-command (concat "print(suppressWarnings(require(" ess-roxy-package + ", quietly=TRUE)))\n")) + (error (concat "Failed to load the " ess-roxy-package " package; " + "in R, try install.packages(\"" ess-roxy-package "\")"))) + (ess-command (concat out-rd-roclet "(\"" tmpf "\")\n") roxy-buf) + (with-current-buffer roxy-buf + ;; Kill characters up to % in case we missed stripping prompts + ;; or +'s: + (goto-char (point-min)) + (when (re-search-forward "%" (line-end-position) t) + (backward-char) + (delete-region (line-beginning-position) (point))))) + (delete-file tmpf) + roxy-buf)) + +(defun ess-roxy-preview-HTML (&optional visit-instead-of-browse) + "Use a (possibly newly) connected R session and the roxygen package to +generate a HTML page for the roxygen entry at point and open that +buffer in a browser. Visit the HTML file instead of showing it in +a browser if `visit-instead-of-browse' is non-nil." + (interactive "P") + (let* ((roxy-buf (ess-roxy-preview)) + (rd-tmp-file (make-temp-file "ess-roxy-" nil ".Rd")) + (html-tmp-file (make-temp-file "ess-roxy-" nil ".html")) + (rd-to-html (concat "Rd2HTML(\"" rd-tmp-file "\",\"" + html-tmp-file "\", stages=c(\"render\"))")) + ) + (with-current-buffer roxy-buf + (set-visited-file-name rd-tmp-file) + (save-buffer) + (kill-buffer roxy-buf)) + (ess-force-buffer-current) + (ess-command "print(suppressWarnings(require(tools, quietly=TRUE)))\n") + (if visit-instead-of-browse + (progn + (ess-command (concat rd-to-html "\n")) + (find-file html-tmp-file)) + (ess-command (concat "browseURL(" rd-to-html ")\n"))))) + +(defun ess-roxy-preview-text () + "Use the connected R session and the roxygen package to +generate the text help page of the roxygen entry at point." + (interactive) + (with-current-buffer (ess-roxy-preview) + (Rd-preview-help))) + +(defun ess-roxy-preview-Rd (&optional name-file) + "Preview Rd for the roxygen entry at point. +Use the connected R session and the roxygen package to +generate the Rd code for the roxygen entry at point. If called +with a non-nil NAME-FILE (\\[universal-argument]), +also set the visited file name of the created buffer to +facilitate saving that file." + (interactive "P") + (let ((roxy-buf (ess-roxy-preview))) + (pop-to-buffer roxy-buf) + (if name-file + (save-excursion + (goto-char 1) + (search-forward-regexp "name{\\(.+\\)}") + (set-visited-file-name (concat (match-string 1) ".Rd")))) + (Rd-mode) + ;; why should the following be needed here? [[currently has no effect !!]] + ;; usually in a *.Rd file fontification happens automatically + (font-lock-ensure))) + + +(defun ess-roxy-guess-str (&optional not-here) + "Guess the prefix used in the current roxygen block. +If NOT-HERE is non-nil, guess the prefix for nearest roxygen +block before the point." + (save-excursion + (if (ess-roxy-entry-p) + (progn + (goto-char (line-beginning-position)) + (search-forward-regexp ess-roxy-re)) + (if not-here + (search-backward-regexp ess-roxy-re))) + (if (or not-here (ess-roxy-entry-p)) + (match-string 0) + (if (derived-mode-p 'ess-r-mode) + ess-roxy-str + (concat (string-trim comment-start) "'"))))) + +(defun ess-roxy-hide-block () + "Hide current roxygen comment block." + (interactive) + (save-excursion + (let ((end-of-entry (ess-roxy-end-of-entry)) + (beg-of-entry (ess-roxy-beg-of-entry))) + (hs-hide-block-at-point nil (list beg-of-entry end-of-entry))))) + +(defun ess-roxy-toggle-hiding () + "Toggle hiding/showing of a block. +See `hs-show-block' and `ess-roxy-hide-block'." + (interactive) + (hs-life-goes-on + (if (hs-overlay-at (line-end-position)) + (hs-show-block) + (ess-roxy-hide-block)))) + +(defun ess-roxy-show-all () + "Hide all Roxygen entries in current buffer." + (interactive) + (ess-roxy-hide-all t)) + +(defun ess-roxy-hide-all (&optional show) + "Hide all Roxygen entries in current buffer." + (interactive) + (when (not ess-roxy-hide-show-p) + (user-error "First enable hide-show with `ess-roxy-hide-show-p'")) + (hs-life-goes-on + (save-excursion + (goto-char (point-min)) + (while (re-search-forward (concat ess-roxy-re) (point-max) t 1) + (let ((end-of-entry (ess-roxy-end-of-entry))) + (if show + (hs-show-block) + (ess-roxy-hide-block)) + (goto-char end-of-entry) + (forward-line 1)))))) + +(defun ess-roxy-previous-entry () + "Go to beginning of previous Roxygen entry." + (interactive) + (if (ess-roxy-entry-p) + (progn + (goto-char (ess-roxy-beg-of-entry)) + (forward-line -1))) + (search-backward-regexp ess-roxy-re (point-min) t 1) + (goto-char (ess-roxy-beg-of-entry))) + +(defun ess-roxy-next-entry () + "Go to beginning of next Roxygen entry." + (interactive) + (if (ess-roxy-entry-p) + (progn + (goto-char (ess-roxy-end-of-entry)) + (forward-line 1))) + (search-forward-regexp ess-roxy-re (point-max) t 1) + (goto-char (ess-roxy-beg-of-entry))) + +(defun ess-roxy-get-function-args () + "Return the arguments specified for the current function as a list of strings. +Assumes point is at the beginning of the function." + (save-excursion + (let ((args-txt + (buffer-substring-no-properties + (progn + (search-forward-regexp "\\([=,-]+ *function *\\|^\s*function\\)" nil nil 1) + (+ (point) 1)) + (progn + (ess-roxy-match-paren) + (point))))) + (setq args-txt (replace-regexp-in-string "#+[^\"']*\n" "" args-txt)) + (setq args-txt (replace-regexp-in-string "([^)]+)" "" args-txt)) + (setq args-txt (replace-regexp-in-string "=[^,]+" "" args-txt)) + (setq args-txt (replace-regexp-in-string "[ \t\n]+" "" args-txt)) + (split-string args-txt ",")))) + +(defun ess-roxy-match-paren () + "Go to the matching parenthesis." + (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1)) + ((looking-at "\\s\)") (forward-char 1) (backward-list 1)))) + +(defun ess-roxy-complete-tag () + "Complete the tag at point." + (let ((bounds (ess-bounds-of-symbol))) + (when (and bounds + (save-excursion + (goto-char (car bounds)) + (eq (following-char) ?@))) + (list (1+ (car bounds)) (cdr bounds) + (append ess-roxy-tags-noparam ess-roxy-tags-param))))) + +(defun ess-roxy-tag-completion () + "Completion data for Emacs >= 24." + (when (save-excursion (re-search-backward "@\\<\\(\\w*\\)" (line-beginning-position) t)) + (let ((beg (match-beginning 1)) + (end (match-end 1))) + (when (and end (= end (point))) + (list beg end (append ess-roxy-tags-noparam ess-roxy-tags-param) :exclusive 'no))))) + +(defun ess-roxy-remove-roxy-re (string) + "Remove `ess-roxy-str' from STRING before sending to R process. +Useful for sending code from example section. This function is +placed in `ess-presend-filter-functions'." + ;; In the future we might want to detect chunks between markdown + ;; fences and strip everything that comes before `@examples` + (if (ess-roxy--all-prefixed string) + (replace-regexp-in-string (concat ess-roxy-re "\\s-*") "" string) + string)) + +(defun ess-roxy--all-prefixed (string) + (let ((ess-roxy-re-lexical ess-roxy-re)) + (with-temp-buffer + (insert string) + (goto-char 0) + (while (and (looking-at-p ess-roxy-re-lexical) + (re-search-forward "\n" nil t))) + (looking-at-p ess-roxy-re-lexical)))) + +(defun ess-roxy-find-par-end (stop-point &rest stoppers) + (mapc #'(lambda (stopper) + (when (and (> stop-point (point)) + (save-excursion + (re-search-forward stopper stop-point t))) + (setq stop-point (match-beginning 0)))) + stoppers) + (save-excursion + (goto-char stop-point) + (line-end-position 0))) + + +;;*;; Advices +(defmacro ess-roxy-with-filling-context (examples &rest body) + "Setup context (e.g. `comment-start') for filling roxygen BODY. +EXAMPLES should be non-nil if filling an example block." + (declare (indent 2) (debug (&rest form))) + `(let ((comment-start (concat ess-roxy-re "[ \t]+#")) + (comment-start-skip (concat ess-roxy-re "[ \t]+# *")) + (comment-use-syntax nil) + (adaptive-fill-first-line-regexp (concat ess-roxy-re "[ \t]*")) + (paragraph-start (concat "\\(" ess-roxy-re "\\(" paragraph-start + "\\|[ \t]*@" "\\)" "\\)\\|\\(" paragraph-start "\\)")) + (temp-table (if ,examples + (make-syntax-table ess-r-mode-syntax-table) + Rd-mode-syntax-table))) + (when ,examples + ;; Prevent the roxy prefix to be interpreted as comment or string + ;; starter + (modify-syntax-entry ?# "w" temp-table) + (modify-syntax-entry ?' "w" temp-table)) + ;; Neutralize (comment-normalize-vars) because it modifies the + ;; comment-start regexp in such a way that paragraph filling of + ;; comments in @examples fields does not work + (cl-letf (((symbol-function 'comment-normalize-vars) #'ignore)) + (with-syntax-table temp-table + ,@body)))) + +(defun ess-roxy-ess-indent-command (&optional whole-exp) + "Hide this block if we are at the beginning of the line. +Else call `ess-indent-command'." + (interactive "P") + (if (and (bolp) (ess-roxy-entry-p) ess-roxy-hide-show-p) + (progn (ess-roxy-toggle-hiding)) + (ess-indent-command whole-exp))) + +(defun ess--roxy-fill-block (fun &optional args) + "Fill a roxygen block. +FUN should be a filling function and ARGS gets passed to it." + (let* ((saved-pos (point)) + (par-start (save-excursion + (if (save-excursion + (and (backward-paragraph) + (forward-paragraph) + (<= (point) saved-pos))) + (line-beginning-position) + (progn (backward-paragraph) (point))))) + (par-end (ess-roxy-find-par-end + (save-excursion + (forward-paragraph) + (point)) + (concat ess-roxy-re "[ \t]*@examples\\b") "^[^#]"))) + ;; Refill the whole structural paragraph sequentially, field by + ;; field, stopping at @examples + (ess-roxy-with-filling-context nil + (save-excursion + (save-restriction + (narrow-to-region par-start par-end) + (goto-char (point-min)) + (while (< (point) (point-max)) + (ess-roxy-maybe-indent-line) + (apply fun args) + (forward-paragraph))))))) + +(defun ess-r--fill-paragraph (orig-fun &rest args) + "ESS fill paragraph for R mode. +Overrides `fill-paragraph' which is ORIG-FUN when necessary and +passes ARGS to it." + (cond + ;; Regular case + ((not (derived-mode-p 'ess-r-mode)) + (apply orig-fun args)) + ;; Filling of code comments in @examples roxy field + ((and (ess-roxy-entry-p) + (save-excursion + (ess-roxy-goto-end-of-roxy-comment) + (looking-at "#"))) + (ess-roxy-with-filling-context t + (apply orig-fun args))) + ((and (not (ess-roxy-entry-p)) + (ess-inside-comment-p)) + (apply orig-fun args)) + ;; Filling of call arguments with point on call name + ((and ess-fill-calls + (ess-inside-call-name-p)) + (save-excursion + (skip-chars-forward "^([") + (forward-char) + (ess-fill-args))) + ;; Filling of continuations + ((and ess-fill-continuations + (ess-inside-continuation-p)) + (ess-fill-continuations)) + ;; Filling of call arguments + ((and ess-fill-calls + (ess-inside-call-p)) + (ess-fill-args)) + ;; Filling of roxy blocks + ((ess-roxy-entry-p) + (ess--roxy-fill-block orig-fun args)) + (t + (apply orig-fun args)))) +(advice-add 'fill-paragraph :around #'ess-r--fill-paragraph) + +(defun ess-roxy-move-beginning-of-line (arg) + "Move point to the beginning of the current line or roxygen comment. +If not in a roxygen comment, call `move-beginning-of-line', which +see for ARG. If in a roxygen field, leave point at the end of a +roxygen comment. If already there, move to the beginning of the +line." + (interactive "^p") + (if (ess-roxy-entry-p) + (let ((pos (point))) + (ess-roxy-goto-end-of-roxy-comment) + (when (eql (point) pos) + (move-beginning-of-line nil))) + (move-beginning-of-line arg))) + +(defun ess-roxy-goto-end-of-roxy-comment () + "Leave point at the end of a roxygen comment. +If not in a roxygen entry, call `back-to-indentation'." + (interactive) + (if (ess-roxy-entry-p) + (progn + (end-of-line) + (re-search-backward (concat ess-roxy-re " *") + (line-beginning-position) t) + (goto-char (match-end 0))) + (back-to-indentation))) + +(defun ess-roxy-indent-new-comment-line () + (if (not (ess-roxy-entry-p)) + (indent-new-comment-line) + (ess-roxy-indent-on-newline))) + +(define-obsolete-function-alias 'ess-roxy-newline-and-indent + #'ess-roxy-newline "ESS 19.04") +(defun ess-roxy-newline () + "Start a newline and insert the roxygen prefix. +Only do this if in a roxygen block and +`ess-roxy-insert-prefix-on-newline' is non-nil." + (interactive) + (if (and (ess-roxy-entry-p) + ess-roxy-insert-prefix-on-newline) + (ess-roxy-indent-on-newline) + (newline nil t))) + +(defun ess-roxy-indent-on-newline () + "Insert a newline in a roxygen field." + (cond + ;; Point at beginning of first line of entry; do nothing + ((= (point) (ess-roxy-beg-of-entry)) + (newline-and-indent)) + ;; Otherwise: skip over roxy comment string if necessary and then + ;; newline and then inset new roxy comment string + (t + (let ((point-after-roxy-string + (save-excursion (forward-line 0) + (ess-back-to-roxy) + (point)))) + (goto-char (max (point) point-after-roxy-string))) + (newline-and-indent) + (insert (concat (ess-roxy-guess-str t) " "))))) + +(defun ess-roxy-cpp-fill-paragraph (&rest _args) + "Advice for `c-fill-paragraph' that accounts for roxygen comments." + (cond + ;; Fill roxy @example's. + ((ess-roxy-entry-p "examples") + (ess--roxy-fill-block 'fill-paragraph) nil) + ;; Fill roxy entries. + ((ess-roxy-entry-p) + (ess--roxy-fill-block 'fill-paragraph) nil) + ;; Return t to signal to go on to `c-fill-paragraph'. + (t t))) + +(advice-add 'c-fill-paragraph :before-while #'ess-roxy-cpp-fill-paragraph) + +(defun ess-roxy-enable-in-cpp () + "Enable `ess-roxy-mode' in C++ buffers in R packages." + (when (and (fboundp 'ess-r-package-project) + (ess-r-package-project)) + (ess-roxy-mode))) + +(with-eval-after-load "cc-mode" + (add-hook 'c++-mode-hook #'ess-roxy-enable-in-cpp)) + +(defun ess-roxy--region-p (beg end) + (when ess-roxy-re + (save-excursion + (goto-char beg) + (catch 'ess-r-not-roxy + (while (< (point) end) + (unless (looking-at-p ess-roxy-re) + (throw 'ess-r-not-roxy nil)) + (forward-line)) + t)))) + +(provide 'ess-roxy) + +;;; ess-roxy.el ends here diff --git a/elpa/ess-20230419.1527/ess-s-lang.el b/elpa/ess-20230419.1527/ess-s-lang.el new file mode 100644 index 00000000..c02f9607 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-s-lang.el @@ -0,0 +1,526 @@ +;;; ess-s-lang.el --- Support for editing S source code -*- lexical-binding: t; -*- + +;; Copyright (C) 1989-2022 Free Software Foundation, Inc. +;; Author: A.J. Rossini +;; Created: 26 Aug 1997 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Code for general editing S source code (specializes to S, S+, R). + +;;; Code: + +(require 'ess-mode) +(require 'ess-help) +(require 'ess-inf) + +(declare-function speedbar-add-supported-extension "speedbar" (extension)) + + ; Configuration variables + +(defvar S-syntax-table + (let ((S-syntax-table (make-syntax-table))) + (modify-syntax-entry ?\\ "\\" S-syntax-table) + (modify-syntax-entry ?+ "." S-syntax-table) + (modify-syntax-entry ?- "." S-syntax-table) + (modify-syntax-entry ?= "." S-syntax-table) + (modify-syntax-entry ?% "." S-syntax-table) + (modify-syntax-entry ?< "." S-syntax-table) + (modify-syntax-entry ?> "." S-syntax-table) + (modify-syntax-entry ?& "." S-syntax-table) + (modify-syntax-entry ?| "." S-syntax-table) + (modify-syntax-entry ?\' "\"" S-syntax-table) + (modify-syntax-entry ?\" "\"" S-syntax-table) + (modify-syntax-entry ?# "<" S-syntax-table) ; open comment + (modify-syntax-entry ?\n ">" S-syntax-table) ; close comment + ;;(modify-syntax-entry ?. "w" S-syntax-table) ; "." used in S obj names + (modify-syntax-entry ?. "_" S-syntax-table) ; see above/below, + ; plus consider separation. + (modify-syntax-entry ?$ "_" S-syntax-table); foo$comp = 1 symbol(completion) + (modify-syntax-entry ?@ "_" S-syntax-table); foo@slot = 1 symbol(completion) + (modify-syntax-entry ?_ "_" S-syntax-table) + (modify-syntax-entry ?: "_" S-syntax-table) + (modify-syntax-entry ?* "." S-syntax-table) + (modify-syntax-entry ?< "." S-syntax-table) + (modify-syntax-entry ?> "." S-syntax-table) + (modify-syntax-entry ?/ "." S-syntax-table) + S-syntax-table) + "Syntax table for S code." + ) + +(defvar S-editing-alist + '((paragraph-start . (concat "\\s-*$\\|" page-delimiter)) + (paragraph-separate . (concat "\\s-*$\\|" page-delimiter)) + (paragraph-ignore-fill-prefix . t) + ;;(comment-indent-function . 'S-comment-indent) + ;;(ess-comment-indent . 'S-comment-indent) + ;;(ess-calculate-indent . 'ess-calculate-indent) + ;;(ess-keep-dump-files . 'ask) + ;; For Changelog add, require ' ' before <- : "attr<-" is a function name : + (add-log-current-defun-header-regexp . "^\\(.+\\)\\s-+<-[ \t\n]*function")) + "General options for S and S+ source files.") + +(defvar inferior-S-language-start + '(concat "options(" + "STERM='" ess-STERM "'" + ", str.dendrogram.last=\"'\"" + (if ess-editor (concat ", editor='" ess-editor "'")) + (if ess-pager (concat ", pager='" ess-pager "', help.pager='" ess-pager "'")) + ", show.error.locations=TRUE" + ")") + "S language expression for startup -- default for all S dialects.") + +(defconst S-common-cust-alist + '((ess-language . "S") + (inferior-ess-exit-command . "q()\n") + (inferior-ess-language-start . (eval inferior-S-language-start)) + (comint-use-prompt-regexp . t) ;;use fields if nil + (comint-process-echoes . t) + ;; these prompt are the same for all S-languages As long as custom prompt + ;; ends in inferior-ess-primary-prompt everything should work as expected. + (inferior-ess-primary-prompt . "> ") + ;; (inferior-ess-secondary-prompt . "[+:] ") ;; catch Selection: and alike + (inferior-ess-secondary-prompt . "+ ") ;; catch Selection: and alike + (comment-start . "#") + (comment-add . 1) + (comment-start-skip . "#+ *") + (comment-use-syntax . t) ; see log for bug report 2013-06-07 + (comment-column . 40) + (ess-no-skip-regexp . (concat "^ *@\\|" (default-value 'ess-no-skip-regexp))) + ;; inferior-ess-prompt is used by comint for navigation, only if + ;; comint-use-prompt-regexp is t; (transcript-mode also relies on this regexp) + (inferior-ess-prompt . inferior-S-prompt) + (ess-getwd-command . "getwd()\n") + (ess-setwd-command . "setwd('%s')\n") + (ess-funargs-command . ".ess_funargs(\"%s\")\n") + (fill-nobreak-predicate . 'ess-inside-string-p) + (ess-execute-screen-options-command . "options(width=%d, length=99999)\n") + (font-lock-defaults . '(ess-build-font-lock-keywords + nil nil ((?\. . "w") (?\_ . "w"))))) + "S-language common settings for all -customize-alist.") + +(defconst S+common-cust-alist + (append + '((ess-suffix . "S") + (ess-help-sec-regex . ess-help-S+-sec-regex) + (ess-help-sec-keys-alist . ess-help-S+sec-keys-alist) + (ess-change-sp-regexp . ess-S+-change-sp-regexp) + (ess-function-pattern . ess-s-function-pattern) + (ess-function-template . " <- \n#\nfunction()\n{\n\n}\n") + (ess-dump-filename-template . (replace-regexp-in-string + "S$" ess-suffix ; in the one from custom: + ess-dump-filename-template-proto)) + (ess-traceback-command . "traceback()\n") + (ess-mode-editing-alist . S-editing-alist) + + (ess-dumped-missing-re + . "\\(\\(<-\\|=\\)\nDumped\n\\'\\)\\|\\(\\(<-\\|=\\)\\(\\s \\|\n\\)*\\'\\)") + (ess-syntax-error-re + . "\\(Syntax error: .*\\) at line \\([0-9]*\\), file \\(.*\\)$") + (inferior-ess-objects-command . inferior-Splus-objects-command) + (ess-describe-object-at-point-commands . 'ess-S-describe-object-at-point-commands) + (ess-editor . S-editor) + (ess-pager . S-pager)) + S-common-cust-alist) + "Common settings for all S+<*>-customize-alist." + ) + +;;; Changes from S to S-PLUS 3.x. (standard S3 should be in ess-s-lang!). + +(defconst ess-help-S+sec-keys-alist + '((?a . "ARGUMENTS:") + (?b . "BACKGROUND:") + (?B . "BUGS:") + (?d . "DESCRIPTION:") + (?D . "DETAILS:") + (?e . "EXAMPLES:") + (?n . "NOTE:") + (?O . "OPTIONAL ARGUMENTS:") + (?R . "REQUIRED ARGUMENTS:") + (?r . "REFERENCES:") + (?s . "SEE ALSO:") + (?S . "SIDE EFFECTS:") + (?u . "USAGE:") + (?v . "VALUE:")) + "Alist of (key . string) pairs for use in section searching.") +;;; `key' indicates the keystroke to use to search for the section heading +;;; `string' in an S help file. `string' is used as part of a +;;; regexp-search, and so specials should be quoted. + +;; S ver.3 (NOT S-Plus) +(defconst ess-help-S3-sec-keys-alist + '((?a . "ARGUMENTS:") + (?b . "BACKGROUND:") + (?B . "BUGS:") + (?d . "DESCRIPTION:") + (?D . "DETAILS:") + (?e . "EXAMPLES:") + (?n . "NOTE:") + (?r . "REFERENCES:") + (?s . "SEE ALSO:") + (?S . "SIDE EFFECTS:") + (?u . "USAGE:") + (?v . "VALUE:")) + "Help section keys for S ver.3.") + +;; S ver.4 (NOT S-Plus) +(defconst ess-help-S4-sec-keys-alist + '((?a . "ARGUMENTS:") + (?b . "BACKGROUND:") + (?B . "BUGS:") + (?d . "DESCRIPTION:") + (?D . "DETAILS:") + (?e . "EXAMPLES:") + (?n . "NOTE:") + (?r . "REFERENCES:") + (?s . "SEE ALSO:") + (?S . "SIDE EFFECTS:") + (?u . "USAGE:") + (?v . "VALUE:")) + "Help section keys for S4.") + + +(defconst ess-help-S+-sec-regex "^[A-Z.]+:$" + "Reg(ular) Ex(pression) of section headers in help file.") + + ; Function Definitions + +(defun S-comment-indent () + "Indentation for S comments." + (if (or (looking-at "###") + (and (looking-at "#!") (= 1 (line-number-at-pos)))) + (current-column) + (if (looking-at "##") + (let ((tem (when ;; FIXME ess-calculate-indent is R specific + (fboundp 'ess-calculate-indent) + (ess-calculate-indent)))) + (if (listp tem) (car tem) tem)) + (skip-chars-backward " \t") + (max (if (bolp) 0 (1+ (current-column))) + comment-column)))) + +;;*;; S/R Pretty-Editing + +(defun ess-fix-comments (&optional dont-query verbose) + "Fix buffer so that single-line comments start with at least '##', +and ensure space before subsequent text." + (interactive "P") + (ess-replace-regexp-dump-to-src "#\\([A-Za-z0-9]\\)" "# \\1" nil verbose) + (ess-replace-regexp-dump-to-src "^\\([ \t]*#\\)\\([^#]\\)" + "\\1#\\2" dont-query verbose)) + +(defun ess-dump-to-src (&optional dont-query verbose) + "Make the change in an S - dump() file to improve human readability. +Optional arguments DONT-QUERY and VERBOSE are passed to +`ess-replace-regexp-dump-to-src'." + (interactive "P") + (ess-replace-regexp-dump-to-src "^\"\\([a-z.][a-z.0-9]*\\)\" *<-\n" + "\n\\1 <- " + dont-query verbose)) + +(defun ess-num-var-round (&optional dont-query verbose) + "Round endings like 000000 and 99999. +Optional argument DONT-QUERY means do not query. +Optional argument VERBOSE gives more verbose output." + (interactive "P") + (save-excursion + (goto-char (point-min)) + (let ((num 0) + (str "") + (rgxp "000000+[1-9]?[1-9]?\\>") + (to "")) + (if dont-query + (ess-rep-regexp rgxp to nil nil verbose) + (query-replace-regexp rgxp to nil)) + (while (< num 9) + (setq str (concat (int-to-string num) "999999+[0-8]*")) + (if (and (numberp verbose) (> verbose 1)) + (message (format "\nregexp: '%s'" str))) + (goto-char (point-min)) + (ess-rep-regexp str (int-to-string (1+ num)) + 'fixedcase 'literal verbose) + (setq num (1+ num)))))) + +(defun ess-fix-dot (before-chars &optional dont-query verbose) + "Remove trailing decimal '.' (\"dot\"), before BEFORE-CHARS. +Optional argument DONT-QUERY and VERBOSE get passed to +`ess-replace-regexp-dump-to-src'." + ;; typically, before-chars = "]:" or more + (ess-replace-regexp-dump-to-src + (concat "\\([0-9]\\)\\.\\( *[" before-chars "]\\)") + ;; 111 ^ + "\\1\\2" dont-query verbose)) + +(defun ess-fix-dot-1 (&optional do-query verbose) + "Remove trailing decimal '.' (\"dot\"), before ':' or ']', i.e., +in cases where it's ugly and nonsense. DO-QUERY(prefix) asks before replacing." + (interactive "P") + (ess-fix-dot "]:" (not do-query) verbose)) + +(defun ess-fix-dot-more (&optional dont-query verbose) + "Remove trailing decimal '.' (\"dot\", typically from S+) in more cases +than `ess-fix-dot-1'." + (interactive "P") + (ess-fix-dot-1 nil verbose) + (ess-fix-dot ",)" dont-query verbose)) + +(defun ess-fix-EQ-assign (&optional dont-query verbose not-all) + "Replace \"=\" by \"<-\" in places where it `might make sense', e.g., +for function assignments and lines not ending in \",\". +Be *careful* for list()s of functions and when argument not-all is +nil (as by default) !" + ;;TODO: "in the few places we can be very sure.." + ;;---- is hard in general: local functions: ok; but functions in + ;; list(a = function(x) abs(x), b= function(y) bound(y)) *NOT* ok! + (interactive "P") + (ess-replace-regexp-dump-to-src + "^\\( *[a-z.][_a-z.0-9]*\\) *= *\\(function *(\\)" + "\\1 <- \\2" dont-query verbose) + (unless not-all + ;; "too" aggressive {proposing to replace function argument specs}: + (ess-replace-regexp-dump-to-src ;; all those *not* ending in "," + ;; including Mat[ i, ] = ..., + ;; but not `names(x) = "..."' for that is "confused" with plot(x=x,..) + "^\\( *[a-z.][][, \"_a-z.0-9]*\\) *= *\\([a-z.0-9({]\\(.*[^,]\\)? *$\\)" + "\\1 <- \\2" nil ;; always query - often has many "false positives" + verbose))) + +;;; All of the above three : +(defun ess-MM-fix-src (&optional dont-query verbose) + "Clean up ess-source code which has been produced by dump(..), and other +code typically produced by other tools. Produces more readable code, +and one that is well formatted in Emacs ess-mode." + (interactive "P") + ;; each of the following does a save-excursion: + (ess-dump-to-src dont-query) + (ess-fix-comments dont-query) + (ess-num-var-round dont-query verbose) + (ess-fix-dot-more dont-query verbose) + (ess-fix-EQ-assign dont-query verbose 'not-all)) + +(defun ess-fix-miscellaneous (&optional from verbose) + "Fix Miscellaneous S/R `ill-formation's from current \\[point]. +Particularly use \"<-\"and put spaces around operators." + (interactive "d\nP"); Defaults: point and prefix (C-u) + ;; activate by (setq ess-verbose t) + (ess-if-verbose-write + (format "ess-fix-misc begin (from = %s, verbose = %s)\n" from verbose)) + (save-excursion + + (when (and (string= ess-dialect "R") + (fboundp 'ess-r-fix-T-F)) + (ess-r-fix-T-F from (not verbose))) + + ;; activate by (setq ess-verbose t) + (ess-if-verbose-write "ess-fix-misc: after fix-T-F\n");___D___ + + ;; former C and matlab programmers leave trailing ";" : + ;; (goto-char from) (ess-rep-regexp "; *$" "" nil 'literal verbose) + ;; (ess-if-verbose-write "ess-fix-misc: after trailing ';'\n");___D___ + (goto-char from) (ess-rep-regexp ";\\( *\\)#" "\\1#" nil nil verbose) + (ess-if-verbose-write "ess-fix-misc: after ';' before #\n");___D___ + + ;;from R 1.9.x "_" is valid in names; here assume no initial / trailing '_' + ;; BUG: The following changes "beta_ " or " _abc" + ;; (goto-char from) (ess-rep-regexp " +_ *" " <- " nil 'literal verbose) + ;; (goto-char from) (ess-rep-regexp "_ +" " <- " nil 'literal verbose) + + (ess-if-verbose-write "ess-fix-misc: before 'around \"<-\"' :\n");___D___ + ;; ensure space around "<-" ---- but only replace if necessary: + (goto-char from) + (ess-rep-regexp "\\([^< \t\n]\\)\\(<" (not ">=") : + (goto-char from);; --> " <", care with "->": + (ess-rep-regexp "\\([^-< \t\n]\\)\\([<>]\\)" "\\1 \\2" nil nil verbose) + ;; ">" -> "> " , for "<", don't split "<-" nor "<<-": + (goto-char from) + (ess-rep-regexp "\\(>=?\\)\\([^= \t\n]\\)" "\\1 \\2" nil nil verbose) + (goto-char from) + (ess-rep-regexp "\\(<=?\\)\\([^-<= \t\n]\\)" "\\1 \\2" nil nil t) + + (ess-if-verbose-write "ess-fix-misc: before \"=\" \"==\" .. :\n");___D___ + ;; -- ensure space around "=", "==", "!=" : + (goto-char from) ;; --> " =" + (ess-rep-regexp "\\([^=!<> ]\\)\\([=!]?\\)=" "\\1 \\2=" nil nil verbose) + (goto-char from) (ess-rep-regexp "=\\([^= ]\\)" "= \\1" nil nil verbose) + + (goto-char from) ;; add a space between "{" and surrounding ..char: + (ess-rep-regexp "{\\([.A-Za-z()]\\)" "{ \\1" 'fix nil verbose) + (ess-rep-regexp "\\([()]\\){" "\\1 {" 'fix nil verbose) + (goto-char from) ;; add a space between "}" and a preceding wordchar: + (ess-rep-regexp "\\([A-Za-z0-9()]\\)}" "\\1 }" 'fix nil verbose) + (ess-space-around "else" from verbose) + + (ess-if-verbose-write "ess-fix-misc: after \"{ ... }\" :\n");___D___ + (goto-char from) ;; add a space inside "){" + (ess-rep-regexp "){" ") {" 'fix nil verbose) + + ;; add a newline and indent before a "}" + ;; --- IFF there's NO "{" or "#" AND some NON-white text on the same line: + ;;D (if verbose (message "\t R-fix-misc..: Hard.. '}'")) + (goto-char from) + (ess-rep-regexp "^\\([^#{\n]*[^#{ \t\n]+[ \t]*\\)}[ \t]*$" + "\\1\n}" 'fix nil verbose) + (ess-if-verbose-write "ess-fix-misc __end__\n");___D___ + )) + +(defun ess-cycle-assign () + "Cycle between assignment symbols in `ess-assign-list'. +On consecutive calls, replace the assignment symbol before point +with the next symbol from that list. This function sets the last +keypress to repeat it, so if it is bound to \"C-c C-=\" pressing +\"=\" again cycles to the next assignment." + (interactive) + (if (eq last-command this-command) + (let ((slist ess-assign-list) + str) + ;; The or statements in the setq allow cycling past the end of + ;; ess-assign-list. + (while (and (setq str (or (car slist) (car ess-assign-list)) + slist (or (cdr slist) ess-assign-list)) + (not (and (re-search-backward str + (- (point) (length str)) t) + (not (replace-match (car slist)))))))) + (delete-horizontal-space) + (insert (car ess-assign-list))) + (set-transient-map + (let ((map (make-sparse-keymap)) + (key (format "%c" (event-basic-type last-input-event)))) + (define-key map (kbd key) #'ess-cycle-assign) + map))) + +(defun ess-insert-assign (arg) + "Insert the first element of `ess-assign-list' unless in string or comment. +If the character before point is the first element of +`ess-assign-list', replace it with the last character typed. + +If `ess-language' is not \"S\", call `self-insert-command' with ARG." + (interactive "p") + (if (string= ess-language "S") + (let* ((assign (car ess-assign-list)) + (event (event-basic-type last-input-event)) + (char (ignore-errors (format "%c" event)))) + (cond ((and char (ess-inside-string-or-comment-p)) + (insert char)) + ((re-search-backward assign (- (point) (length assign)) t) + (if (and char (numberp event)) + (replace-match char t t) + (replace-match ""))) + (t (delete-horizontal-space) + (insert assign)))) + (funcall #'self-insert-command arg))) + +;; In case people had this in their config don't cause errors: +(define-obsolete-function-alias 'ess-smart-S-assign #'ess-insert-assign "ESS 18.10") +(define-obsolete-function-alias 'ess-disable-smart-S-assign #'ignore "ESS 18.10") + +(defun ess-add-MM-keys () + "Define MM's user keys." + (declare (obsolete "Setup your own keybindings." "ESS 19.04")) + (define-key inferior-ess-mode-map "\C-cw" #'ess-execute-screen-options) + (define-key ess-mode-map [?\M--] #'ess-insert-assign) + (define-key inferior-ess-mode-map [?\M--] #'ess-insert-assign)) + +(defun ess-dump-args-and-go (Sfunc) + "Dump the function name, with arguments, to a buffer for editing. + +Currently, this needs to: + 1. set the buffer to the right mode, with the right settings + 2. format the statement, + 3. c/function/Sfunc/ +and I need to relearn Emacs lisp (but I had to, anyway." + (declare (obsolete 'ess-execute "ESS 19.04")) + (interactive "sFunction ? ") + (let* ((buffname "ess-complete.R")) + (ess-execute (format "args(%s)" Sfunc) t buffname) + (pop-to-buffer (concat "*" buffname "*")) + (while (search-forward "function" nil t) + (replace-match Sfunc nil t)) + (when (fboundp 'ess-r-mode) + (ess-r-mode)))) + +;;; S imenu support + +;; don't use syntax classes, bad for etags +(defvar ess-imenu-S-generic-expression + '(("Functions" "^\\([^ \t\n]+\\)[ \t\n]*\\(?:<-\\|=\\)[ \t\n]*function[ ]*(" 1) + ("Classes" "^.*setClass(\\(.*\\)," 1) + ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to + ("Generics" "^.*setGeneric(\\([^,]*\\)," 1) + ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\\([^,]+,[^,]*\\)" 2) + ("Package" "^.*\\(library\\|require\\)(\\([^)]*\\)" 2) + ("Data" "^\\(.+\\)[ \t\n]-*\\(?:<-\\|=\\)[ \t\n]*\\(read\\|.*data\\.frame\\).*(" 1)) + "Imenu generic expression for S modes. +See `imenu-generic-expression'.") + +(defun ess-imenu-S (&optional _arg) + "S Language Imenu support for ESS. +ARG is ignored." + (declare (obsolete "It is set automatically in major modes" "ESS 19.04")) + (imenu-add-to-menubar "Imenu-S")) + + + ;;; Speedbar stuff. + +(eval-after-load "speedbar" + '(progn + (speedbar-add-supported-extension ".R") + (speedbar-add-supported-extension ".S") + (speedbar-add-supported-extension ".s") + (speedbar-add-supported-extension ".q"))) + +(cl-defmethod ess-help-get-topics (proc &context (ess-dialect "R")) + "Return a list of current S help topics associated with process PROC. +If `sp-for-help-changed?' process variable is non-nil or +`ess-help-topics-list' is nil, (re)-populate the latter and +return it. Otherwise, return `ess-help-topics-list'." + (with-ess-process-buffer nil + (cond + ;; (Re)generate the list of topics + ((or (not ess-help-topics-list) + (ess-process-get 'sp-for-help-changed?)) + (ess-process-put 'sp-for-help-changed? nil) + (setq ess-help-topics-list + (delete-dups + (append (ess-get-object-list proc 'exclude-1st) + (ess-get-help-files-list) + (ess-get-help-aliases-list))))) + (t + ess-help-topics-list)))) + +(cl-defmethod ess-help--reset-cache-override (&context (ess-dialect "R")) + (ess-command ".ess.getHelpAliases(reset = TRUE)\n" + nil nil nil nil nil nil ess-help--aliases-timeout)) + +(define-obsolete-function-alias 'ess-toggle-S-assign-key #'ignore "ESS 18.10") +(define-obsolete-function-alias 'ess-smart-underscore #'ess-insert-assign "ESS 18.10") +(define-obsolete-function-alias 'ess-insert-S-assign #'ess-insert-assign "ESS 18.10") + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Ss]t\\'" . S-transcript-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.Sout\\'" . S-transcript-mode)) + +(provide 'ess-s-lang) + +;;; ess-s-lang.el ends here diff --git a/elpa/ess-20230419.1527/ess-sas-a.el b/elpa/ess-20230419.1527/ess-sas-a.el new file mode 100644 index 00000000..3dfd1554 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-sas-a.el @@ -0,0 +1,1441 @@ +;;; ess-sas-a.el --- clean-room implementation of many SAS-mode features -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: Rodney A. Sparapani +;; Maintainer: ESS-core@r-project.org +;; Created: 17 November 1999 +;; Keywords: languages + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Code: + +(require 'ess-mode) +(require 'ess-utils) +;; Silence the byte compiler +;; FIXME: This is a lot, perhaps they can be moved? +(defvar sas-indent-width) +(defvar SAS-customize-alist) +(defvar sas-mode-local-map) +(declare-function ess-num-or-zero "ess-sas-d") +;; FIXME: What is this doing here??? +(declare-function ess-add-ess-process "essd-els") +(declare-function ess-listing-minor-mode "ess-sas-l") +;;; Table of Contents +;;; Section 1: Variable Definitions +;;; Section 2: Function Definitions +;;; Section 3: Key Definitions + +;;; Section 1: Variable Definitions + +(defvar ess-sas-file-path "." + "Full path-name of the sas file to perform operations on.") + +(defcustom ess-sas-data-view-libname " " + "SAS code to define a library for `ess-sas-data-view-fsview' +or `ess-sas-data-view-insight'." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-data-view-submit-options + (if ess-microsoft-p "-noenhancededitor -nosysin -log NUL:" + "-nodms -nosysin -log /dev/null -terminal") + "The command-line options necessary for your OS with respect to +`ess-sas-data-view-fsview' and `ess-sas-data-view-insight'." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-data-view-fsview-command "; proc fsview data=" + "SAS code to open a SAS dataset with `ess-sas-data-view-fsview'." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-data-view-fsview-statement " " + "SAS code to perform a PROC FSVIEW statement with `ess-sas-data-view-fsview'." + :group 'ess-sas + :type 'string) + + +(make-variable-buffer-local 'ess-sas-data-view-fsview-statement) + +(defcustom ess-sas-data-view-insight-command "; proc insight data=" + "SAS code to open a SAS dataset with `ess-sas-data-view-insight'." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-data-view-insight-statement " " + "SAS code to perform a PROC FSVIEW statement with `ess-sas-data-view-insight'." + :group 'ess-sas + :type 'string) + +(make-variable-buffer-local 'ess-sas-data-view-insight-statement) + +(defcustom ess-sas-graph-view-suffix-regexp + "[.]\\([eE]?[pP][sS]\\|[pP][dD][fF]\\|[gG][iI][fF]\\|[jJ][pP][eE]?[gG]\\|[tT][iI][fF][fF]?\\|[pP][nN][gG]\\)" + "GSASFILE suffix regexp." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-graph-view-viewer-alist + ;;creates something like + ;;'(("[pP][dD][fF]" . "/usr/local/bin/acroread") ("[eE]?[pP][sS]" . "/usr/local/bin/gv"))) + (let ((ess-tmp-ps nil) (ess-tmp-pdf nil)) + (setq ess-tmp-ps (executable-find (if ess-microsoft-p "gsview32" "gsview"))) + (if (not ess-tmp-ps) (setq ess-tmp-ps (executable-find "gv"))) + (if (not ess-tmp-ps) (setq ess-tmp-ps (executable-find "ghostview"))) + (setq ess-tmp-pdf (executable-find "evince")) + (if (not ess-tmp-pdf) (setq ess-tmp-pdf (executable-find "xpdf"))) + (if (not ess-tmp-pdf) (setq ess-tmp-pdf (if ess-microsoft-p "acrord32" "acroread")))) + + "Associate file name extensions with graphics image file viewers." + :group 'ess-sas + :type '(choice (const nil) (alist))) + +(defcustom ess-sas-log-max 0 + "If >0 and .log file exceeds this many bytes, just \"refresh\" this many bytes." + :group 'ess-sas + :type 'integer) + +(defcustom ess-sas-rtf-font-name "Courier" ; "Bitstream Vera Sans Mono" + "Name of font with which to create MS RTF." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-shell-buffer "*shell*" + "Name that you want to use for the shell buffer; buffer-local." + :group 'ess-sas + :type 'string) + +(make-variable-buffer-local 'ess-sas-shell-buffer) + +(defcustom ess-sas-shell-buffer-remote-host nil + "Remote host that you want to open a shell on." + :group 'ess-sas + :type '(choice (const nil) string)) + +(make-variable-buffer-local 'ess-sas-shell-buffer-remote-host) + +(defcustom ess-sas-shell-buffer-remote-init "ssh" + "Command to open a shell on a remote host." + :group 'ess-sas + :type 'string) + +(make-variable-buffer-local 'ess-sas-shell-buffer-remote-init) + +(defcustom ess-sas-submit-mac-virtual-pc nil + "Non-nil means that you want to run Windows SAS in a +Virtual PC emulator on your Mac; buffer-local." + :group 'ess-sas + :type 'boolean) + +(make-variable-buffer-local 'ess-sas-submit-mac-virtual-pc) + +(defcustom sas-program "sas" + "Command to invoke SAS, default for buffer-local `ess-sas-submit-command'." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-submit-command sas-program + "Command to invoke SAS in batch; buffer-local." + :group 'ess-sas + :type 'string) + +(make-variable-buffer-local 'ess-sas-submit-command) + +(defcustom ess-sas-submit-command-options "-rsasuser" + "Options to pass to SAS in batch; buffer-local." + :group 'ess-sas + :type 'string) + +(make-variable-buffer-local 'ess-sas-submit-command-options) + +(defvar-local ess-sas-submit-method + (if (and (and ess-microsoft-p + (fboundp 'w32-shell-dos-semantics)) + (w32-shell-dos-semantics)) + 'ms-dos 'sh) + "Method used by `ess-sas-submit'. +The default is based on the value of the emacs variable `system-type' +and, on Windows, the function `w32-shell-dos-semantics'. +\\='sh if *shell* runs sh, ksh, csh, tcsh or bash +\\='ms-dos if *shell* follows MS-DOS semantics + +Unix users will get \\='sh by default. + +Windows users running bash in *shell* will get \\='sh by default. + +Windows users running MS-DOS in *shell* will get \\='ms-dos by default. + +Users accessing a remote machine with `telnet', `rlogin', `ssh', etc., +should set this variable to \\='sh regardless of their local shell +(since their remote shell is \\='sh).") + +(defcustom ess-sas-graph-view-viewer-default + (if ess-microsoft-p "explorer" + (if (equal ess-sas-submit-method 'sh) "sdtimage")) + "Default graphics image file viewer." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-submit-post-command + (if (equal ess-sas-submit-method 'sh) "&" + (if ess-microsoft-p "-icon")) + "Command-line statement to post-modify SAS invocation." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-submit-pre-command ;;"nohup" + (if (equal ess-sas-submit-method 'sh) + ;; nice is tricky, higher numbers give you lower priorities + ;; if you are using csh/tcsh, the default priority is 4 + ;; if you are using most other shells, the default priority is 10, + ;; and some implementations are higher, i.e. zsh unless you + ;; specify "setopt no_bg_nice" in your ~/.zshrc + ;; therefore, on the same machine, you can run at a higher or + ;; lower priority by changing shells, although, the command + ;; line is the same! + ;; the following code should give you a priority of 10 regardless + ;; of which shell is in use, but it will default to the old + ;; behavior if csh or variant is not recognized + ;; this should avoid the necessity of each user needing to set this + ;; variable correctly based on the shell that they use and provide + ;; an environment where all shells are treated equally + + (let* ((temp-shell (getenv "SHELL")) + ;; AJR: old CYGWIN versions return nil for (getenv + ;; "SHELL"), so we need to deal with it 'cause I have to + (temp-char (if temp-shell + (string-match "/" temp-shell) + nil))) + (while temp-char + (setq temp-shell (substring temp-shell (+ 1 temp-char))) + (setq temp-char (string-match "/" temp-shell))) + + (cond ((or (equal temp-shell "csh") (equal temp-shell "tcsh")) + "nohup nice +6") + (t "nohup nice"))) + (if ess-microsoft-p "start")) + "Command-line statement to precede SAS invocation, e.g. start or nohup." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-suffix-1 "txt" + "The first suffix to associate with SAS." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-suffix-2 "csv" + "The second suffix to associate with SAS." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-suffix-regexp + (concat "[.]\\([sS][aA][sS]\\|[lL][oO][gG]\\|[lL][sS][tT]" + (if ess-sas-suffix-1 (concat + "\\|" (downcase ess-sas-suffix-1) "\\|" (upcase ess-sas-suffix-1))) + (if ess-sas-suffix-2 (concat + "\\|" (downcase ess-sas-suffix-2) "\\|" (upcase ess-sas-suffix-2))) + "\\)") + "Regular expression for SAS suffixes." + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-tab-stop-list + '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120) + "List of tab stop positions used by `tab-to-tab-stop' in ESS[SAS]." + :type '(repeat integer) + :group 'ess-sas) + +(defcustom ess-sas-temp-root "-temp" + "Appended to root name of the temporary .sas file for `ess-sas-submit-region'." + :group 'ess-sas + :type 'string) + +(defvar ess-sas-versions '("sas") + "List of partial strings for versions of SAS to access within ESS. +Each string specifies the start of a filename. If a filename +beginning with one of these strings is found on `exec-path', a M-x +command for that version of SAS is made available. For example, if the +file \"sas8\" is found and this variable includes the string +\"sas\", a function called `M-x SAS8' will be available to run that +version of SAS. +If duplicate versions of the same program are found (which happens if +the same path is listed on `exec-path' more than once), they are +ignored by calling `delete-dups'. +If you set this variable, you need to restart Emacs (and set this variable +before ess-site is loaded) for it to take effect.") + +(defvar ess-sas-global-unix-keys nil + "Non-nil if function keys use Unix-like SAS key definitions in all modes.") + +(defvar ess-sas-local-pc-keys nil + "Non-nil if function keys use PC-like SAS key definitions +in SAS-mode and related modes.") + +(defvar ess-sas-local-unix-keys nil + "Non-nil if function keys use Unix-like SAS key definitions +in SAS-mode and related modes.") + +;;; Section 2: Function Definitions + + +(defun ess-ebcdic-to-ascii-search-and-replace () + "Search and replace EBCDIC text with ASCII equivalents." + (interactive) + (let ((ess-tmp-dd (executable-find "dd")) (ess-tmp-recode (executable-find "recode")) + (ess-tmp-util nil) (ess-tmp-util-args nil)) + + (if ess-tmp-dd (progn + (setq ess-tmp-util ess-tmp-dd) + (setq ess-tmp-util-args "conv=ascii")) + + (setq ess-tmp-util ess-tmp-recode) + (setq ess-tmp-util-args "EBCDIC..ISO-8859-1")) + + (if ess-tmp-util + (while (search-forward-regexp "[^\f\t\n -~][^\f\t\n -?A-JQ-Yb-jp-y]*[^\f\t\n -~]?" nil t) + (call-process-region (match-beginning 0) (match-end 0) + ess-tmp-util t (list t nil) t ess-tmp-util-args))))) + + +(defun ess-exit-notify-sh (string) + "Detect completion or failure of submitted job and notify the user." + (let* ((exit-done "\\[[0-9]+\\] *\\+* *\\(Exit\\|Done\\)[^\r\n]*") + (beg (string-match exit-done string))) + (if beg + (message "%s" (substring string beg (match-end 0)))))) + + +(defun ess-sas-append-log () + "Append ess-temp.log to the current .log file." + (interactive) + (ess-sas-goto "log" 'revert) + (goto-char (point-max)) + (insert-file-contents (concat (ess-sas-temp-root) ".log")) + (save-buffer)) + +(defun ess-sas-append-lst () + "Append ess-temp.lst to the current .lst file." + (interactive) + (ess-sas-goto "lst" 'revert) + (goto-char (point-max)) + (insert-file-contents (concat (ess-sas-temp-root) ".lst")) + (save-buffer)) + +(defun ess-sas-backward-delete-tab () + "Moves the cursor to the previous tab-stop, deleting any characters +on the way." + (interactive) + + (let* (;; point of search + ;;(ess-sas-search-point nil) + ;; column of search + ;;(ess-sas-search-column nil) + ;; limit of search + ;;(ess-sas-search-limit nil) + ;; text to be inserted after a back-tab, if any + ;;(ess-sas-end-text "end;") + ;; current-column + (ess-sas-column (current-column)) + ;; remainder of current-column and sas-indent-width + (ess-sas-remainder (% ess-sas-column sas-indent-width))) + + (if (not (= ess-sas-column 0)) + (progn + (if (= ess-sas-remainder 0) + (setq ess-sas-remainder sas-indent-width)) + + (let ((backward-delete-char-untabify-method 'nil)) + (backward-delete-char-untabify ess-sas-remainder t) + (setq ess-sas-column (- ess-sas-column ess-sas-remainder)) + (move-to-column ess-sas-column) + (setq left-margin ess-sas-column)) + )) + )) + +;; this feature was far too complicated to perfect +;; (if ess-sas-smart-back-tab (progn +;; (save-excursion +;; (setq ess-sas-search-point +;; (search-backward-regexp "end" nil t)) + +;; (if (and ess-sas-search-point +;; (search-backward-regexp "%" (+ ess-sas-search-point -1) t)) +;; (setq ess-sas-search-point (+ ess-sas-search-point -1)) +;; ) + +;; (if (and ess-sas-search-point +;; (not (equal ess-sas-column (current-column)))) +;; (setq ess-sas-search-point nil)) +;; ) + +;; (save-excursion +;; (setq ess-sas-search-point +;; (search-backward-regexp "do\\|select" +;; ess-sas-search-point t)) + +;; (setq ess-sas-search-column (current-column)) + +;; (if ess-sas-search-point (progn +;; (save-excursion +;; (search-backward-regexp "^" nil t) +;; (setq ess-sas-search-limit (point)) +;; ) + +;; (if (search-backward-regexp "if.*then\\|else" ess-sas-search-limit t) +;; (setq ess-sas-search-point (point))) + +;; (if (search-backward-regexp "%" ess-sas-search-limit t) (progn +;; (setq ess-sas-end-text "%end;") +;; (setq ess-sas-search-point (point)) +;; )) + +;; (setq ess-sas-search-column (current-column)) + +;; (if (not (equal ess-sas-column ess-sas-search-column)) +;; (setq ess-sas-search-point nil)) +;; ))) + +;; (if ess-sas-search-point (insert ess-sas-end-text)) +;; )) + +(defun ess-sas-cd () + "Change directory, taking into account various issues with respect to +`ess-sas-file-path'." + ;(interactive) + (ess-sas-file-path) + (ess-sas-goto-shell t) + (comint-send-input) + (if (equal ess-sas-submit-method 'sh) + (insert "cd \"" (car (last (split-string (file-name-directory ess-sas-file-path) + "\\([a-zA-Z][a-zA-Z]:\\|]\\)"))) "\"") + (if (equal ess-sas-submit-method 'ms-dos) (progn + (if (string-equal ":" (substring ess-sas-file-path 1 2)) (progn + (insert (substring ess-sas-file-path 0 2)) + (comint-send-input))) + (insert "cd \"" (convert-standard-filename + (file-name-directory ess-sas-file-path)) "\"")))) + (comint-send-input)) + +(defun ess-sas--change-alist (item value alist) + "Modify ALIST to set VALUE to ITEM. +If there is a pair whose car is ITEM, replace its cdr by VALUE. +If there is not such pair, create new pair (ITEM . VALUE) and +return new alist whose car is the new pair and cdr is ALIST. +\[tomo's ELIS like function]" + (let ((pair (assoc item alist))) + (if pair + (progn + (setcdr pair value) + alist) + (cons (cons item value) alist)))) + +(defun ess-sas-create-local-variables-alist (&optional file-or-buffer) + "Create an alist of local variables from file-or-buffer. +Use the current buffer if nil." + (declare (obsolete nil "ESS 19.04")) + (if file-or-buffer (set-buffer (if (bufferp file-or-buffer) + file-or-buffer + (find-buffer-visiting file-or-buffer)))) + (ess-sas--change-alist 'ess-kermit-remote-directory ess-kermit-remote-directory nil)) + +(define-obsolete-function-alias + 'ess-change-alist #'ess-sas--change-alist "ESS 18.10") + +(defun ess-sas-data-view-fsview (&optional ess-sas-data) + "Open a dataset for viewing with PROC FSVIEW." + (interactive) + (ess-save-and-set-local-variables) + + (save-excursion (let ((ess-tmp-sas-data nil) + (ess-tmp-sas-data-view-fsview-statement ess-sas-data-view-fsview-statement) + (ess-search-regexp + "[ \t=]\\([a-zA-Z_][a-zA-Z_0-9]*[.][a-zA-Z_][a-zA-Z_0-9]*\\)\\(&.*\\)?[. ,()\t;/]") + (ess-search-except + "^\\([wW][oO][rR][kK]\\|[fF][iI][rR][sS][tT]\\|[lL][aA][sS][tT]\\)[.]")) + + (if ess-sas-data nil (save-match-data + (search-backward-regexp "[ \t=]" nil t) + + (save-excursion + (setq ess-tmp-sas-data + (ess-search-except ess-search-regexp ess-search-except))) + + (if (not ess-tmp-sas-data) + (setq ess-tmp-sas-data + (ess-search-except ess-search-regexp ess-search-except t))) + + (setq ess-sas-data (read-string "Permanent SAS Dataset: " ess-tmp-sas-data)) + + ;; (ess-sas-goto-shell t) + (ess-sas-cd) + + (insert (concat ess-sas-submit-pre-command " " ess-sas-submit-command + " -initstmt \"" ess-sas-data-view-libname ess-sas-data-view-fsview-command + ess-sas-data ";" ess-tmp-sas-data-view-fsview-statement "; run;\" " + ess-sas-submit-command-options " " + ess-sas-data-view-submit-options " " ess-sas-submit-post-command)) + (comint-send-input) + ))))) + +(defun ess-sas-data-view-insight (&optional ess-sas-data) + "Open a dataset for viewing with PROC INSIGHT." + (interactive) + (ess-save-and-set-local-variables) + + (save-excursion (let ((ess-tmp-sas-data nil) + (ess-tmp-sas-data-view-insight-statement ess-sas-data-view-insight-statement) + (ess-search-regexp + "[ \t=]\\([a-zA-Z_][a-zA-Z_0-9]*[.][a-zA-Z_][a-zA-Z_0-9]*\\)\\(&.*\\)?[. ,()\t;]") + (ess-search-except + "^\\([wW][oO][rR][kK]\\|[fF][iI][rR][sS][tT]\\|[lL][aA][sS][tT]\\)[.]")) + + (if ess-sas-data nil (save-match-data + (search-backward-regexp "[ \t=]" nil t) + + (save-excursion + (setq ess-tmp-sas-data + (ess-search-except ess-search-regexp ess-search-except))) + + (if (not ess-tmp-sas-data) + (setq ess-tmp-sas-data + (ess-search-except ess-search-regexp ess-search-except t))) + + (setq ess-sas-data (read-string "Permanent SAS Dataset: " ess-tmp-sas-data)) + + ;; (ess-sas-goto-shell t) + (ess-sas-cd) + + (insert (concat ess-sas-submit-pre-command " " ess-sas-submit-command + " -initstmt \"" ess-sas-data-view-libname ess-sas-data-view-insight-command + ess-sas-data ";" ess-tmp-sas-data-view-insight-statement "; run;\" " + ess-sas-data-view-submit-options " " ess-sas-submit-post-command)) + (comint-send-input) + ))))) + +(defun ess-sas-graph-view () + "Open a GSASFILE for viewing." + (interactive) + ;; (ess-sas-goto-shell t) + (ess-sas-cd) + (ess-sas-goto-log 'no-error-check) + + (save-excursion + (let ( + (ess-tmp-length (length ess-sas-graph-view-viewer-alist)) + (ess-tmp-counter 0) + (ess-tmp-graph nil) + (ess-tmp-graph-alist nil) + (ess-tmp-glyph nil) + (ess-tmp-graph-regexp + (concat "[cCub][oOty][rRpt][dDue][sSt][ ][wW][rR][iI][tT][tT][eE][nN][ ]+[tT][oO][ ]\n?[ ]*\\(.*" + ;; (concat "[ ][rR][eE][cC][oO][rR][dD][sS][ ][wW][rR][iI][tT][tT][eE][nN][ ]+[tT][oO][ ]\n?[ ]*\\(.*" + ess-sas-graph-view-suffix-regexp "\\)"))) + ; (concat "['\"]\\(.*" ess-sas-graph-suffix-regexp "\\)['\"]"))) + + (save-match-data + (search-backward-regexp "[ \t=]" nil t) + + (save-excursion + (setq ess-tmp-graph (ess-search-except ess-tmp-graph-regexp))) + + (if (not ess-tmp-graph) + (setq ess-tmp-graph (ess-search-except ess-tmp-graph-regexp nil t))) + + (setq ess-tmp-graph (read-string "GSASFILE: " + (or ess-tmp-graph ess-sas-file-path))) + +;; whether the image libraries are configured is what is important here + (if (and (string-match "JPEG" system-configuration-features) + (string-match "[.][jJ][pP][eE]?[gG]" ess-tmp-graph)) + (find-file ess-tmp-graph) + (if (and (string-match "PNG" system-configuration-features) + (string-match "[.][pP][nN][gG]" ess-tmp-graph)) + (find-file ess-tmp-graph) + ;; ;;GNU Emacs graphics file image viewing mode loaded? + ;; (if (and (bound-and-true-p auto-image-file-mode) + ;; (string-match "[.][jJ][pP][eE]?[gG]" ess-tmp-graph)) + ;; (find-file ess-tmp-graph) + ;; ;;else XEmacs graphics file image viewing mode loaded? + ;; (if (and (fboundp 'image-mode) + ;; (string-match "[.]\\([jJ][pP][eE]?[gG]\\|[gG][iI][fF]\\)" + ;; ess-tmp-graph)) + ;; (find-file ess-tmp-graph) + ;;else use the appropriate graphics file image viewer + (while (< ess-tmp-counter ess-tmp-length) + (setq ess-tmp-graph-alist + (nth ess-tmp-counter ess-sas-graph-view-viewer-alist)) + (setq ess-tmp-graph-regexp (car ess-tmp-graph-alist)) + + (if (string-match + (concat "[.]" ess-tmp-graph-regexp) ess-tmp-graph) + (progn + (ess-sas-goto-shell t) + (insert ess-sas-submit-pre-command " " + (cdr ess-tmp-graph-alist) " " ess-tmp-graph + (if (equal ess-sas-submit-method 'sh) " &")) + (setq ess-tmp-glyph 'alist) + (setq ess-tmp-counter ess-tmp-length)) + ;;else + (setq ess-tmp-counter (+ ess-tmp-counter 1)))) + + (if (not ess-tmp-glyph) + (progn + (ess-sas-goto-shell t) + (insert ess-sas-submit-pre-command " " + ess-sas-graph-view-viewer-default " " ess-tmp-graph + (if (equal ess-sas-submit-method 'sh) " &")))) + + (comint-send-input))))))) + +(defun ess-sas-file-path (&optional force) + "Define `ess-sas-file-path' to be the current buffer depending on suffix." + (interactive) + + (save-match-data (let ((ess-sas-temp-file (expand-file-name (buffer-name)))) + (if (or force (string-match ess-sas-suffix-regexp ess-sas-temp-file)) ;;(progn + (setq ess-sas-file-path + (nth 0 (split-string ess-sas-temp-file "[<]"))))))) + +(defun ess-sas-file-path-remote-host () + "Return the remote host, if any, associated with `ess-sas-file-path'." + (interactive) + + (let* ((temp-colon-pos (string-match ":" ess-sas-file-path)) + (temp-list + (if (or (not temp-colon-pos) (> temp-colon-pos 2)) + (if (equal ess-sas-file-path ".") nil + (split-string (file-name-directory ess-sas-file-path) + "\\(@\\|:\\|]\\)")) + (list ess-sas-file-path))) + (temp-list-length (length temp-list))) + (if (= temp-list-length 1) (setq temp-list nil) + (if (= temp-list-length 2) (setq temp-list (car temp-list)) + (setq temp-list (nth 1 temp-list)))) + + (if temp-list (setq temp-list + (car (last (split-string temp-list "/"))))) + temp-list)) + +(defun ess-sas-goto (suffix &optional revert no-create) + "Find a file associated with a SAS file by suffix and revert if necessary." +; (interactive) +; (let ((ess-temp-regexp (concat ess-sas-suffix-regexp "[.]?[1-9]?\\'"))) +; can we identify common nonsense extensions like .log.1 or .sas.2? + (let ((ess-temp-regexp (concat ess-sas-suffix-regexp "\\(@.+\\)?\\'"))) + (save-match-data + (if (or (string-match ess-temp-regexp (expand-file-name (buffer-name))) + (string-match ess-temp-regexp ess-sas-file-path)) + (progn + (ess-sas-file-path) + (let* ( + (ess-sas-temp-file (replace-match (concat "." suffix) t t + ess-sas-file-path)) + (ess-sas-temp-buff (find-buffer-visiting ess-sas-temp-file)) + (ess-temp-kermit-remote-directory ess-kermit-remote-directory)) + + (if ess-sas-temp-buff (switch-to-buffer ess-sas-temp-buff) + ;; else + (if no-create (setq revert nil) + (if (file-exists-p ess-sas-temp-file) + (find-file ess-sas-temp-file)))) + ;; else + ;; (let* ((ess-sas-buffer-list (buffer-list)) + ;; (ess-sas-buffer-list-index 0) + ;; (ess-sas-buffer-list-file nil) + ;; (ess-sas-buffer-list-length (length ess-sas-buffer-list))) + ;; (while (< ess-sas-buffer-list-index ess-sas-buffer-list-length) + ;; (setq ess-sas-buffer-list-file + ;; (buffer-file-name (nth ess-sas-buffer-list-index ess-sas-buffer-list))) + ;; (if (and ess-sas-buffer-list-file + ;; (string-match (concat "." suffix) ess-sas-buffer-list-file)) + ;; (switch-to-buffer (nth ess-sas-buffer-list-index ess-sas-buffer-list)) + ;; (setq ess-sas-buffer-list-index ess-sas-buffer-list-length) + ;; ) + ;; (setq ess-sas-buffer-list-index (+ 1 ess-sas-buffer-list-index)) + ;; ))) + + (if (and (not no-create) + (or (string-equal suffix "log") + (string-equal suffix "lst"))) + (ess-kermit-get (file-name-nondirectory ess-sas-temp-file) + ess-temp-kermit-remote-directory)) + + (if revert + (if (and (> ess-sas-log-max 0) (string-equal suffix "log") + (> (ess-num-or-zero (nth 7 (file-attributes ess-sas-temp-file))) + ess-sas-log-max)) + (progn + (insert-file-contents ess-sas-temp-file nil 0 + ess-sas-log-max t) + t) + + (ess-revert-wisely)) nil))))))) + +;;(defun ess-sas-file (suffix &optional revert) +;; "Please use `ess-sas-goto' instead." +;; (let* ((tail (downcase (car (split-string +;; (car (last (split-string (buffer-name) "[.]"))) "[<]")))) +;;(if (fboundp 'file-name-extension) (file-name-extension (buffer-name)) +;; (substring (buffer-name) -3))) +;; (tail-in-tail-list (member tail (list "sas" "log" "lst" +;; ess-sas-suffix-1 ess-sas-suffix-2))) +;; (root (if tail-in-tail-list (expand-file-name (buffer-name)) +;; ess-sas-file-path)) +;; (ess-sas-arg (concat (file-name-sans-extension root) "." suffix)) +;; (ess-sas-buf (find-buffer-visiting ess-sas-arg))) +;; (if (equal tail suffix) (if revert (ess-revert-wisely)) +;; (if (not ess-sas-buf) (find-file ess-sas-arg) +;; (switch-to-buffer ess-sas-buf) +;; (if revert (ess-revert-wisely)))))) + + +(defun ess-sas-goto-file-1 () + "Switch to ess-sas-file-1 and revert from disk." + (interactive) + (ess-sas-goto ess-sas-suffix-1 'revert)) + +(defun ess-sas-goto-file-2 () + "Switch to ess-sas-file-2 and revert from disk." + (interactive) + (ess-sas-goto ess-sas-suffix-2 'revert)) + +(defun ess-sas-goto-log (&optional ess-tmp-no-error-check) + "Switch to the .log file, revert from disk and search for error messages." + (interactive) + + (let ((ess-sas-error (concat + "^ERROR [0-9]+-[0-9]+:\\|^ERROR:\\|_ERROR_=1 _N_=\\|_ERROR_=1[ ]?$" + "\\|NOTE: MERGE statement has more than one data set with repeats" + "\\|NOTE: Variable .* is uninitialized." + "\\|NOTE: SAS went to a new line when INPUT statement reached past" + "\\|NOTE 485-185: Informat .* was not found" + "\\|NOTE: Estimated G matrix is not positive definite." + "\\|NOTE: Compressing data set .* increased size by" + "\\|NOTE: ERROR DETECTED IN ANNOTATE=" + "\\|WARNING: Apparent symbolic reference .* not resolved." + "\\|WARNING: Length of character variable has already been set." + "\\|WARNING: Not all variables in the list " + "\\|WARNING: RUN statement ignored due to previous errors." + "\\|WARNING: Values exist outside the axis range" + "\\|WARNING: Truncated record." + "\\|Bus Error In Task\\|Segmentation Violation In Task")) + (ess-sas-save-point nil)); (ess-sas-pop-mark nil)) + + (if (ess-sas-goto "log" 'revert) (progn + (setq ess-sas-save-point (point)) + (goto-char (point-min))) + (setq ess-sas-save-point (point))) + + ;(if (number-char-or-marker-p ess-sas-save-point) (progn + (if ess-tmp-no-error-check (goto-char ess-sas-save-point) + (if (or (search-forward-regexp ess-sas-error nil t) + (and (goto-char (point-min)) + (search-forward-regexp ess-sas-error nil t))) + t + (goto-char ess-sas-save-point))))) + +(defun ess-sas-goto-lst () + "Switch to the .lst file and revert from disk." + (interactive) + (ess-sas-goto "lst" 'revert)) + +(defun ess-sas-goto-sas (&optional revert) + "Switch to the .sas file." + (interactive) + (ess-sas-goto "sas" revert)) + +(defun ess-sas-goto-shell (&optional set-buffer) + "Set `ess-sas-file-path' and goto `ess-sas-shell-buffer'. If +optional argument is non-nil, then set-buffer rather than switch." + (interactive) + (ess-sas-file-path) + + ; The following let* block is an attempt to deal with remote directories. + (let* ((temp-shell-buffer-remote-host + (or ess-sas-shell-buffer-remote-host (ess-sas-file-path-remote-host))) + (temp-shell-buffer-remote-init ess-sas-shell-buffer-remote-init) + (temp-shell-buffer + (if temp-shell-buffer-remote-host + (concat "*" temp-shell-buffer-remote-host "*") + ess-sas-shell-buffer)) + ) + + (if (get-buffer temp-shell-buffer) + (if set-buffer (set-buffer temp-shell-buffer) + (switch-to-buffer temp-shell-buffer)) + (shell) + (rename-buffer temp-shell-buffer) + (ess-sleep) ; GNU Emacs needs this + + (if temp-shell-buffer-remote-host (progn + (insert (concat + temp-shell-buffer-remote-init " " temp-shell-buffer-remote-host)) + (comint-send-input)) + ) + + (if (eq ess-sas-submit-method 'sh) + (add-hook 'comint-output-filter-functions #'ess-exit-notify-sh)) ;; 19.28 + ;; nil t) works for newer emacsen + ) + ) + + (goto-char (point-max)) + ; (insert "cd " ess-temp-directory) + ; (comint-send-input)) + ) + +(defun ess-sas-interactive () + "And now for something completely different." + (interactive) + ;;(ess-sas-file-path) + (setq ess-local-customize-alist SAS-customize-alist) + ;; (let ((ess-temp-sas-file + ;; (nth 0 (split-string + ;; (car (last (split-string ess-sas-file-path "\\([a-zA-Z][a-zA-Z]:\\|]\\)"))) "[.]")))) + (setq ess-sas-shell-buffer "*iESS[SAS]*") + (ess-sas-goto-shell) + (ess-add-ess-process) + (ess-setq-vars-local ess-local-customize-alist) + (inferior-ess-mode) + (ess-eval-linewise (concat ess-sas-submit-command " " ess-sas-submit-command-options " -stdio")) + ;;" -altlog " ess-temp-sas-file ".log -altprint " + ;; ess-temp-sas-file ".lst -stdio")) + (ess-sas-goto-sas) + (setq ess-sas-submit-method 'iESS) + (setq ess-eval-visibly-p nil) + ) + +;;(defun ess-sas-interactive () +;; (interactive) +;; (ess-sas-file-path) +;; (setq ess-sas-submit-method 'iESS) +;; +;; (let ((ess-temp-stderr " ") (ess-temp-stdout " ") (ess-temp-stdin " ")) +;; (setq ess-sas-shell-buffer "*LOG*") +;; (ess-sas-goto-shell) +;; (insert "tty") +;; (comint-send-input) +;; (sleep-for ess-sleep-for) +;; (save-excursion (setq ess-temp-stderr (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) +;; (setq ess-sas-shell-buffer "*OUTPUT*") +;; (ess-sas-goto-shell) +;; (insert "tty") +;; (comint-send-input) +;; (sleep-for ess-sleep-for) +;; (save-excursion (setq ess-temp-stdout (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) +;; (setq ess-sas-shell-buffer "*PROGRAM*") +;; (ess-sas-goto-shell) +;;;; (insert "tty") +;; (comint-send-input) +;; (sleep-for ess-sleep-for) +;; (insert "sh") +;; (comint-send-input) +;; (sleep-for ess-sleep-for) +;; (save-excursion (setq ess-temp-stdin (ess-search-except "\\(/dev/[a-z0-9/]+\\)" nil t))) +;; (insert (concat ess-sas-submit-command " " ess-sas-submit-command-options " -stdio <" +;; ess-temp-stdin " >1 " ess-temp-stdout " >2 " ess-temp-stderr)) +;; (comint-send-input) +;; (ess-add-ess-process) +;; (ess-sas-goto-sas) +;;)) + +(defun ess-sas-kill-buffers () + "Kill all buffers related to a .sas file." + (interactive) + (ess-sas-file-path) + (ess-sas-goto "log" nil t) + (kill-buffer nil) + (ess-sas-goto "lst" nil t) + (kill-buffer nil) + (ess-sas-goto ess-sas-suffix-1 nil t) + (kill-buffer nil) + (ess-sas-goto ess-sas-suffix-2 nil t) + (kill-buffer nil) + (ess-sas-goto "sas" nil t) + (kill-buffer nil) + ) + +; else +(defun ess-sas-rtf-portrait (&optional _ess-tmp-font-size) + "Creates an MS RTF portrait file from the current buffer." + (interactive) + (ess-revert-wisely) + (set-visited-file-name (concat (buffer-name) ".rtf")) + (when buffer-read-only + (setq buffer-read-only nil)) + (ess-rtf-replace-chars) + (goto-char (point-min)) + (insert (concat + "{\\rtf1\\ansi{\\fonttbl\\f1\\fmodern " ess-sas-rtf-font-name ";}\n" + "\\margl720\\margr720\\margt720\\margb720\n" + "{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\n" + "{\\stylesheet{\\s15\\plain\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Text;}{\\*\\cs16 \\additive\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Base Style;}}\n" + "{\\plain\\s15{\\cs16\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024{\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024\n")) + (goto-char (point-max)) + (insert "}}}}\n") + (save-buffer) + (kill-buffer (current-buffer))) + +(defun ess-rtf-replace-chars () + "Convert a text file to an MS RTF file." + (interactive) + (goto-char (point-min)) + (while (re-search-forward "\n" nil t) (replace-match "\\par\n" nil t)) + (goto-char (point-min)) + (while (re-search-forward "\f" nil t) (replace-match "\\page\n" nil t)) + (goto-char (point-min)) + (while (re-search-forward "\t" nil t) (replace-match "\\tab" nil t))) + +(defun ess-sas-rtf-landscape (&optional _ess-tmp-font-size) + "Creates an MS RTF landscape file from the current buffer." + (interactive) + (ess-revert-wisely) + (set-visited-file-name (concat (buffer-name) ".rtf")) + (when buffer-read-only + (setq buffer-read-only nil)) + (ess-rtf-replace-chars) + (goto-char (point-min)) + (insert (concat + "{\\rtf1\\ansi{\\fonttbl\\f1\\fmodern " ess-sas-rtf-font-name ";}\n" + "\\margl720\\margr720\\margt720\\margb720\n" + "{\\*\\pgdsctbl\n" + "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" + "\\landscape\\paperh12240\\paperw15840\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n" + "{\\colortbl;\\red0\\green0\\blue0;\\red0\\green0\\blue255;\\red0\\green255\\blue255;\\red0\\green255\\blue0;\\red255\\green0\\blue255;\\red255\\green0\\blue0;\\red255\\green255\\blue0;\\red255\\green255\\blue255;\\red0\\green0\\blue128;\\red0\\green128\\blue128;\\red0\\green128\\blue0;\\red128\\green0\\blue128;\\red128\\green0\\blue0;\\red128\\green128\\blue0;\\red128\\green128\\blue128;\\red192\\green192\\blue192;}\n" + "{\\stylesheet{\\s15\\plain\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Text;}{\\*\\cs16 \\additive\\f1\\fs16\\cf1\\cb8\\lang1024 Emacs Base Style;}}\n" + "{\\plain\\s15{\\cs16\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024{\\cs16\\f1\\fs16\\cf1\\cb8\\lang1024\n")) + (goto-char (point-max)) + (insert "}}}}\n") + (save-buffer) + (kill-buffer (current-buffer))) + +(defun ess-sas-rtf-us-landscape () + "Creates an MS RTF US landscape file from the current buffer." + (interactive) + (ess-sas-rtf-portrait "16") + (ess-sas-goto "rtf" t) + (goto-char (point-min)) + (forward-line 3) + (insert (concat "{\\*\\pgdsctbl\n" + "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" + "\\landscape\\paperh12240\\paperw15840\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn15840\\pghsxn12240\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n")) + (save-buffer) + (kill-buffer (current-buffer))) + +(defun ess-sas-rtf-a4-landscape () + "Creates an MS RTF A4 landscape file from the current buffer." + (interactive) + (ess-sas-rtf-portrait "16") + (ess-sas-goto "rtf" t) + (goto-char (point-min)) + (forward-line 3) + (insert (concat "{\\*\\pgdsctbl\n" + "{\\pgdsc0\\pgdscuse195\\lndscpsxn\\pgwsxn16837\\pghsxn11905\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\pgdscnxt0 Default;}}\n" + "\\landscape\\paperh11905\\paperw16837\\margl1800\\margr1800\\margt1440\\margb1440\\sectd\\sbknone\\lndscpsxn\\pgwsxn16837\\pghsxn11905\\marglsxn1800\\margrsxn1800\\margtsxn1440\\margbsxn1440\\ftnbj\\ftnstart1\\ftnrstcont\\ftnnar\\aenddoc\\aftnrstcont\\aftnstart1\\aftnnrlc\n")) + (save-buffer) + (kill-buffer (current-buffer))) + +(defun ess-sas-submit () + "Save the .sas file and submit to shell using a function that +depends on the value of `ess-sas-submit-method'" + (interactive) + (ess-sas-file-path) + (ess-sas-goto-sas) + (save-buffer) + (hack-local-variables) + ;(ess-save-and-set-local-variables) + + (cond + ((eq ess-sas-submit-method 'ms-dos) + (ess-sas-submit-windows ess-sas-submit-command + ess-sas-submit-command-options)) + ((eq ess-sas-submit-method 'iESS) + (ess-sas-submit-iESS ess-sas-submit-command + ess-sas-submit-command-options)) + ((eq ess-sas-submit-method 'sh) + (ess-sas-submit-sh ess-sas-submit-command + ess-sas-submit-command-options)) + (t (ess-sas-submit-sh ess-sas-submit-command + ess-sas-submit-command-options))) + ; (ess-sas-goto-sas) + ) + +(defun ess-sas-submit-iESS (arg1 arg2) + "iESS +Submit a batch job in an inferior-ESS buffer. The buffer should +(1) have telnet access and be running a shell on a remote machine +or +(2) be running a shell on the local machine. + +The user can telnet to the remote computer and then declare the +*telnet-buffer* to be an inferior ESS buffer with the `ess-add-ess-process' +command. When using a remote computer, the .sas file must live on the +remote computer and be accessed through `ange-ftp'. When +`ess-sas-submit' saves a file, it is therefore saved on the remote +computer. The various functions such as `ess-sas-goto-lst' retrieve +their files from the remote computer. Local copies of the .sas .lst +.log and others may be made manually with `write-buffer'." + ;; (ess-eval-linewise (concat "cd default-directory)) +(ess-force-buffer-current "Process to load into: ") +(ess-eval-linewise + (concat "cd " (car (last + (split-string (file-name-directory ess-sas-file-path) "\\(:\\|]\\)"))))) +(ess-eval-linewise (concat arg1 " " arg2 " " (buffer-name) " &"))) + +(defun ess-sas-submit-region () + "Write region to temporary file, and submit to SAS." + (interactive) + (ess-sas-file-path) + (hack-local-variables t) + (write-region (region-beginning) (region-end) + (concat (ess-sas-temp-root) ".sas")) + + (let ((arg1 ess-sas-submit-command) + (arg2 ess-sas-submit-command-options)) + (save-excursion + (ess-sas-goto-shell t) + + (if (and (when + ;; Silence byte compiler warns about w32-fns + (fboundp 'w32-shell-dos-semantics) + (w32-shell-dos-semantics)) + (string-equal ":" (substring ess-sas-file-path 1 2))) + (progn + (insert (substring ess-sas-file-path 0 2)) + (comint-send-input) + )) + + (insert "cd \"" (convert-standard-filename + (file-name-directory ess-sas-file-path)) "\"") + (comint-send-input) + + (insert (concat ess-sas-submit-pre-command " " arg1 + " " arg2 + " " (ess-sas-temp-root) " " ess-sas-submit-post-command)) + (comint-send-input) + )) + ) + +(defun ess-sas-submit-sh (arg1 arg2) + "Unix or bash in the *shell* buffer. +Multiple processing is supported on this platform. +SAS may not be found in your PATH. You can alter your PATH to include +SAS or you can specify the PATHNAME (PATHNAME can NOT contain spaces), +i.e. let arg1 be your local equivalent of +\"/usr/local/sas612/sas\"." + (if (string-equal (substring + (file-name-nondirectory ess-sas-file-path) 0 1) ess-kermit-prefix) + (progn + (ess-kermit-send) + (ess-sas-goto-shell t) + (insert ess-sas-submit-pre-command " " arg1 " " + (substring (file-name-sans-extension + (file-name-nondirectory ess-sas-file-path)) 1) + " " arg2 " " ess-sas-submit-post-command) + (comint-send-input)) + ;;else + ;; (ess-sas-goto-shell t) + (ess-sas-cd) + ; (insert "cd " (car (last (split-string (file-name-directory ess-sas-file-path) + ;"\\([a-zA-Z][a-zA-Z]:\\|]\\)")))) + ; (comint-send-input) + (insert ess-sas-submit-pre-command " " arg1 " " + (file-name-sans-extension (file-name-nondirectory ess-sas-file-path)) + " " arg2 " " ess-sas-submit-post-command)) + ; (ess-sleep) + (comint-send-input)) + +(defun ess-sas-submit-windows (arg1 arg2) + "Windows using MS-DOS prompt in the *shell* buffer. +Multiple processing is supported on this platform. +On most Windows installations, SAS will not be found in your +PATH so you should alter your PATH to include SAS, i.e. + +SET PATH=%PATH%;C:\\Program Files\\SAS + +Or you can specify the PATHNAME directly (you must escape +spaces by enclosing the string in \\\"'s), i.e. let +`ess-sas-submit-command' be \"\\\"C:\\Program Files\\SAS\\sas.exe\\\"\". +Keep in mind that the maximum command line length in MS-DOS is +127 characters so altering your PATH is preferable." + ;(ess-save-and-set-local-variables) + (ess-sas-goto-shell t) + (if (string-equal ":" (substring ess-sas-file-path 1 2)) + (progn + (insert (substring ess-sas-file-path 0 2)) + (comint-send-input) + ) + ) + (insert "cd \"" (convert-standard-filename + (file-name-directory ess-sas-file-path)) "\"") + (comint-send-input) + (insert ess-sas-submit-pre-command " " arg1 " -sysin \"" + (file-name-sans-extension (file-name-nondirectory ess-sas-file-path)) "\" " + arg2 " " ess-sas-submit-post-command) + (comint-send-input)) + +(defun ess-sas-tab-to-tab-stop () + "Tab to next tab-stop and set left margin." + (interactive) + (tab-to-tab-stop) + (setq left-margin (current-column)) + ) + +(defun ess-sas-temp-root () + "Return `ess-sas-file-path' sans extension with `ess-sas-temp-root' appended." + (concat (file-name-sans-extension ess-sas-file-path) ess-sas-temp-root)) + +(defun ess-sas-transcript (&optional strip) + "Comment .log messages to create a .sas program; use C-u to strip." + (interactive "P") + (save-excursion + (goto-char (point-min)) + + (while (search-forward-regexp (concat + "^\\(\\(1[ \t]+The SAS System\\| \\|NOTE\\|WARNING\\|ERROR\\|" + "[ \t]+\\(\\(real\\|cpu\\) time\\|Licensed to\\|Engine:\\|" + "Physical Name:\\|File Name=\\|Owner Name=\\|Group Name=\\|" + "Access Permission=\\|File Size (bytes)=\\|Pipe command=\\|" + "RECFM=[DFNPV],LRECL=\\|[0-9]+:[0-9]+[ /t]+[0-9]+:[0-9]+\\|" + "[1-9][0-9]* at [0-9]+:[0-9]+[ /t]+[1-9][0-9]* at [0-9]+:[0-9]+\\)\\).*$" + "\\|[0-9]+\\([ \t]+!\\)?\\|MPRINT([_A-Z]+):\\|" + "[ \t]+\\(values at the places given by: (Line):(Column).\\|" + "The m\\(in\\|ax\\)imum record length was [1-9][0-9]*.\\|" + "One or more lines were truncated.\\|" + "Each place is given by: (Number of times) at (Line):(Column).\\|" + "[0-9][0-9]:[0-9][0-9] [MTWFS][aeioudhnrst]+day, [JFMASOND]" + "[aeiouybcghlmnprstv]+ [1-9][0-9]?, 20[0-9][0-9]\\)\\)") + nil t) + (replace-match (if strip " " "/*\\&*/") t)) + )) + +(defun ess-sas-toggle-sas-listing-mode (&optional _force) + "Toggle SAS-listing-mode for .lst files." + (interactive) + (ess-sas-goto-lst) + + (if (equal (cdr (assoc "\\.[lL][sS][tT]\\'" auto-mode-alist)) 'SAS-listing-mode) (progn + (setq auto-mode-alist (delete '("\\.[lL][sS][tT]\\'" . SAS-listing-mode) auto-mode-alist)) + (setq buffer-read-only nil) + (ess-listing-minor-mode 0)) + (setq auto-mode-alist (append '(("\\.[lL][sS][tT]\\'" . SAS-listing-mode)) auto-mode-alist)) + (setq buffer-read-only t) + (ess-listing-minor-mode 1))) + +(defun ess-sas-toggle-sas-log-mode () + "Toggle SAS-log-mode for .log files." + (interactive) + + (ess-sas-goto-log) + (kill-buffer nil) + + ; (if (equal (cdr (assoc "\\.[lL][oO][gG]\\'" auto-mode-alist)) 'SAS-log-mode) (progn + ; (setq auto-mode-alist (delete '("\\.[lL][oO][gG]\\'" . SAS-log-mode) auto-mode-alist)) + ; (setq buffer-read-only nil) + ; (ess-transcript-minor-mode 0) + ; (font-lock-mode 0)) + ; (setq auto-mode-alist (append '(("\\.[lL][oO][gG]\\'" . SAS-log-mode)) auto-mode-alist)) + ; (setq buffer-read-only t) + ; (ess-transcript-minor-mode 1) + ; (font-lock-mode 1) + ; (font-lock-fontify-buffer)) + + (if (equal (cdr (assoc "\\.[lL][oO][gG]\\'" auto-mode-alist)) 'SAS-log-mode) + (setq auto-mode-alist (delete '("\\.[lL][oO][gG]\\'" . SAS-log-mode) auto-mode-alist)) + (setq auto-mode-alist (append '(("\\.[lL][oO][gG]\\'" . SAS-log-mode)) auto-mode-alist))) + (ess-sas-goto-log)) + +(define-obsolete-variable-alias + 'ess-sas-versions-created 'ess-sas-created-runners "ESS 18.10") +(defvar ess-sas-created-runners) +(defun ess-sas-define-runners () + "Generate the `M-x SASV' functions for starting other versions of SAS. +See `ess-sas-versions' for strings that determine which functions are created. + +The local variable `ess-sas-created-runners' is used to return list of +the new SAS defuns, if any, that were created. The defuns will normally +be placed on the menubar upon ESS initialization." + ;; This works by creating a temp buffer where the template function is + ;; edited so that V is replaced by the version number + (let ((versions + ;; Find which versions of SAS we want. Remove the pathname, + ;; leaving just the name of the executable. + (delete-dups + (mapcar #'file-name-nondirectory + (apply #'nconc + (mapcar #'ess-find-exec-completions + ess-sas-versions)))))) + ;; Iterate over each string in VERSIONS, creating a new defun each time. + (setq ess-sas-created-runners + (mapc (lambda (v) (ess-define-runner v "SAS")) versions)))) +(define-obsolete-function-alias + 'ess-sas-create-versions #'ess-sas-define-runners "ESS 18.10") + + +;;; Section 3: Key Definitions + + +(defun ess-sas-edit-keys-set (&optional arg) + "Set TAB/RET key in `SAS-mode'. +If arg is nil + TAB is `sas-indent-line' and + RET is `newline-and-indent'. +Else + TAB is `ess-sas-tab-to-tab-stop', + C-TAB is `ess-sas-backward-delete-tab' and + RET is `newline'." + (interactive) + (when arg + ;; TODO: Why is this set up this way? + (define-key sas-mode-local-map [(control tab)] #'ess-sas-backward-delete-tab) + (define-key sas-mode-local-map [return] #'newline) + (define-key sas-mode-local-map "\t" #'ess-sas-tab-to-tab-stop))) + +(defvar ess-sas-edit-keys-toggle nil + "Toggle TAB/RET key in `SAS-mode'. +nil binds TAB to `sas-indent-line' and RET to `newline-and-indent'. +Non-nil binds TAB to `ess-sas-tab-to-tab-stop', +C-TAB to `ess-sas-backward-delete-tab', and RET to `newline'.") + +(defun ess-sas-edit-keys-toggle (&optional _arg) + "Toggle `ess-sas-edit-keys-toggle'. Optional arg is still +accepted for backward compatibility, however, arg is ignored." + (interactive) + + (setq ess-sas-edit-keys-toggle (not ess-sas-edit-keys-toggle)) + (ess-sas-edit-keys-set ess-sas-edit-keys-toggle) + ) + +(defvar ess-sas-global-pc-keys nil + "Non-nil if function keys use PC-like SAS key definitions in all modes.") + +(defun ess-sas-global-pc-keys () + "PC-like SAS key definitions" + (interactive) + (global-set-key [(control f1)] #'ess-sas-rtf-portrait) + (global-set-key [(control f2)] #'ess-sas-rtf-landscape) + (global-set-key (quote [f2]) #'ess-revert-wisely) + (global-set-key (quote [f3]) #'ess-sas-goto-shell) + (global-set-key (quote [f4]) #'ess-sas-goto-file-1) + (global-set-key (quote [f5]) #'ess-sas-goto-sas) + (global-set-key (quote [f6]) #'ess-sas-goto-log) + (global-set-key [(control f6)] #'ess-sas-append-log) + (global-set-key (quote [f7]) #'ess-sas-goto-lst) + (global-set-key [(control f7)] #'ess-sas-append-lst) + (global-set-key (quote [f8]) #'ess-sas-submit) + (global-set-key [(control f8)] #'ess-sas-submit-region) + (global-set-key (quote [f9]) #'ess-sas-data-view-fsview) + (global-set-key [(control f9)] #'ess-sas-data-view-insight) + ;; (global-set-key (quote [f10]) #'ess-sas-toggle-sas-log-mode) + ;; (global-set-key [(control f10)] #'ess-sas-toggle-sas-listing-mode) + ;; (global-set-key (quote [f11]) #'ess-sas-goto-file-2) + ;; (global-set-key [(control f11)] #'ess-ebcdic-to-ascii-search-and-replace) + (global-set-key (quote [f12]) #'ess-sas-graph-view) + (global-set-key [(control tab)] #'ess-sas-backward-delete-tab) + ;; (define-key sas-mode-local-map "\C-c\C-p" #'ess-sas-file-path) + (setq ess-sas-global-pc-keys t) + (setq ess-sas-global-unix-keys nil) + (setq ess-sas-local-pc-keys nil) + (setq ess-sas-local-unix-keys nil) + ) + +(defun ess-sas-global-unix-keys () + "Unix/Mainframe-like SAS key definitions" + (interactive) + (global-set-key [(control f1)] #'ess-sas-rtf-portrait) + (global-set-key [(control f2)] #'ess-sas-rtf-landscape) + (global-set-key (quote [f2]) #'ess-revert-wisely) + (global-set-key (quote [f3]) #'ess-sas-submit) + (global-set-key [(control f3)] #'ess-sas-submit-region) + (global-set-key (quote [f4]) #'ess-sas-goto-sas) + (global-set-key (quote [f5]) #'ess-sas-goto-log) + (global-set-key [(control f5)] #'ess-sas-append-log) + (global-set-key (quote [f6]) #'ess-sas-goto-lst) + (global-set-key [(control f6)] #'ess-sas-append-lst) + (global-set-key (quote [f7]) #'ess-sas-goto-file-1) + (global-set-key (quote [f8]) #'ess-sas-goto-shell) + (global-set-key (quote [f9]) #'ess-sas-data-view-fsview) + (global-set-key [(control f9)] #'ess-sas-data-view-insight) + ;; (global-set-key (quote [f10]) #'ess-sas-toggle-sas-log-mode) + ;; (global-set-key [(control f10)] #'ess-sas-toggle-sas-listing-mode) + ;; (global-set-key (quote [f11]) #'ess-sas-goto-file-2) + ;; (global-set-key [(control f11)] #'ess-ebcdic-to-ascii-search-and-replace) + (global-set-key (quote [f12]) #'ess-sas-graph-view) + (global-set-key [(control tab)] #'ess-sas-backward-delete-tab) + ;;(define-key sas-mode-local-map "\C-c\C-p" #'ess-sas-file-path) + (setq ess-sas-global-pc-keys nil) + (setq ess-sas-global-unix-keys t) + (setq ess-sas-local-pc-keys nil) + (setq ess-sas-local-unix-keys nil) + ) + +(defun ess-sas-local-pc-keys () + "PC-like SAS key definitions." + (interactive) + (define-key sas-mode-local-map [(control f1)] #'ess-sas-rtf-portrait) + (define-key sas-mode-local-map [(control f2)] #'ess-sas-rtf-landscape) + (define-key sas-mode-local-map (quote [f2]) #'ess-revert-wisely) + (define-key sas-mode-local-map (quote [f3]) #'ess-sas-goto-shell) + (define-key sas-mode-local-map (quote [f4]) #'ess-sas-goto-file-1) + (define-key sas-mode-local-map (quote [f5]) #'ess-sas-goto-sas) + (define-key sas-mode-local-map (quote [f6]) #'ess-sas-goto-log) + (define-key sas-mode-local-map [(control f6)] #'ess-sas-append-log) + (define-key sas-mode-local-map (quote [f7]) #'ess-sas-goto-lst) + (define-key sas-mode-local-map [(control f7)] #'ess-sas-append-lst) + (define-key sas-mode-local-map (quote [f8]) #'ess-sas-submit) + (define-key sas-mode-local-map [(control f8)] #'ess-sas-submit-region) + (define-key sas-mode-local-map (quote [f9]) #'ess-sas-data-view-fsview) + (define-key sas-mode-local-map [(control f9)] #'ess-sas-data-view-insight) + (define-key sas-mode-local-map (quote [f10]) #'ess-sas-toggle-sas-log-mode) + (define-key sas-mode-local-map [(control f10)] #'ess-sas-toggle-sas-listing-mode) + (define-key sas-mode-local-map (quote [f11]) #'ess-sas-goto-file-2) + (define-key sas-mode-local-map [(control f11)] #'ess-ebcdic-to-ascii-search-and-replace) + (define-key sas-mode-local-map (quote [f12]) #'ess-sas-graph-view) + ;(define-key sas-mode-local-map "\C-c\C-p" #'ess-sas-file-path) + (setq ess-sas-global-pc-keys nil) + (setq ess-sas-global-unix-keys nil) + (setq ess-sas-local-pc-keys t) + (setq ess-sas-local-unix-keys nil) + ) + +(defun ess-sas-local-unix-keys () + "Unix/Mainframe-like SAS key definitions" + (interactive) + (define-key sas-mode-local-map [(control f1)] #'ess-sas-rtf-portrait) + (define-key sas-mode-local-map [(control f2)] #'ess-sas-rtf-landscape) + (define-key sas-mode-local-map (quote [f2]) #'ess-revert-wisely) + (define-key sas-mode-local-map (quote [f3]) #'ess-sas-submit) + (define-key sas-mode-local-map [(control f3)] #'ess-sas-submit-region) + (define-key sas-mode-local-map (quote [f4]) #'ess-sas-goto-sas) + (define-key sas-mode-local-map (quote [f5]) #'ess-sas-goto-log) + (define-key sas-mode-local-map [(control f5)] #'ess-sas-append-log) + (define-key sas-mode-local-map (quote [f6]) #'ess-sas-goto-lst) + (define-key sas-mode-local-map [(control f6)] #'ess-sas-append-lst) + (define-key sas-mode-local-map (quote [f7]) #'ess-sas-goto-file-1) + (define-key sas-mode-local-map (quote [f8]) #'ess-sas-goto-shell) + (define-key sas-mode-local-map (quote [f9]) #'ess-sas-data-view-fsview) + (define-key sas-mode-local-map [(control f9)] #'ess-sas-data-view-insight) + (define-key sas-mode-local-map (quote [f10]) #'ess-sas-toggle-sas-log-mode) + (define-key sas-mode-local-map [(control f10)] #'ess-sas-toggle-sas-listing-mode) + (define-key sas-mode-local-map (quote [f11]) #'ess-sas-goto-file-2) + (define-key sas-mode-local-map [(control f11)] #'ess-ebcdic-to-ascii-search-and-replace) + (define-key sas-mode-local-map (quote [f12]) #'ess-sas-graph-view) + ;;(define-key sas-mode-local-map "\C-c\C-p" #'ess-sas-file-path) + (setq ess-sas-global-pc-keys nil) + (setq ess-sas-global-unix-keys nil) + (setq ess-sas-local-pc-keys nil) + (setq ess-sas-local-unix-keys t) + ) + +(defun ess-kermit-get (&optional ess-file-arg ess-dir-arg) + "Get a file with Kermit. WARNING: Experimental! From your *shell* +buffer, start kermit and then log in to the remote machine. Open +a file that starts with `ess-kermit-prefix'. From that buffer, +execute this command. It will retrieve a file from the remote +directory that you specify with the same name, but without the +`ess-kermit-prefix'." + + (interactive) + + ;; (save-match-data + (let ((ess-temp-file (if ess-file-arg ess-file-arg (buffer-name))) + (ess-temp-file-remote-directory ess-dir-arg)) + + (if (string-equal ess-kermit-prefix (substring ess-temp-file 0 1)) + (progn + ;; I think there is a bug in the buffer-local variable handling in GNU Emacs 21.3 + ;; Setting ess-kermit-remote-directory every time is somehow resetting it to the + ;; default on the second pass. So, here's a temporary work-around. It will fail + ;; if you change the default, so maybe this variable should not be customizable. + ;; In any case, there is also trouble with local variables in XEmacs 21.4.9 and + ;; 21.4.10. XEmacs 21.4.8 is fine. + (if ess-temp-file-remote-directory + (setq ess-kermit-remote-directory ess-temp-file-remote-directory) + + (if (string-equal "." ess-kermit-remote-directory) + (setq ess-kermit-remote-directory (read-string "Remote directory to transfer file from: " + ess-kermit-remote-directory)))) + + (setq ess-temp-file-remote-directory ess-kermit-remote-directory) + ;; (setq ess-temp-file (substring ess-temp-file (match-end 0))) + (ess-sas-goto-shell) + (insert "cd " ess-temp-file-remote-directory "; " ess-kermit-command " -s " + (substring ess-temp-file 1) " -a " ess-temp-file) + (comint-send-input) + ;; (insert (read-string "Press Return to connect to Kermit: " nil nil "\C-\\c")) + ;; (comint-send-input) + ;; (insert (read-string "Press Return when Kermit is ready to receive: " nil nil + ;; (concat "receive ]" ess-sas-temp-file))) + ;; (comint-send-input) + ;; (insert (read-string "Press Return when transfer is complete: " nil nil "c")) + ;; (comint-send-input) + (insert (read-string "Press Return when shell is ready: ")) + (comint-send-input) + (switch-to-buffer (find-buffer-visiting ess-temp-file)) + (ess-revert-wisely) + )))) + +(defun ess-kermit-send () + "Send a file with Kermit. WARNING: Experimental! From +a file that starts with `ess-kermit-prefix', +execute this command. It will transfer this file to the remote +directory with the same name, but without the `ess-kermit-prefix'." + + (interactive) + + ;; (save-match-data + (let ((ess-temp-file (expand-file-name (buffer-name))) + (ess-temp-file-remote-directory nil)) + + (if (string-equal ess-kermit-prefix (substring (file-name-nondirectory ess-temp-file) 0 1)) + (progn + ;; I think there is a bug in the buffer-local variable handling in GNU Emacs 21.3 + ;; Setting ess-kermit-remote-directory every time is somehow resetting it to the + ;; default on the second pass. Here's a temporary work-around. It will fail + ;; if you change the default, so maybe this variable should not be customizable. + ;; In any case, there is also trouble with local variables in XEmacs 21.4.9 and + ;; 21.4.10. XEmacs 21.4.8 is fine. + (if (string-equal "." ess-kermit-remote-directory) + (setq ess-kermit-remote-directory (read-string "Remote directory to transfer file to: " + ess-kermit-remote-directory))) + + (setq ess-temp-file-remote-directory ess-kermit-remote-directory) + + ;; (setq ess-temp-file (substring ess-temp-file (match-end 0))) + (ess-sas-goto-shell) + (insert "cd " ess-temp-file-remote-directory "; " ess-kermit-command " -a " + (substring (file-name-nondirectory ess-temp-file) 1) " -g " ess-temp-file) + (comint-send-input) + ;; (insert (read-string "Press Return to connect to Kermit: " nil nil "\C-\\c")) + ;; (comint-send-input) + ;; (insert (read-string "Press Return when Kermit is ready to receive: " nil nil + ;; (concat "receive ]" ess-sas-temp-file))) + ;; (comint-send-input) + ;; (insert (read-string "Press Return when transfer is complete: " nil nil "c")) + ;; (comint-send-input) + (insert (read-string "Press Return when shell is ready: ")) + (comint-send-input) + (switch-to-buffer (find-buffer-visiting ess-temp-file)) + (ess-revert-wisely) + )))) + +(provide 'ess-sas-a) + +;;; ess-sas-a.el ends here diff --git a/elpa/ess-20230419.1527/ess-sas-d.el b/elpa/ess-20230419.1527/ess-sas-d.el new file mode 100644 index 00000000..98afed49 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-sas-d.el @@ -0,0 +1,332 @@ +;;; ess-sas-d.el --- SAS customization -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: Richard M. Heiberger +;; Created: 20 Aug 1997 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This file defines all the SAS customizations for ESS behaviors. See +;; ess-sas-l and ess-sas-a for the underlying general modifications. + +;;; Code: + +(require 'shell) +(require 'ess-sas-l) + +(defcustom SAS-mode-hook nil + "Hook to run when entering SAS mode." + :type 'hook + :group 'ess-sas) + +(defvar inferior-SAS-args "-stdio -linesize 80 -noovp -nosyntaxcheck" + "Arguments to use for starting SAS.") + +(defvar inferior-SAS-args-temp nil + "Hack variable, needed for args preprocessing. +Better logic needed! (see 2 uses, in this file).") + +(defvar SAS-mode-syntax-table + (let ((tab (make-syntax-table))) + (modify-syntax-entry ?\\ "." tab) ;; backslash is punctuation + (modify-syntax-entry ?+ "." tab) + (modify-syntax-entry ?- "." tab) + (modify-syntax-entry ?= "." tab) + (modify-syntax-entry ?% "w" tab) + (modify-syntax-entry ?< "." tab) + (modify-syntax-entry ?> "." tab) + (modify-syntax-entry ?& "w" tab) + (modify-syntax-entry ?| "." tab) + (modify-syntax-entry ?\' "\"" tab) + (modify-syntax-entry ?* ". 23" tab) ; comment character + (modify-syntax-entry ?\; "." tab) + (modify-syntax-entry ?_ "w" tab) + (modify-syntax-entry ?< "." tab) + (modify-syntax-entry ?> "." tab) + (modify-syntax-entry ?/ ". 14" tab) ; comment character + (modify-syntax-entry ?. "w" tab) + tab) + "Syntax table for `SAS-mode'.") + +(defun ess-SAS-pre-run-hook (temp-ess-dialect) + "Set up log and list files for interactive SAS." + + (let* ((ess-shell-buffer-name-flag (get-buffer "*shell*")) + ess-shell-buffer-name + ;; isn't pretty yet. + ;; ess-local-process-name is defined after this function. + ;; it needs to be defined prior to this function. + (tmp-procname (let ((ntry 0) + (done nil)) + ;; find a non-existent process + (while (not done) + (setq ntry (1+ ntry) + done (not + (get-process (ess-proc-name + ntry + temp-ess-dialect))))) + (ess-proc-name ntry temp-ess-dialect))) + ;; Following was tmp-local-process-name. Stolen from inferior-ess + (ess-sas-lst-bufname (concat "*" tmp-procname ".lst*")) + (ess-sas-log-bufname (concat "*" tmp-procname ".log*")) + (explicit-shell-file-name "/bin/sh") + inferior-SAS-redirect-args + ess-sas-lst + ess-sas-log) + + (ess-write-to-dribble-buffer + (format "(ess-SAS-pre-run-hook 1): ess-lang=%s, ess-dialect=%s, temp-dialect=%s, buf=%s \n" + ess-language + ess-dialect + temp-ess-dialect + (current-buffer))) + ;; If someone is running a *shell* buffer, rename it to avoid + ;; inadvertent nuking. + (if ess-shell-buffer-name-flag + (with-current-buffer "*shell*" + (setq ess-shell-buffer-name + (rename-buffer "*ess-shell-regular*" t)))) + + ;; Construct the LST buffer for output + (if (get-buffer ess-sas-lst-bufname) + nil + (with-current-buffer (shell) + (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (sleep-for 2) ; need to wait, else working too fast! + (setq ess-sas-lst (ess-insert-accept "tty")) + (SAS-listing-mode) + (shell-mode) + (ess-listing-minor-mode t) + (rename-buffer ess-sas-lst-bufname t))) + + ;; Construct the LOG buffer for output + (if (get-buffer ess-sas-log-bufname) + nil + (with-current-buffer (shell) + (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (sleep-for 2) ; need to wait, else working too fast! + (setq ess-sas-log (ess-insert-accept "tty")) + ;(SAS-log-mode) + (shell-mode) + (ess-transcript-minor-mode t) + (rename-buffer ess-sas-log-bufname t))) + + (setq inferior-SAS-redirect-args (concat " " + ess-sas-lst + " " + ess-sas-log + " ") + inferior-SAS-args-temp (concat inferior-SAS-redirect-args + inferior-SAS-args)) + + ;; Restore the *shell* buffer + (if ess-shell-buffer-name-flag + (with-current-buffer ess-shell-buffer-name + (rename-buffer "*shell*"))) + + (delete-other-windows) + (split-window-vertically) + (split-window-vertically) + (switch-to-buffer (nth 2 (buffer-list))) + (other-window 2) + (switch-to-buffer ess-sas-log-bufname) + (split-window-vertically) + (other-window 1) + (switch-to-buffer ess-sas-lst-bufname) + (other-window 2) + + ;;workaround + (setq inferior-SAS-program + (concat (file-name-as-directory ess-etc-directory) + "ess-sas-sh-command")) + (setq inferior-ess-program inferior-SAS-program))) + +(defun ess-insert-accept (command) + "Submit command to process, get next line." + (interactive) + (goto-char (point-max)) + (insert command) + (comint-send-input) + (accept-process-output (get-buffer-process (current-buffer)) 0.2) + (forward-line -1) + (let* ((beg (point)) + (ess-tty-name (progn (end-of-line) (buffer-substring beg (point))))) + (goto-char (point-max)) + ess-tty-name)) + + +(defvar SAS-customize-alist + '((ess-local-customize-alist . SAS-customize-alist) + (ess-language . "SAS") + (ess-dialect . "SAS") + (inferior-ess-program . inferior-SAS-program) + (ess-help-sec-regex . "^[A-Z. ---]+:$") + (ess-help-sec-keys-alist . " ") + (ess-object-name-db-file . "ess-sas-namedb.el") + (inferior-ess-objects-command . "objects(%d)");;FIXME + (inferior-ess-help-command . "help(\"%s\",pager=\"cat\",window=F)\n");;FIXME + (inferior-ess-exit-command . "endsas;\n") + (ess-loop-timeout . 500000 ) + (inferior-ess-primary-prompt . "^") + (inferior-ess-secondary-prompt . "^") + (comint-use-prompt-regexp . t) + (inferior-ess-start-args . inferior-SAS-args-temp) + ;; (ess-pre-run-hook . 'ess-SAS-pre-run-hook) + ;; (ess-local-process-name . nil) + ) + "Variables to customize for SAS") + +;;; The functions of interest (mode, inferior mode) + +;;;###autoload +(define-derived-mode SAS-mode ess-mode "[SAS]" + "Major mode for editing SAS source. See `ess-mode' for more help." + :group 'ess-sas + (ess-setq-vars-local SAS-customize-alist) + (setq ess-local-customize-alist SAS-customize-alist) + (setq-local sentence-end ";[\t\n */]*") + (setq-local paragraph-start "^[ \t]*$") + (setq-local paragraph-separate "^[ \t]*$") + (setq-local paragraph-ignore-fill-prefix t) + (setq-local adaptive-fill-mode nil) + (setq-local indent-line-function #'sas-indent-line) + (setq-local comment-start "/*") + (setq-local comment-start-skip "/[*]") + (setq-local comment-end "*/") + (setq-local comment-end-skip "[*]/") + (setq-local comment-column 40) + (setq-local ess-local-process-name nil) + (setq-local tab-stop-list ess-sas-tab-stop-list) + (setq-local font-lock-keywords-case-fold-search t) + ;; Local map settings, AFTER initialization (only if not yet defined) + (unless sas-mode-local-map + (setq sas-mode-local-map (copy-keymap (current-local-map))) + (ess-sas-edit-keys-set ess-sas-edit-keys-toggle) + (if ess-sas-local-unix-keys (ess-sas-local-unix-keys)) + (if ess-sas-local-pc-keys (ess-sas-local-pc-keys)) + (if ess-sas-global-unix-keys (ess-sas-global-unix-keys)) + (if ess-sas-global-pc-keys (ess-sas-global-pc-keys))) + (define-key sas-mode-local-map ";" #'ess-electric-run-semicolon) + (define-key sas-mode-local-map (kbd "\C-c\C-w") #'ess-multi-frame-SAS) + ;; this is a mess + ;; interactive and batch commands share sas-mode-local-map, + ;; but the associated commands are very different + ;; what would be better is two maps like + ;; sas-batch-mode-local-map and sas-interactive-mode-local-map + ;; or smart function definitions that would do the appropriate + ;; thing for either batch or interactive sessions + ;; however, neither of these solutions are planned + ;; therefore, no key definitions can be shared between + ;; batch and interactive at this time, hence the lines that + ;; are commented below: uncomment at your own risk + ;; (define-key sas-mode-local-map "\C-c\C-p" 'ess-sas-file-path) + ;; (define-key sas-mode-local-map "\C-c\C-b" 'ess-sas-submit) + ;; (define-key sas-mode-local-map "\C-c\C-r" 'ess-sas-submit-region) + ;; (define-key sas-mode-local-map "\C-c\C-x" 'ess-sas-goto-log) + ;; (define-key sas-mode-local-map "\C-c\C-y" 'ess-sas-goto-lst) + + (use-local-map sas-mode-local-map) + + (setq font-lock-defaults + ;; KEYWORDS KEYWORDS-ONLY CASE-FOLD ..... + '(SAS-mode-font-lock-defaults nil t))) + + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode)) + +;; rmh Jul 10 2003 +(defun ess-electric-run-semicolon (arg) + "Insert character. +If the line contains \"run;\" or \"quit;\" and nothing else then +indent line." + (interactive "P") + (if ess-sas-edit-keys-toggle + (insert ";") + (if (and (not arg) + (eolp) + (save-excursion + (skip-chars-backward " \t") + (backward-word 1) + (and (looking-at "run\\|quit") + (progn + (skip-chars-backward " \t") + (bolp))))) + (progn + (insert last-command-event) + (funcall indent-line-function) + (save-excursion + (delete-char -1)))) + (self-insert-command (prefix-numeric-value arg)))) + +(defun SAS-menu () + "Start SAS from the menu." + (interactive) + (if ess-microsoft-p + ;; replace with other choices for starting SAS? + (error "SAS cannot be started this way in ESS on Windows.") + (SAS))) + +(defun SAS () + "Call 'SAS', from SAS Institute." + (interactive) + (let* ((temp-dialect "SAS")) ;(cdr (rassoc ess-dialect SAS-customize-alist)))) + (ess-write-to-dribble-buffer + (format "(SAS): ess-dial=%s, temp-dial=%s\n" + ess-dialect + temp-dialect)) + (ess-SAS-pre-run-hook temp-dialect) + (setq ess-eval-visibly-p nil) + ;; FIXME: `inferior-SAS-args' is defined from + ;; `inferior-SAS-args-temp' in `ess-SAS-pre-run-hook' + (let ((inf-buf (inferior-ess nil SAS-customize-alist))) + (with-current-buffer inf-buf + (use-local-map sas-mode-local-map)) + inf-buf))) + +(defun ess-multi-frame-SAS () + "Put running SAS buffers into separate frames. +Load this function M-x load-file essx-sas.el RET. +Then find-file myfile.sas. If myfile.sas is already in a buffer, kill-buffer +it and then find-file it again. +Place the cursor in a myfile.sas buffer. Run SAS with M-x SAS, +Return the cursor to the myfile.sas buffer, +then enter C-c C-w to put *SAS* *SAS.log* *SAS.lst* buffers into +their own frames." + (interactive) + (delete-other-windows) + (with-current-buffer "*SAS*" + (make-frame)) + (with-current-buffer "*SAS.log*" + (make-frame)) + (with-current-buffer "*SAS.lst*" + (make-frame))) + +(defun ess-num-or-zero (arg) + "If a number, then return that number, otherwise return 0." + (or (and (numberp arg) arg) 0)) + + ; Provide package + +(provide 'ess-sas-d) + +;;; ess-sas-d.el ends here diff --git a/elpa/ess-20230419.1527/ess-sas-l.el b/elpa/ess-20230419.1527/ess-sas-l.el new file mode 100644 index 00000000..f6da281c --- /dev/null +++ b/elpa/ess-20230419.1527/ess-sas-l.el @@ -0,0 +1,1774 @@ +;;; ess-sas-l.el --- SAS customization -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Authors: Richard M. Heiberger +;; A.J. Rossini +;; Rodney Sparapani +;; Created: 20 Aug 1997 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This is based upon Version 1.4 of SAS mode: + + +;;; sas-mode: indent, run etc, SAS programs. +;;; Author: Tom Cook +;;; Dept. of Biostatistics +;;; University of Wisconsin - Madison +;;; Madison, WI 53706 +;;; cook@biostat.wisc.edu +;;; +;;; Acknowledgements: +;;; Menu code for XEmacs/Lucid emacs and startup mods +;;; contributed by arossini@biostats.hmc.psu.edu +;;; +;;; Last change: 2/1/95 +;;; Last change: 01/15/02 + +;;; Code: + +(require 'ess-mode) +(require 'ess-sas-a) + +(declare-function SAS-mode "ess-sas-d") + +(put 'ess-transcript-minor-mode 'permanent-local t) +(or (assq 'ess-transcript-minor-mode minor-mode-alist) + (setq minor-mode-alist + (append minor-mode-alist + (list '(ess-transcript-minor-mode " ESStr"))))) + +(put 'ess-listing-minor-mode 'permanent-local t) +(or (assq 'ess-listing-minor-mode minor-mode-alist) + (setq minor-mode-alist + (append minor-mode-alist + (list '(ess-listing-minor-mode " ESSlst"))))) + +(defun ess-transcript-minor-mode (&optional arg) + "Toggle Ess-Transcript minor mode. +With arg, turn Ess-Transcript minor mode on if arg is positive, off +otherwise. See the command `ess-transcript-mode' for more information +on this mode." + (interactive "P") + (setq ess-transcript-minor-mode + (if (null arg) (not ess-transcript-minor-mode) + (> (prefix-numeric-value arg) 0))) + (force-mode-line-update) + (setq mode-line-process + '(" [" ess-local-process-name "]"))) + +(defun ess-listing-minor-mode (&optional arg) + "Toggle Ess-Listing minor mode. +With arg, turn Ess-Listing minor mode on if arg is positive, off +otherwise. Ess-Listing mode is used solely to place an indicator on +the mode line." + (interactive "P") + (setq ess-listing-minor-mode + (if (null arg) (not ess-listing-minor-mode) + (> (prefix-numeric-value arg) 0))) + (force-mode-line-update) + (setq mode-line-process + '(" [" ess-local-process-name "]"))) + +(defcustom ess-automatic-sas-log-or-lst-mode t + "Automatically turn on `SAS-log-mode' and `SAS-listing-mode' when enabled." + :type 'boolean + :group 'ess-sas) + +(defun ess-SAS-log-mode-p () + "Return t when when a SAS log file is detected. +A SAS log is defined as having: + +1. The first line matches \"^1[ \t]*The SAS System\" +2. The file name ends in .log. +" + (and ess-automatic-sas-log-or-lst-mode + (save-excursion + (goto-char (point-min)) + (looking-at "1[ \t]*The SAS System")) + (if (buffer-file-name) + (string-match ".log$" (buffer-file-name)) + t))) + +(defun ess-SAS-listing-mode-p () + "Return t when SAS listing file is detected. +A .lst file is a SAS listing file when: + +1. The file name ends in .lst +2. The corresponding log file exists and is a SAS log file. +" + (when ess-automatic-sas-log-or-lst-mode + (let* ((bfn (buffer-file-name)) + (log (and bfn + (string-match-p "\\.lst$" bfn) + (replace-regexp-in-string "\\.lst$" ".log" bfn)))) + (and log + (file-exists-p log) + (with-temp-buffer + (insert-file-contents log nil 0 200) + (goto-char (point-min)) + (looking-at "1[ \t]*The SAS System")))))) + +(add-to-list 'magic-mode-alist + '(ess-SAS-log-mode-p . SAS-log-mode)) +(add-to-list 'magic-mode-alist + '(ess-SAS-listing-mode-p . SAS-listing-mode)) + +(define-derived-mode SAS-log-mode SAS-mode "ESS[LOG]" + "`ess-transcript-mode' for SAS." + :group 'ess-sas + (ess-transcript-minor-mode 1) + (setq buffer-read-only t) ;; to protect the buffer. + (buffer-disable-undo)) + +(defvar sas-mode-local-map nil "contains modified local keymap for SAS") +(define-derived-mode SAS-listing-mode special-mode "ESS[LST]" + "Fundamental mode with `ess-listing-minor-mode' and read-only." + :keymap sas-mode-local-map + :group 'ess-sas + (ess-listing-minor-mode 1) + (buffer-disable-undo)) + +(defalias 'sas-log-mode #'SAS-log-mode) +(defalias 'SAS-transcript-mode #'SAS-log-mode) +(defalias 'sas-transcript-mode #'SAS-log-mode) +(defalias 'sas-mode #'SAS-mode) +(defalias 'sas-listing-mode #'SAS-listing-mode) + +(defcustom sas-indent-width 4 + "Amount to indent sas statements." + :group 'ess-sas + :type 'integer) + +(defcustom sas-indent-ignore-comment "\\*" + "Comments that start with this regular expression are ignored in indentation." + :group 'ess-sas + :type 'string) + +(defcustom sas-require-confirmation t + "Require confirmation when revisiting a modified sas-output file." + :group 'ess-sas + :type 'boolean) + +(defcustom sas-pre-run-hook nil + "Hook to execute prior to running SAS via `submit-sas'." + :group 'ess-sas + :type 'hook) + +(defcustom sas-notify t + "Beep and display message when job is done." + :group 'ess-sas + :type 'boolean) + +(defcustom sas-error-notify t + "If `sas-notify' t, indicate errors in log file upon completion." + :group 'ess-sas + :type 'boolean) + +(defcustom sas-get-options nil + "Options to be passed to SAS in sas-get-dataset." + :group 'ess-sas + :type '(choice (const nil) string)) + +(defcustom sas-get-options-history nil + "History list of Options passed to SAS in sas-get-dataset." + :type '(choice (const nil) + (string)) + :group 'ess-sas) + +(defcustom sas-page-number-max-line 3 + "Number of lines from the page break, to search for the page +number." + :group 'ess-sas + :type 'integer) + +(defcustom sas-notify-popup nil + "If this and `sas-notify' are t), popup a window when SAS job ends." + :group 'ess-sas + :type 'boolean) + +(defcustom sas-tmp-libname "_tmp_" + "Libname to use for sas-get-dataset." + :group 'ess-sas + :type 'string) + +(defcustom sas-file-name nil + "The name of the current sas file." + :group 'ess-sas + :type '(choice (const nil) file)) + +;; The next two are ``the inside of [...] in a regexp'' to be used in +;; (skip-chars-(for|back)ward SAS-..-chars) +(defcustom sas-white-chars " \t\n\f" + "This does NOT escape blanks (RMH, 2000/03/20)." + :group 'ess-sas + :type 'string) + +(defcustom sas-comment-chars (concat sas-white-chars ";") + "Doc?" + :group 'ess-sas + :type 'string) + +(defcustom ess-sas-run-regexp-opt t + "If you do not want to run regexp-opt, then set to nil." + :group 'ess-sas + :type 'boolean) + +(defvar sas-buffer-name nil) +(defvar sas-file-root nil) +(defvar sas-submitable nil) +(defvar sas-dataset nil) + +(defvar SAS-mode-font-lock-defaults + (if ess-sas-run-regexp-opt + (list + ;; .log NOTE: messages + (cons "^NOTE [0-9]+-[0-9]+: Line generated by the invoked macro" + font-lock-comment-face) + (cons "^NOTE: .*$" font-lock-comment-face) + (cons "^ [^ @].*[.]$" font-lock-comment-face) + (cons "^ [a-z].*[a-z][ ]?$" font-lock-comment-face) + (cons "^ Engine:[ ]+V.+$" font-lock-comment-face) + (cons "^ Physical Name:[ ]+.+$" font-lock-comment-face) + (cons "^ \\(cpu\\|real\\) time[ ]+[0-9].*$" + font-lock-comment-face) + (cons "^ decimal may be shifted by the" + font-lock-comment-face) + (cons "^NOTE: The infile " font-lock-comment-face) + (cons "^NOTE: 1 record was read from the infile " + font-lock-comment-face) + (cons "^NOTE: [1-9][0-9]* records were read from the infile " + font-lock-comment-face) + (cons "^ Filename=.*,$" font-lock-comment-face) + (cons "^ File Name=.*,$" font-lock-comment-face) + (cons "^ File $" font-lock-comment-face) + (cons "^ Name=.*,$" font-lock-comment-face) + (cons "^ File List=(" font-lock-comment-face) + (cons "^ List=(" font-lock-comment-face) + (cons "^ Owner Name=.*,$" font-lock-comment-face) + (cons "^ Access Permission=.*,$" font-lock-comment-face) + (cons "^ Last Modified=.*,?$" font-lock-comment-face) + (cons "^ File Size (bytes)=[0-9]+$" font-lock-comment-face) + (cons "^ Pipe command=" font-lock-comment-face) + (cons "^NOTE: The file " font-lock-comment-face) + (cons "^NOTE: 1 record was written to the file " + font-lock-comment-face) + (cons "^NOTE: [1-9][0-9]* records were written to the file " + font-lock-comment-face) + (cons "^NOTE: PROC LOGISTIC is modeling the probability that" + font-lock-comment-face) + (cons "^NOTE: PROC GENMOD is modeling the probability that" + font-lock-comment-face) + (cons "^1[ ]+The SAS System.*$" font-lock-comment-face) + (cons "^\014.*$" font-lock-comment-face) + (cons "[*][*][*] ANNOTATE macros are now available [*][*][*]" + font-lock-comment-face) + (cons "For further information on ANNOTATE macros, enter," + font-lock-comment-face) + ;; (cons "^SAS/STAT 9.3_M1, SAS/ETS 9.3_M1, SAS/OR 9.3_M1" + ;; font-lock-comment-face) + (cons "\\(or \\)?%HELPANO.*$" + font-lock-comment-face) + (cons "^Local Variables:$" font-lock-comment-face) + (cons "^End:$" font-lock-comment-face) + (cons "^MPRINT([_A-Z0-9]+)" font-lock-comment-face) + + ;; .log ERROR: messages + ; (cons "^ERROR\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$" + (cons "^ERROR\\( [0-9]+-[0-9]+\\)?: .*$" + font-lock-keyword-face) + ; ERROR: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-keyword-face) + ; ERROR #-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-keyword-face) + ; ERROR ##-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-keyword-face) + ; ERROR ###-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-keyword-face) + (cons "^ a format name." font-lock-keyword-face) + (cons "^ where a numeric operand is required. The condition was: " + font-lock-keyword-face) + (cons "[ ][_]+$" font-lock-keyword-face) + + ;; .log WARNING: messages + ;(cons "^WARNING\\( [0-9]+-[1-9][0-9][0-9]\\)?: .*$" + (cons "^WARNING\\( [0-9]+-[0-9]+\\)?: .*$" + font-lock-function-name-face) + ; WARNING: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-function-name-face) + ; WARNING #-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-function-name-face) + ; WARNING ##-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-function-name-face) + ; WARNING ###-###: + (cons "^ [^ @].*\\([.][ ]?[ ]?\\|[,a-z][ ]\\)$" + font-lock-function-name-face) + + ;; SAS comments + ;; /* */ style handled by grammar above + (cons "\\(^[0-9]*\\|[:;!]\\)[ \t]*%?\\*[^;/][^;]*;" + font-lock-comment-face) + + ; these over-rides need to come before the more general declarations + (cons "\\") + ; font-lock-keyword-face) + ; + ;; SAS base and SAS/Graph statements + (cons (concat ;"\\<" + (regexp-opt + '( + "do" "to" "by" "goto" ; "go" + "abort" "and" "array" "assess" "attrib" + "baseline" "bayes" "between" "bivar" "block" "bubble" "bubble2" + "change" "choro" "class" "contains" "contrast" + "delete" "display" "dm" "donut" "drop" + "else" "error" "exchange" "exclude" + "fcs" "file" "filename" "format" "freq" + "footnote" "footnote1" "footnote2" "footnote3" "footnote4" "footnote5" + "footnote6" "footnote7" "footnote8" "footnote9" "footnote10" + "goptions" "grid" ; "ge" "gt" + "hazardratio" "hbar" "hbar3d" + "id" "if" "index" "infile" "informat" "input" ; "is" rarely used, but common false pos. + "keep" + "label" "length" "libname" "like" "link" "lsmeans" ; "le" "lt" + "manova" "means" "merge" "missing" "model" "modify" + "not" "null" ; "ne" "note" + "ods" "options" "output" "otherwise" ; "or" + "pageby" "parms" "pie" "pie3d" "plot" "plot2" "prism" "put" + "random" "rename" "repeated" "retain" + "same" "save" "scatter" "select" "set" "skip" "star" "strata" "sum" "sumby" "surface" + "table" "tables" "test" "then" "time" + "title" "title1" "title2" "title3" "title4" "title5" + "title6" "title7" "title8" "title9" "title10" + "univar" "update" + "value" "var" "vbar" "vbar3d" + "weight" "where" "window" "with" + ; "x" + ) 'words)) ;"\\>") + font-lock-keyword-face) + + ;; SAS/GRAPH statements not handled above + (cons (concat "\\<" + (regexp-opt + '("axis" "legend" "pattern" "symbol")) "\\([1-9][0-9]?\\)?" + "\\>") + font-lock-keyword-face) + + ;; SAS functions and SAS macro functions + (cons "%[a-z_][a-z_0-9]*[(;]" font-lock-function-name-face) + ;(cons "\\" + "("); "[ \t]*(") + font-lock-function-name-face) + ) + (list + ;; .log NOTE: messages + (cons "^NOTE: .*$" font-lock-constant-face) + + ;; .log ERROR: messages + (cons "^ERROR: .*$" font-lock-keyword-face) + + ;; .log WARNING: messages + (cons "^WARNING: .*$" font-lock-function-name-face) + + ;; SAS comments + ;; /* */ handled by grammar above + ;; (list "/\\*.*\\*/" 0 font-lock-comment-face t) + (cons "\\(^[0-9]*\\|;\\)[ \t]*\\(%?\\*\\|comment\\).*\\(;\\|$\\)" font-lock-comment-face) + + ;; SAS execution blocks, DATA/RUN, PROC/RUN, SAS Macro Statements + (cons "\\<%do[ \t]*\\(%until\\|%while\\)?\\>" + font-lock-constant-face) + ;;(cons (concat "\\(^[0-9]*\\|;\\)[ \t]*" + ;;"%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)" + ;;"\\>") font-lock-constant-face) + (cons "\\<%\\(end\\|global\\|local\\|m\\(acro\\|end\\)\\)\\>" + font-lock-constant-face) + + (cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*" + "\\(data\\|endsas\\|finish\\|quit\\|run\\|start\\)[ \t\n;]") + font-lock-constant-face) + (cons (concat "\\(^[0-9]*\\|;\\|):\\|%then\\|%else\\)[ \t]*" + ;;"proc[ \t]+[a-z][a-z_0-9]+") font-lock-constant-face) + "proc[ \t]+" + ;;SAS/Base, SAS/Graph, SAS/FSP and common add-ons + "\\(append" + "\\|b\\(genmod\\|lifereg\\|phreg\\)" + "\\|c\\(a\\(lendar\\|talog\\)\\|port\\|o\\(mpare\\|ntents\\|py\\|rr\\)\\)" + "\\|d\\(atasets\\|bcstab\\|isplay\\)\\|ex\\(plode\\|port\\)" + "\\|f\\(orm\\(at\\|s\\)\\|req\\|s\\(browse\\|edit\\|l\\(etter\\|ist\\)\\|view\\)\\)" + "\\|g?\\(chart\\|p\\(lot\\|rint\\)\\)" + "\\|g\\(anno\\|contour\\|device\\|font\\|\\(key\\)?map\\|options\\|project" + "\\|re\\(duce\\|move\\|play\\)\\|slide\\|testit\\|3\\(d\\|grid\\)\\)" + "\\|\\(map\\|[cg]\\)?import\\|i\\(ml\\|nsight\\)" + "\\|means\\|options\\|p\\(menu\\|rintto\\)" + "\\|r\\(ank\\|e\\(gistry\\|port\\)\\)" + "\\|s\\(ort\\|ql\\|tandard\\|ummary\\)" + "\\|t\\(abulate\\|emplate\\|imeplot\\|ran\\(spose\\|tab\\)\\)\\|univariate" + ;;SAS/Stat and SAS/ETS + "\\|a\\(ceclus\\|nova\\|rima\\|utoreg\\)\\|boxplot" + "\\|c\\(a\\(lis\\|n\\(corr\\|disc\\)\\|tmod\\)\\|itibase\\|luster\\|o\\(mputab\\|rresp\\)\\)" + "\\|discrim\\|expand\\|f\\(a\\(ctor\\|stclus\\)\\|orecast\\|req\\)" + "\\|g\\(enmod\\|l\\(immix\\|m\\(mod\\|power\\|select\\)?\\)\\)\\|inbreed\\|k\\(de\\|rige2d\\)" + "\\|l\\(attice\\|ife\\(reg\\|test\\)\\|o\\(ess\\|gistic\\)\\)" + "\\|m\\(ds\\|ixed\\|o\\(de\\(clus\\|l\\)\\|rtgage\\)\\|ulttest\\)" + "\\|n\\(ested\\|l\\(in\\|mixed\\)\\|par1way\\)\\|orthoreg" + "\\|p\\(dlreg\\|hreg\\|l\\(an\\|s\\)\\|ower\\|r\\(in\\(comp\\|qual\\)\\|obit\\)\\)\\|r\\(sr\\)?eg" + "\\|s\\(core\\|im\\(2d\\|lin\\)\\|pectra\\|t\\(atespace\\|dize\\|epdisc\\)\\|urvey\\(means\\|reg\\|select\\)\\|yslin\\)" + "\\|t\\(phreg\\|pspline\\|r\\(ansreg\\|ee\\)\\|test\\)" + "\\|var\\(clus\\|comp\\|iogram\\)\\|x11" + "\\)") font-lock-constant-face) + + ;;(cons (concat "\\(^[0-9]*\\|;\\|%then\\|%else\\)[ \t]*" + ;;"\\(%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\)" + ;;"\\>") font-lock-constant-face) + (cons "\\<%\\(go[ \t]*to\\|i\\(f\\|n\\(clude\\|put\\)\\)\\|let\\|put\\|sysexec\\)\\>" + font-lock-constant-face) + + (cons "\\<%\\(by\\|else\\|t\\(o\\|hen\\)\\)\\>" + font-lock-constant-face) + + ;; SAS dataset options/PROC statements followed by an equal sign/left parentheses + + (cons (concat + "[ \t(,]" + "\\(attrib\\|by\\|compress\\|d\\(ata\\|rop\\)\\|f\\(irstobs\\|ormat\\)" + "\\|i\\(d\\|f\\|n\\)\\|ke\\(ep\\|y\\)\\|l\\(abel\\|ength\\)" + "\\|o\\(bs\\|rder\\|ut\\)\\|rename\\|s\\(ortedby\\|plit\\)" + "\\|var\\|where\\)" + "[ \t]*=") + font-lock-keyword-face) + (cons "\\<\\(in\\(:\\|dex[ \t]*=\\)?\\|until\\|wh\\(en\\|ile\\)\\)[ \t]*(" + font-lock-keyword-face) + + ;; SAS statements + (cons (concat + "\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*" + "\\(a\\(bort\\|rray\\|ttrib\\)\\|b\\(ayes\\|y\\)" + "\\|c\\(hange\\|lass\\|ontrast\\)" + "\\|d\\(elete\\|isplay\\|m\\|o\\([ \t]+\\(data\\|over\\)\\)?\\|rop\\)" + "\\|e\\(rror\\|stimate\\|xc\\(hange\\|lude\\)\\)" + "\\|f\\(ile\\(name\\)?\\|o\\(otnote\\(10?\\|[2-9]\\)?\\|rmat\\)\\|req\\)" + "\\|go\\([ \t]*to\\|ptions\\)" + "\\|hazardratio\\|[hv]bar\\(3d\\)?" + "\\|i\\(d\\|f\\|n\\(dex\\|f\\(ile\\|ormat\\)\\|put\\|value\\)\\)" + "\\|keep\\|l\\(abel\\|ength\\|i\\(bname\\|nk\\|st\\)\\|smeans\\)" + "\\|m\\(anova\\|e\\(ans\\|rge\\)\\|issing\\|od\\(el\\|ify\\)\\)\\|note" + "\\|o\\(ds\\|ptions\\|therwise\\|utput\\)\\|p\\(arms\\|lot2?\\|ut\\)" + "\\|r\\(andom\\|e\\(name\\|peated\\|tain\\)\\)" + "\\|s\\(ave\\|e\\(lect\\|t\\)\\|kip\\|trata\\|um\\(by\\)?\\)" + "\\|t\\(ables?\\|i\\(me\\|tle\\(10?\\|[2-9]\\)?\\)\\)\\|update" + "\\|va\\(lue\\|r\\)\\|w\\(eight\\|here\\|i\\(ndow\\|th\\)\\)" + + ;; IML statements that are not also SAS statements + "\\|append\\|c\\(lose\\(file\\)?\\|reate\\)\\|edit\\|f\\(ind\\|orce\\|ree\\)" + "\\|insert\\|load\\|mattrib\\|p\\(a[ru]se\\|rint\\|urge\\)" + "\\|re\\(move\\|peat\\|place\\|set\\|sume\\)" + "\\|s\\(et\\(in\\|out\\)\\|how\\|ort\\|tore\\|ummary\\)\\|use\\)?" + + "\\>") font-lock-keyword-face) + + + + ;; (cons "\\<\\(\\(then\\|else\\)[ \t]*\\)?\\(do\\([ \t]*over\\)?\\|else\\)\\>" + ;; font-lock-keyword-face) + + ;; SAS statements that must be followed by a semi-colon + (cons (concat + "\\(^[0-9]*\\|):\\|[;,]\\|then\\|else\\)[ \t]*" + "\\(cards4?\\|datalines\\|end\\|l\\(ostcard\\)\\|page\\|stop\\)?" + "[ \t]*;") font-lock-keyword-face) + + ;; SAS/GRAPH statements not handled above + (cons (concat + "\\(^[0-9]*\\|):\\|[;,]\\)[ \t]*" + "\\(axis\\|legend\\|pattern\\|symbol\\)" + "\\([1-9][0-9]?\\)?\\>") font-lock-keyword-face) + + ;; SAS Datastep functions and SAS macro functions + ;(cons "%[a-z_][a-z_0-9]*[ \t]*[(;]" + ;; SAS macro functions occasionally defined with no arguments + ;; which means they can be followed by any character that can + ;; separate tokens, however, they are most likely to be followed + ;; by operat-ions/ors + (cons "%[a-z_][a-z_0-9]*[- \t();,+*/=<>]" + font-lock-function-name-face) + (cons "\\ (- (point-max) pos) (point)) + (goto-char (- (point-max) pos))))) + + +;;(defun sas-indent-region (start end) +;; "Indent a region of SAS code." +;; (interactive "r") +;; (save-excursion +;; (let ((endmark (copy-marker end))) +;; (goto-char start) +;; (and (bolp) (not (eolp)) +;; (sas-indent-line)) +;; (indent-sexp endmark) +;; (set-marker endmark nil)))) + + +(defun indent-sas-statement (arg) + "Indent all continuation lines sas-indent-width spaces from first +line of statement." + (interactive "p") + (let (end) + (save-excursion + (if (> arg 0) + (while (and (> arg 0) (search-forward ";" (point-max) 1 1)) + (setq end (point)) + (if (bobp) nil (backward-char 1)) + (beginning-of-sas-statement 1) + (forward-char 1) + (indent-region (point) + end + (+ (current-column) (1- sas-indent-width))) + (search-forward ";" (point-max) 1 1) + (setq arg (1- arg))))))) + +;; added 9/31/94 +(defun sas-next-statement-indentation () + "Returns the correct indentation of the next sas statement. +The current version assumes that point is at the end of the statement. +This will (hopefully) be fixed in later versions." + (if (bobp) 0 + (save-excursion + (let ((prev-end (point))) + (beginning-of-sas-statement 1) + (while (and (not (bobp)) + (not (looking-at "\\*/")) + (looking-at sas-indent-ignore-comment)) + (skip-chars-backward sas-white-chars) + (if (bobp) nil + (backward-char 1)) + (setq prev-end (point)) + (beginning-of-sas-statement 1 t)) + (if (or + (looking-at + (concat "data[ \n\t;]\\|" + (regexp-opt '("cards;" "cards4;" "datalines;" "datalines4;" "lines;" "lines4;")) + "\\|proc[ \n\t]\\|%?do[ \n\t;]\\|%macro[ \n\t]\\|/\\*")) + (save-excursion + (re-search-forward + "\\b%?then\\>[ \n\t]*\\b%?do\\>\\|\\b%?else\\>[ \n\t]*\\b%?do\\>" + prev-end 1 1))) ; fixed 1/30/95 to avoid being fooled by + ; variable names starting with "do" + (+ (current-indentation) sas-indent-width) + (if (looking-at "%?end[ ;\n]\\|%mend[ ;\n]\\|\\*/") + (max (- (current-indentation) sas-indent-width) 0) + (current-indentation))))))) + +;; added 2/1/95 +(defun sas-comment-start-col () + "If the current line is inside a /* */ comment, returns column in which the +opening /* appears. returns 0 otherwise." + (let ((pos (point))) + (save-excursion + (if (and (search-backward "*/" (point-min) 1 1) + (search-forward "/*" pos 1 1)) + (current-indentation) + 0)))) + + +;; Created 6/27/94 to verify that RUN; statements match PROC and DATA +;; statements. Useful since indentation my be goofy w/o "RUN;" +(defun sas-check-run-statements () + "Check to see that \"run\" statements are matched with proc, data statements." + (interactive) + (let (pos + (ok t) + (eob-ok t)) + (save-excursion + (beginning-of-line) + (while ok + (if (re-search-forward + "\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)" + nil 1) + (if (match-beginning 2) + (if (re-search-forward + "\\(^[ \t]*run[ ;]\\)\\|\\(^[ \t]*proc \\|^[ \t]*data[ ;]\\)" + nil t) + (progn (setq pos (point)) + (setq ok (match-beginning 1))) + (setq eob-ok nil pos (point-max)))) + (setq ok nil))) + (setq ok (eobp))) + (if (and ok eob-ok) (message "Run statements match") + (goto-char pos) + (beep) + (message "Missing Run Statement.")))) + +(defun sas-fix-life-tables () + "Remove censored and duplicate observations from life tables generated by +Proc Lifetest. Operates on current region. A major space saver if there is +heavy censoring." + (interactive) + (if buffer-read-only (setq buffer-read-only nil)) + (goto-char (point-min)) + (while (re-search-forward "^.*[ ]+[.][ ]+[.][ ]+[.][ ]+.*$" nil t) + (replace-match "" nil nil))) + ; (save-excursion + ; (shell-command-on-region + ; start end + ; "sed '/[ ][.][ ]/d'" t))) +;;"sed \"\\? *\\. *\\. *\\. ?d\"" t))) +;;(vip-goto-line 1) +;;(setq ex-g-flag nil +;;ex-g-variant nil) +;;(vip-ex "1,$g/ \\. \\. \\. /d"))) + +(defun sas-fix-page-numbers (offset &optional page-num) + "Fix number of current page in sas output files after editing. Add +OFFSET to actual page number." + (interactive "P") + (if (not offset) (setq offset 0)) + (if (not page-num) (setq page-num (sas-page-number))) + (save-excursion + (if (/= (preceding-char) ?\C-l) (backward-page 1)) + (let (end len mstart mend) + (save-excursion + (forward-line sas-page-number-max-line) + (setq end (point))) + (if (re-search-forward + "\\(^[0-9]+[ ]\\)\\|\\([ ][0-9]+$\\)" + end t) + (progn (setq len (- (match-end 0) (match-beginning 0)) + mstart (match-beginning 0) + mend (match-end 0)) + (delete-region mstart mend) + (if (eolp) + (insert (format + (concat "%" len "d") (+ page-num offset))) + (insert (substring + (concat (+ (sas-page-number) offset) " ") + 0 len)))))))) + +(defun sas-page-fix (start) + "Fix page numbers in sas output from point to end of file. +If START is given this will be the number for the current page." + (interactive "P") + (let (offset (pnum (sas-page-number))) + (if (not start) (setq offset 0) + (setq offset (- start pnum))) + (while (not (eobp)) + (sas-fix-page-numbers offset pnum) + (setq pnum (1+ pnum)) + (forward-page 1)))) + +(defun fix-page-breaks () + "Fix page breaks in SAS 6 print files." + (interactive) + (save-excursion + (goto-char (point-min)) + (if (looking-at "\f") (delete-char 1)) + ;(replace-regexp "^\\(.+\\)\f" "\\1\n\f\n") + (while (re-search-forward "^\\(.+\\)\f" nil t) + (replace-match "\\1\n\f\n" nil nil)) + (goto-char (point-min)) + ;(replace-regexp "^\f\\(.+\\)" "\f\n\\1") + (while (re-search-forward "^\f\\(.+\\)" nil t) + (replace-match "\f\n\\1" nil nil)) + ; (goto-char (point-min)) + ;(replace-regexp " $" "") + ;(while (re-search-forward "$" nil t) + ; (replace-match "" nil nil)) + (goto-char (point-min)) + ;(replace-regexp " \\([^\\$]+\\)" "\n\\1") + (while (re-search-forward " \\([^\\$]+\\)" nil t) + (replace-match "\n\\1" nil nil)) + (goto-char (point-max)) + (if (not (bobp)) + (progn (backward-char 1) + (if (not (looking-at "\n")) + (progn (forward-char 1) (open-line 1))))))) + +(defun sas-page-number () + ;; like what-page except it returns an integer page number + "Return page number of point in current buffer." + (let ((opoint (point))) (save-excursion + (goto-char (point-min)) + (1+ (sas-how-many page-delimiter opoint))))) + +(defun sas-how-many (regexp &optional end) + ;; a copy of `how-many' which returns an integer + ;; rather than a message + "Return number of matches for REGEXP following point." + (let ((count 0) opoint) + (save-excursion + (while (and (not (eobp)) + (progn (setq opoint (point)) + (re-search-forward regexp end t))) + (if (= opoint (point)) + (forward-char 1) + (setq count (1+ count)))) + count))) + +(defun beginning-of-sas-proc () + "Move point to beginning of sas proc, macro or data step." + (interactive) + (let ((case-fold-search t)) + (forward-char -1) + (while (not (or (looking-at "data\\|proc\\|%macro") + (bobp))) + (re-search-backward "proc\\|data\\|%macro" (point-min) 1) + (beginning-of-sas-statement 1)))) + +(defun next-sas-proc (arg) + "Move point to beginning of next sas proc." + (interactive "P") + (let ((case-fold-search t)) + (forward-char 1) + (if (re-search-forward + "^[ \t]*\\(data[ ;]\\|proc[ ;]\\|endsas[ ;]\\|g?options[ ;]\\|%macro[ ;]\\)" + nil t arg) + (beginning-of-sas-statement 1) + (forward-char -1)))) + +(defun set-sas-file-name () + "Stores the name of the current sas file." + (let ((name (buffer-file-name))) + (cond ((not name)) + ((string-match (substring name -4 nil) + "\\.sas\\|\\.lst\\|\\.log") + + (setq sas-file-name (substring name 0 (- (length name) 4))) + (setq sas-buffer-name (buffer-name)) + (setq sas-file-root (substring sas-buffer-name 0 + (- (length sas-buffer-name) 4)))) + (t (message "This file does not have a standard suffix"))))) + +;; created 6/27/94 +(defun sas-set-alternate-file-name (name) + "Stores the NAME of an alternate sas file. +When this file is submitted with `submit-sas', the alternate file will +be submitted instead. `sas-submitable' is automatically sets to t." + (interactive "f") + (cond ((string-match (substring name -4 nil) + "\\.sas\\|\\.lst\\|\\.log") + (setq sas-file-name (substring name 0 (- (length name) 4))) + (setq sas-submitable t)) + (t (message "This file does not have a standard suffix")))) + +(defun switch-to-sas-source () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file "sas")) + +(defun switch-to-sas-lst () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file "lst")) + +(defun switch-to-sas-log () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file "log")) + +(defun switch-to-sas-source-other-window () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file-other-window "sas")) + +(defun switch-to-sas-lst-other-window () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file-other-window "lst")) + +(defun switch-to-sas-log-other-window () + "Switches to sas source file associated with the current file." + (interactive) + (switch-to-sas-file-other-window "log")) + +;;(defun switch-to-sas-file (suff &optional revert silent) +;; "Switches to sas \"SUFF\" file associated with the current file" +;; (let* ((sfile sas-file-name) +;; (buf (get-file-buffer (concat sfile "." suff))) +;; (sas-require-confirmation +;; (and sas-require-confirmation (not revert)))) +;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) +;; (find-file (concat sfile "." suff)) +;; (progn (switch-to-buffer buf) +;; (if (not (verify-visited-file-modtime (current-buffer))) +;; (progn (revert-buffer t t) +;; (if (not silent) +;; (message "File has changed on disk. Buffer automatically updated.")))))) +;; (setq sas-file-name sfile)) +;; (if (string-equal suff "sas") +;; (if (not (string-equal major-mode "sas-mode")) +;; (sas-mode)) +;; (if (not (string-equal major-mode "sasl-mode")) +;; (sasl-mode)))) +;; +;;(defun switch-to-sas-file-other-window (suff) +;; "Switches to sas \"SUFF\" file associated with the current file" +;; (let* ((sfile sas-file-name) +;; (buf (get-file-buffer (concat sfile "." suff)))) +;; (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) +;; (find-file-other-window (concat sfile "." suff)) +;; (progn (switch-to-buffer-other-window buf) +;; (if (not (verify-visited-file-modtime (current-buffer))) +;; (progn (revert-buffer t t) +;; (message "File has changed on disk. Buffer automatically updated."))))) +;; (setq sas-file-name sfile)) +;; (if (string-equal suff "sas") +;; (if (not (string-equal major-mode "sas-mode")) +;; ;;(sas-mode) +;; ) +;; (if (not (string-equal major-mode "sasl-mode")) +;; ;;(sasl-mode) +;; ))) + +(defun switch-to-sas-file (suff) + "Switches to sas \"SUFF\" file associated with the current file." + (switch-to-buffer (set-sas-file-buffer suff))) + +(defun switch-to-sas-file-other-window (suff) + "Switches to sas \"SUFF\" file associated with the current file." + (switch-to-buffer-other-window (set-sas-file-buffer suff))) + +;; The following was created 6/7/94 to handle buffers without messing up +;; windows. + +(defun set-sas-file-buffer (suff &optional revert silent) + "Sets current buffer to sas \"SUFF\" file associated with the current file." + (let* ((sfile sas-file-name) + (buf (get-file-buffer (concat sfile "." suff))) + (sas-require-confirmation + (and sas-require-confirmation (not revert)))) + (if (or sas-require-confirmation (string-equal suff "sas") (not buf)) + (set-buffer (find-file-noselect (concat sfile "." suff))) + (progn (set-buffer buf) + (if (not (verify-visited-file-modtime (current-buffer))) + (progn (revert-buffer t t) + (if (not silent) + (message "File has changed on disk. Buffer automatically updated.")))))) + (setq sas-file-name sfile)) + ;;(if (string-equal suff "sas") + ;; (if (not (string-equal major-mode "sas-mode")) (sas-mode)) + ;; (if (not (string-equal major-mode "sasl-mode"))(sasl-mode)) + (current-buffer)) + +(defun switch-to-sas-process-buffer () + "Switch to sas-process-buffer." + (interactive) + (let (buf proc-name) + (setq proc-name (concat "SAS" sas-file-name) + buf (concat "*" proc-name "*")) + (switch-to-buffer-other-window buf))) + +(defun submit-sas () + ;; 6/17/94 added sas-submitable local variable. + "Submit SAS file as shell command." + (interactive) + (if ;; can file be run, or is it only for inclusion? + (or sas-submitable + (progn + (beep) + (y-or-n-p + (format + "Submission is disabled for this file. Submit it anyway? ")))) + (progn + ;; if buffer name has changed, tell user + (if (or + (string-equal sas-buffer-name (buffer-name)) + (not + (y-or-n-p + (format + "The name of this buffer has changed. Submit the new file? ")))) + (setq sas-buffer-name (buffer-name)) + (set-sas-file-name)) + (let ((sas-file sas-file-name) + (sas-root sas-file-root) + ;;(sas-buf sas-buffer-name) + proc-name + buf) + + ;; Save buffer to SAS the right file :-). + (if (buffer-modified-p) + (if (y-or-n-p (format "Buffer %s is modified. Save it? " + (buffer-name))) + (save-buffer))) + (setq proc-name (concat "SAS" sas-file) + buf (concat "*" proc-name "*")) + (if (get-buffer buf) + (save-window-excursion (switch-to-buffer buf) + (erase-buffer) + (setq default-directory + (file-name-directory sas-file)))) + + (run-hooks 'sas-pre-run-hook) ;; added 8/24/94 + (message "---- Submitting SAS job ----") + ;; (switch-to-buffer buf) + (make-comint proc-name + sas-program ;added sas-program 4/29/94 + nil + sas-root) + (save-window-excursion + (switch-to-buffer buf) + (setq sas-file-name sas-file) + (bury-buffer buf)) + + (message "---- SAS job submitted ---- ") + + (if sas-notify;; added 4/7/94 + (set-process-sentinel (get-process proc-name) #'sas-sentinel) + (display-buffer buf t)))) + (message "---- File not submitted ----"))) + +;; 5/2/94 Modified sas-sentinel to check for errors in log file upon +;; completion. +(defun sas-sentinel (proc arg);; created 4/7/94 + "Notify user that SAS run is done." + (beep) + ;;(if (string-equal arg "finished\n") + (save-excursion + (let (msg buf win (sbuf (concat "*" (process-name proc) "*"))) + (setq msg + (format "SAS %s %s" + (substring arg 0 -1) + (if sas-error-notify + ;;(save-window-excursion + (progn + (set-buffer sbuf) + (setq buf (set-sas-file-buffer "log" t t)) + (goto-char (point-min)) + (setq win (get-buffer-window buf)) + (save-window-excursion + (if win + (progn + (select-window win) + (if (re-search-forward "^ERROR" nil t) + " (See .log file for errors)" + "")) + (switch-to-buffer buf) + (if (re-search-forward "^ERROR" nil t) + " (See .log file for errors)" + "")))) + ""))) + (set-buffer sbuf) + (goto-char (point-max)) + (insert msg) + (bury-buffer (get-buffer sbuf)) + ;;(if (and sas-notify-popup window-system) + ;; (x-popup-dialog t + ;; (list "SAS Menu" (cons msg nil) ))) + ;;(if (not (minibuffer-window-active-p)) (princ msg)) + (princ msg)))) + +;; 5/2/94 Modified run-sas-on-region to separate log and output buffers. +;; +;;(defun run-sas-on-region (start end append &optional buffer) +;; "Submit region to SAS" +;; (interactive "r\nP") +;; (message "---- Running SAS ----") +;; (let ((sfile sas-file-name) +;; (shell-file-name "/bin/sh") +;; serror buff) +;; (setq buffer (or buffer "*SAS output*")) +;; (save-excursion +;; (shell-command-on-region +;; start end;; added sas-program +;; (concat sas-program " -nonews -stdio 2> /tmp/_temp_.log" nil)) +;; (get-buffer-create "*SAS Log*") +;; (save-window-excursion +;; (switch-to-buffer "*SAS Log*") +;; (erase-buffer) +;; (insert-file-contents "/tmp/_temp_.log") +;; (delete-file "/tmp/_temp_.log") +;; (setq serror (re-search-forward "^ERROR" nil t)) +;; (if serror () (bury-buffer))) +;; (setq buff (get-buffer-create buffer)) +;; (save-window-excursion +;; (switch-to-buffer buff) +;; (setq sas-file-name sfile) +;; (if append +;; (progn +;; (end-of-buffer) +;; (insert "\f\n")) +;; (erase-buffer)) +;; (if (get-buffer "*Shell Command Output*") +;; (progn (insert-buffer "*Shell Command Output*") +;; (kill-buffer "*Shell Command Output*")) +;; (insert "SAS completed with no output.")) +;; (if append () (sasl-mode)) +;; (message "---- SAS Complete ----"))) +;; (if (not serror) +;; (switch-to-buffer-other-window buff) +;; (switch-to-buffer-other-window "*SAS Log*") +;; (goto-char serror) +;; (beep) +;; (message "Error found in log file.") +;; ))) + +(defun switch-to-dataset-log-buffer () + "Switch to log buffer for run-sas-on-region." + (interactive) + (switch-to-buffer-other-window "*SAS Log*")) + +(defun switch-to-dataset-source-buffer () + "Switch to source buffer for run-sas-on-region." + (interactive) + (switch-to-buffer-other-window (format " *sas-tmp-%s*" sas-dataset))) + +;;(defun sas-get-dataset (filename &optional arg opts-p append buffer vars) +;; "Run proc contents and proc print on SAS dataset. Automatically prompts +;;for SAS options to use. Default options are defined by the variable +;;`sas-get-options'. Output may be updated from within output buffer with +;;C-cr if dataset changes. Also, the source code which generates the output +;;may be edited with C-cs. Typing C-cr within the output buffer reexecutes +;;the (modified) source code." +;; (interactive "fName of SAS dataset (file name):") +;; (let ((file (file-name-nondirectory filename)) +;; (dir (file-name-directory filename)) +;; (opts sas-get-options) +;; (minibuffer-history sas-get-options-history) +;; buf); fsize) +;; (setq buffer (or buffer (concat "*" file "*"))) +;; (setq opts (if opts-p opts (read-string "SAS options: " opts))) +;; (setq sas-get-options-history minibuffer-history) +;; (cond ((string-match (substring file -6 nil) "\\.ssd01") +;; (setq file (substring file 0 (- (length file) 6)))) +;; (t (error "This file is not a SAS dataset."))) +;; (setq buf (format " *sas-tmp-%s*" file)) +;; (get-buffer-create buf) +;; (save-window-excursion +;; (switch-to-buffer buf) +;; (erase-buffer) +;; (setq default-directory dir) +;; (if opts +;; (insert (format "options %s ;\n" opts))) +;; (insert (format "title \"Contents of SAS dataset `%s'\" ;\n" file)) +;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir)) +;; (if (not (equal arg 1)) +;; (insert (format "proc contents data = %s.%s ;\n" sas-tmp-libname file))) +;; (if (equal arg 2) () +;; (insert (format "proc print data = %s.%s ;\n" sas-tmp-libname file)) +;; (if vars (insert (format " var %s ;\n" vars)))) +;; (run-sas-on-region (point-min) (point-max) append +;; buffer) +;; (get-buffer buffer) +;; (if append () (sasd-mode)) ;; added 5/5/94 +;; (setq sas-dataset file)) +;; (if (get-buffer-window buffer t) +;; (raise-frame (window-frame (get-buffer-window buffer t))) +;; (display-buffer buffer (not append))) +;; )) + +;;(defun revert-sas-dataset () +;; "Revert current sas dataset from disk version" +;; (interactive) +;; (let* ((file sas-dataset) +;; (buf (format " *sas-tmp-%s*" file)) +;; (pos (point))) +;; (save-window-excursion +;; (switch-to-buffer buf) +;; (run-sas-on-region (point-min) (point-max) nil +;; (concat "*" file ".ssd01*")) +;; ) +;; (goto-char pos) ;; added 6/9/94 +;; (sasd-mode) ;; added 5/5/94 +;; (setq sas-dataset file))) + +(defun sas-insert-local-variables () ;; created 6/17/94 + "Add local variables code to end of sas source file." + (interactive) + (save-excursion + (if (re-search-forward "\\* *Local Variables: *;" nil t) + () + (goto-char (point-max)) + (insert " + +** Local Variables: ; +** End: ; +page ; +")))) + + +;; variables section +(defvar sas-dir-mode-map nil) +(defvar-local sas-directory-name nil + "Name of directory associated with this buffer.") +(defvar-local sas-dir-buf-end nil) +(defvar-local sas-sorted-by-num nil) +;; user variables + +;; keymaps etc... + +(if sas-dir-mode-map () + (setq sas-dir-mode-map (make-sparse-keymap)) + (define-key sas-dir-mode-map "m" #'sas-mark-item) + (define-key sas-dir-mode-map "u" #'sas-unmark-item) + (define-key sas-dir-mode-map " " #'sas-next-line) + (define-key sas-dir-mode-map "\C-n" #'sas-next-line) + (define-key sas-dir-mode-map "\C-p" #'sas-prev-line) + (define-key sas-dir-mode-map "\177" #'sas-prev-line-undo) + (define-key sas-dir-mode-map "\C-b" #'sas-backward-page-narrow) + (define-key sas-dir-mode-map "\C-v" #'sas-forward-page-narrow) + (define-key sas-dir-mode-map "\C-m" #'sas-goto-dataset) + (define-key sas-dir-mode-map "t" #'sas-dir-goto-page) + (define-key sas-dir-mode-map "q" #'bury-buffer) + (define-key sas-dir-mode-map "1" #'digit-argument) + (define-key sas-dir-mode-map "2" #'digit-argument) + (define-key sas-dir-mode-map "3" #'digit-argument) + (define-key sas-dir-mode-map "4" #'digit-argument) + (define-key sas-dir-mode-map "5" #'digit-argument) + (define-key sas-dir-mode-map "6" #'digit-argument) + (define-key sas-dir-mode-map "7" #'digit-argument) + (define-key sas-dir-mode-map "8" #'digit-argument) + (define-key sas-dir-mode-map "9" #'digit-argument) + (define-key sas-dir-mode-map [menu-bar sas run] + '("Submit File " . submit-sas)) + ) + +(define-derived-mode sas-dir-mode special-mode "SAS" + "Major mode for managing sas files." + :group 'ess-sas + (setq sas-directory-name (expand-file-name default-directory))) + + +;;(defun sas-make-library (directory &optional update) +;; "Create a buffer with the names of all sas datasets from DIRECTORY." +;; (interactive "DDirectory Name: ") +;; (let ((dir (expand-file-name directory)) buf out cont pos) +;; (setq buf (format " *sas-tmp-%s*" dir)) +;; (setq out (concat "*SAS-dir-" dir)) +;; (setq cont (concat "*SAS-cont-" dir)) +;; (get-buffer-create buf) +;; (if (get-buffer out) +;; (if update +;; (progn +;; (set-buffer out) +;; (setq buffer-read-only nil))) +;; (setq update t)) +;; (pop-to-buffer out) +;; (setq default-directory dir) +;; (setq pos (point)) +;; (if update +;; (progn +;; (save-window-excursion +;; (set-buffer buf) +;; (erase-buffer) +;; (setq default-directory dir) +;; (insert "options linesize=70 pagesize=1000 ;\n") +;; (insert (format "title \"Contents of SAS directory `%s'\" ;\n" +;; dir)) +;; (insert (format "libname %s '%s' ;\n" sas-tmp-libname dir)) +;; (insert (format "proc contents data = %s._all_ directory details memtype=data ;\n" sas-tmp-libname)) +;; (run-sas-on-region (point-min) (point-max) nil +;; out) +;; (set-buffer out) +;; (goto-char (point-min)) +;; (if (= (sas-how-many page-delimiter (point-max)) 0) +;; (let ((buffer-read-only nil)) +;; (erase-buffer) +;; (insert "There are no SAS datasets in this directory") +;; (pop-to-buffer out)) +;; (save-excursion +;; (set-buffer (get-buffer-create cont)) +;; (setq buffer-read-only t) +;; (let ((buffer-read-only nil)) +;; (erase-buffer) +;; (insert-buffer out) +;; (delete-region (point-min) +;; (or (re-search-forward page-delimiter nil t) +;; (point-min))) +;; (sas-page-fix 1) +;; (goto-char (point-min)) +;; (sas-dir-mode) +;; (sas-narrow-to-page))) +;; (if (re-search-forward page-delimiter nil t) +;; (delete-region (progn (beginning-of-line) (point)) +;; (point-max))) +;; (sas-insert-set-properties (point-min) (point-max)) +;; ) +;; (switch-to-buffer out t) +;; (goto-char (point-min)) +;; (sas-dir-mode) +;; (setq sas-dir-buf-end (point-max))) +;; (goto-char pos) +;; (sas-move-to-filename (point-max)))))) + + +(defun sas-move-to-filename (&optional eol) + (or eol (setq eol (progn (end-of-line) (point)))) + (beginning-of-line) + (if (re-search-forward "\\(^ *[0-9]+ *<*\\)[^:0-9\n]" eol t) + (goto-char (match-end 1)))) + +(defun sas-next-line (arg) + "Move down one line." + (interactive "p") + (forward-line arg) + (sas-move-to-filename (point-max))) +;;(and (< (point) sas-dir-buf-end) +;;(forward-line arg) +;;(sas-move-to-filename sas-dir-buf-end))) + +(defun sas-prev-line (&optional _arg) + "Move up one line." + (interactive) + (beginning-of-line) + (re-search-backward "^ *[0-9]+ *<*[^:0-9\n]" (point-min) t) + (sas-move-to-filename sas-dir-buf-end)) + +(defun sas-insert-set-properties (beg end) + (save-excursion + (goto-char beg) + (while (< (point) end) + (if (sas-move-to-filename) + (put-text-property (point) + (+ 8 (point)) + 'mouse-face 'highlight)) + (forward-line 1)))) + +(defun sas-get-filename () + "Return name of dataset on current line." + (interactive) + (save-excursion + (if (string-equal "*SAS-dir" (substring (buffer-name) 0 8)) + (sas-move-to-filename) + (goto-char (point-min)) + (re-search-forward "Data Set Name: [^.]*\\.")) + (expand-file-name + (downcase (concat sas-directory-name + (buffer-substring + (point) + (save-excursion + (skip-chars-forward "A-Z0-9_") + (point))) ".ssd01"))))) + +(defun sas-get-file-number () + "Return name of dataset on current line." + (interactive) + (if (sas-move-to-filename) + (progn (forward-word -1) + (re-search-forward "[0-9]*") + (string-to-number + (buffer-substring (match-beginning 0) + (match-end 0)))))) + +(defun sas-goto-page (arg) + "Goto top of page ARG. If no ARG, then goto top of file." + (interactive "P") + (goto-char 1) + (if arg + (if (> arg 1) + (progn + (re-search-forward page-delimiter (point-max) 1 (1- arg))))) + (skip-chars-forward sas-white-chars); was " \f\n" till 5.1.13 + (recenter 1)) + +(defun forward-page-top-of-window (arg) + "Move forward to page boundary and leave first line at top of window. +With arg, repeat, or go back if negative. A page boundary is any line +whose beginning matches the regexp `page-delimiter'." + (interactive "p") + (forward-page arg) + (recenter 0)) + +(defun backward-page-top-of-window (arg) + "Move backward to page boundary and leave first line at top of window. +With arg, repeat, or go back if negative. A page boundary is any line +whose beginning matches the regexp `page-delimiter'." + (interactive "p") + (forward-page (- arg)) + (recenter 0)) + +(defun sas-narrow-to-page () + (save-excursion + (let* ((min (point-min)) + (max (point-max))) + ;;(omin (point-min)) + ;;(omax (point-max))) + (if (or (bolp) (beginning-of-line) + (looking-at page-delimiter)) + (forward-char 1) + (forward-page -1)) + (setq min (point)) + (forward-page 1) + (beginning-of-line) + (setq max (point)) + (narrow-to-region min max)))) + +(defun sas-forward-page-narrow (arg) + "Move forward to page boundary and narrow to page. +With arg, repeat, or go back if negative. A page boundary is any line +whose beginning matches the regexp `page-delimiter'." + (interactive "p") + (widen) + (forward-page arg) + (sas-narrow-to-page) + (goto-char (point-min))) + +(defun sas-backward-page-narrow (arg) + "Move backward to page boundary and narrow to page. +With arg, repeat, or go back if negative. A page boundary is any line +whose beginning matches the regexp `page-delimiter'." + (interactive "p") + (goto-char (point-min)) + (widen) + (forward-page (- arg)) + (sas-narrow-to-page)) + +(defun sas-goto-dataset (&optional page) + (interactive) + (and sas-directory-name + (let ((page (or page (sas-get-file-number)))) + ;;(dir sas-directory-name)) + (if page + (progn + (switch-to-buffer-other-window + (concat "*SAS-cont-" sas-directory-name)) + (widen) + (sas-goto-page page) + (sas-narrow-to-page) + (goto-char (point-min))))))) + + +(defun sas-dir-goto-page (page) + (interactive "p") + (widen) + (sas-goto-page page) + (sas-narrow-to-page)) + +(defun sas-mark-item (&optional next) + (interactive) + (sas-move-to-filename) + (beginning-of-line) + (let ((buffer-read-only nil)) + (if (re-search-forward "^\\( *[0-9]+ *\\) \\([A-Z][A-Z_0-9]*\\) " + (save-excursion (end-of-line) (point)) t) + (replace-match "\\1<\\2>"))) + (or next (sas-next-line 1))) + +(defun sas-unmark-item () + (interactive) + (save-excursion + (beginning-of-line) + (let ((buffer-read-only nil)) + (if (re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>" + (save-excursion (end-of-line) (point)) t) + (replace-match "\\1 \\2 "))))) + +(defun sas-prev-line-undo (arg) + (interactive "p") + (sas-prev-line arg) + (sas-unmark-item) + (sas-move-to-filename)) + +(defun sas-create-var-string () + (and (string-equal "*SAS-cont" (substring (buffer-name) 0 9)) + (let (str) + (goto-char (point-min)) + (while + (re-search-forward "^\\( *[0-9]+ *\\)<\\([A-Z][A-Z_0-9]*\\)>" + nil t) + (setq str (concat str " " (buffer-substring (match-beginning 2) + (match-end 2))))) + str))) + + +(defun ess-imenu-SAS (&optional _arg) + "SAS language Imenu support for ESS." + (interactive) + (setq imenu-generic-expression + '( (nil "[ \t\n=]\\([[:alpha:]_][[:alnum:]_]*[.][[:alpha:]_][[:alnum:]_]*\\)[ ,()\t\n;]" 1))) + (imenu-add-to-menubar "SAS Datasets")) + +(provide 'ess-sas-l) + +;;; ess-sas-l.el ends here diff --git a/elpa/ess-20230419.1527/ess-site.el b/elpa/ess-20230419.1527/ess-site.el new file mode 100644 index 00000000..c298086f --- /dev/null +++ b/elpa/ess-20230419.1527/ess-site.el @@ -0,0 +1,65 @@ +;;; ess-site.el --- user customization of ESS -*- lexical-binding: t; -*- + +;; Copyright (C) 1993-2020 Free Software Foundation, Inc. +;; Author: David Smith +;; Created: 12 Nov 1993 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Load path, autoloads, and major modes +;; ======================================== +;; +;; This file defines all the site-specific customizations for ESS. It should be +;; edited on a per-site basis. users who wish to use ESS should add the path to +;; ess-site to their `load-path' and require it: +;; +;; (add-to-list 'load-path "/path/to/ess/lisp-directory");; +;; (require 'ess-site) +;; +;; For most users the variable ess-lisp-directory will automatically be set +;; correctly. If you are working with an old Emacs, one in which file-truename +;; is not defined, then you might need to change the value of ess-lisp-directory +;; to the directory which is to contain the file ess-site.elc. This is probably +;; the current directory, or the value of LISPDIR if it was set in the Makefile. +;; +;; Debug startup: (setq ess-show-load-messages t) + +;;; Code: + +(when load-file-name + ;; Modify this if ess-site.el is not in the ./lisp/ directory + (defvar ess-lisp-directory (file-name-directory load-file-name) + "Directory containing ess-site.el(c) and other ESS Lisp files.") + (add-to-list 'load-path (directory-file-name ess-lisp-directory))) + +;;; Loading popular dialects (they should become optional in the future) + +(require 'ess-r-mode) +(require 'essd-els) ;; ess-remote +(require 'ess-sas-d) +(require 'ess-bugs-d) +(require 'ess-jags-d) +(require 'ess-toolbar) + +(provide 'ess-site) + +;;; ess-site.el ends here diff --git a/elpa/ess-20230419.1527/ess-sp6-d.el b/elpa/ess-20230419.1527/ess-sp6-d.el new file mode 100644 index 00000000..087c7cad --- /dev/null +++ b/elpa/ess-20230419.1527/ess-sp6-d.el @@ -0,0 +1,196 @@ +;;; ess-sp6-d.el --- S-Plus 6 & 7 & 8 customization -*- lexical-binding: t; -*- + +;; Copyright (C) 2001-2022 Free Software Foundation, Inc. +;; Author: A.J. Rossini +;; Created: 2001/02/06 +;; Maintainer: ESS Core Team + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; AJR copied S+5 to be S+6. +;; AJR copied S4 to be S+5. +;; DB contributed the changes from ess-sp3-d.el to +;; ess-s4-d.el. (removed the old ugly approach). +;; This file defines Sp5 customizations for ess-mode. Lots of thanks +;; to RMH and JMC for code and suggestions +;; Thanks to MM for making this sensible. + +;;; Code: + +(require 'ess-mode) +(require 'ess-inf) +(require 'ess-s-lang) +(require 'ess-trns) + + +;; You now need to make sure you've defined if you are running 5.0 or 5.1. +;; Lots of things are broken between them, GRR... + +(defun S+-directory-p (directory) + "Splus 5++ directories have a .Data directory and a __Meta directory within." + (and directory + (file-directory-p (concat directory ".Data")) + (file-directory-p (concat directory ".Data/__Meta")))) + +(defvar S+-directory-function #'inferior-ess-default-directory) + +(defvaralias 'S+6-setup-directory-function 'S+-setup-directory-function) +(defvar S+-setup-directory-function + (lambda (startdir) + (when (and startdir (S+-directory-p startdir)) + (setenv "S_WORK" + (if (getenv "S_WORK") + (concat startdir ":" (getenv "S_WORK")) + ;;(message "adding %s to S_WORK" startdir) + startdir))))) + + + +(defvaralias 'S+6-customize-alist 'S+-customize-alist) +(defvar S+-customize-alist + (append + '((ess-local-customize-alist . S+-customize-alist) + (ess-dialect . S+-dialect-name) + (ess-function-pattern . ess-r-function-pattern) + + (ess-object-name-db-file . "ess-sp6-namedb.el") + (inferior-ess-program . inferior-S+-program) + (inferior-ess-help-command . "help(\"%s\", pager=\"slynx -dump\", window=FALSE)\n") + (inferior-ess-search-list-command . "searchPaths()\n") + + (ess-startup-directory-function . S+-directory-function) + (ess-STERM . "iESS")) + S+common-cust-alist) + + "Variables to customize for S+.") + +(defvar ess-S+-post-run-hook nil + "Functions run in process buffer after the initialization of S+ + process.") + +(defvar ess-S+--injected-code + ".ess_funargs <- function(funname){ + ## funname <- deparse(substitute(object)) + fun <- try(eval(parse(text=funname)), silent = TRUE) + if(is.function(fun)) { + special <- grepl('[:$@[]', funname) + args <- args(fun) + fmls <- formals(args) + fmls.names <- names(fmls) + fmls <- gsub('\\\"', '\\\\\\\"', as.character(fmls), fixed = TRUE) + args.alist <- sprintf(\"'(%s)\", paste(\"(\\\"\", fmls.names, \"\\\" . \\\"\", fmls, \"\\\")\", sep = '', collapse = ' ')) + ## envname <- environmentName(environment(fun)) + envname <- if (special) '' else 'S+' + cat(sprintf('(list \\\"%s\\\" %s )\\n', envname, args.alist)) + } +} +") + +(defalias 'S+6 #'S+) +(defun S+ (&optional _proc-name) + "Call `Splus6', based on S version 4, from Bell Labs. +New way to do it." + (interactive) + (ess-write-to-dribble-buffer + (format "\n(S+): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer))) + (let ((inf-buf (inferior-ess nil S+-customize-alist))) + (ess-command ess-S+--injected-code) + (when inferior-ess-language-start + (ess-eval-linewise inferior-ess-language-start)) + (with-current-buffer inf-buf + (run-mode-hooks 'ess-S+-post-run-hook)) + inf-buf)) + + +(defalias 'S+6-mode #'S+-mode) +;;;###autoload +(defun S+-mode (&optional _proc-name) + "Major mode for editing S+ source. See `ess-mode' for more help." + (interactive) + (setq-local ess-local-customize-alist S+-customize-alist) + (ess-mode) + (if (fboundp 'ess-add-toolbar) (ess-add-toolbar)) + (setq imenu-generic-expression ess-imenu-S-generic-expression) + (when ess-imenu-use-S (imenu-add-to-menubar "Imenu-S"))) + +(defalias 'S+6-transcript-mode #'S+-transcript-mode) +(define-derived-mode S+-transcript-mode ess-transcript-mode "ESS S Transcript" + "S-PLUS 6 transcript mode." + :syntax-table S-syntax-table + :group 'ess-S) + +(defvar ess-s-versions '("Splus") + "List of partial strings for versions of S to access within ESS. +Each string specifies the start of a filename. If a filename +beginning with one of these strings is found on `exec-path', a M-x +command for that version of S is made available. For example, if the +file \"Splus7\" is found and this variable includes the string +\"Splus\", a function called `M-x Splus7' will be available to run that +version of S. +If duplicate versions of the same program are found (which happens if +the same path is listed on `exec-path' more than once), they are +ignored by calling `delete-dups'. +Set this variable to nil to disable searching for other versions +of S using this method. +If you set this variable, you need to restart Emacs (and set this variable +before ess-site is loaded) for it to take effect.") +(define-obsolete-variable-alias + 'ess-s-versions-created 'ess-s-created-runners "ESS 18.10") +(defvar ess-s-created-runners) +(defun ess-s-define-runners () + "Generate functions for starting other versions of S. +See `ess-s-versions' for strings that determine which functions are created. +It assumes these versions of S can be run as a substitute for Splus6. + +This function returns the list of functions, if any, that were +created. The functions will normally be placed on the menubar upon +ESS initialization." + (when ess-s-versions + (let ((versions + (delete-dups + (mapcar #'file-name-nondirectory + (apply #'nconc + (mapcar #'ess-find-exec-completions + ess-s-versions)))))) + ;; Iterate over each string in VERSIONS, creating a new defun + ;; each time. + (setq ess-s-created-runners + (mapc (lambda (v) (ess-define-runner v "S")) versions)) + ;; Add to menu + (when ess-s-created-runners + ;; new-menu will be a list of 3-vectors, of the form: + ;; ["R-1.8.1" R-1.8.1 t] + (let ((new-menu (mapcar (lambda (x) (vector x (intern x) t)) + ess-s-created-runners))) + (easy-menu-add-item ess-mode-menu '("Start Process") + (cons "Other" new-menu))))))) +;; Define the runners +(ess-s-define-runners) +(define-obsolete-function-alias + 'ess-s-versions-create #'ess-s-define-runners "ESS 18.10") + + + + ; Provide package + +(provide 'ess-sp6-d) + +;;; ess-sp6-d.el ends here diff --git a/elpa/ess-20230419.1527/ess-toolbar.el b/elpa/ess-20230419.1527/ess-toolbar.el new file mode 100644 index 00000000..b6d12079 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-toolbar.el @@ -0,0 +1,184 @@ +;;; ess-toolbar.el --- Support for a toolbar in ESS. -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2020 Free Software Foundation, Inc. +;; Author: Stephen Eglen +;; Created: 2004-05-06 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This code adds a toolbar to ESS modes for editing R and S code. +;; Support can be added for other modes (e.g. STATA), just ask! +;; +;; This code is experimental. It has been tested only on Linux +;; machines. All feedback appreciated. +;; +;; If your Emacs can support images, the ESS toolbar should be loaded. +;; +;; If you see a toolbar, but no icons, check out the value of +;; ess-icon-directory. +;; +;; The toolbar can be customized in several ways. To see options, do: +;; M-x customize-group RET ess-toolbar RET +;; If you change any of the variables, you _may_ need to restart Emacs +;; to see any effect. See also the documentation for ess-toolbar-items +;; if you wish to change its value. + +;;; Technical issues. + +;; 2009-03-16: toolbar code in Emacs 23 has changed slightly to 22, +;; and presumably once Emacs 22 is no longer supported, this code can +;; be cleaned up a bit (i.e. no need to set load-path.) + +;;; Code: + +(require 'ess-mode) + +(defgroup ess-toolbar nil + "ESS: toolbar support." + :group 'ess + :link '(emacs-commentary-link :tag "Commentary" "ess-toolbar.el") + :prefix "ess-") + +(defcustom ess-use-toolbar + (and (fboundp 'display-images-p) (display-images-p)) + "Non-nil means ESS should support the toolbar." + :type 'boolean) + + +(defcustom ess-toolbar-own-icons nil + "Non-nil means that we only put our toolbar entries in ESS. +Otherwise we get standard toolbar as well as ESS entries. +The standard toolbar items are copied from the default toolbar." + :type 'boolean) + +(defcustom ess-toolbar-global nil + "*Non-nil means that the ESS toolbar is available in all Emacs buffers. +Otherwise, the ESS toolbar is present only in R/S mode buffers. +For beginners, this is probably better set to a non-nil value." + :type 'boolean) + +(defcustom ess-toolbar-items + '( (R "startr") + ;;(S "spluslogo" "Start S process") + (S "splus_letter_small") + (ess-eval-line-and-step "rline") + (ess-eval-region "rregion") + (ess-eval-function-or-paragraph-and-step "rregion") + (ess-load-file "rbuffer") + (ess-eval-function "rfunction") + (ess-switch-to-ESS "switch_ess")) + "Items to be added to the ESS toolbar. +Each list element has two items: +1. the name of the function to run +2. the icon to be used (without .xpm extension) + +General toolbar items are also added to the ESS toolbar +iff `ess-toolbar-own-icons' is nil. + +Setting this variable with setq doesn't take effect once you have +loaded ess-site, unless you follow it by a call to +`ess-make-toolbar' afterwards. Instead, change its value using +Custom, and then on all new ESS buffers you should see the +toolbar has changed." + :set (lambda (symbol value) + (set-default symbol value) + (if (fboundp 'ess-make-toolbar) + (ess-make-toolbar))) + :type '(repeat (list (function :tag "Function to run") + (string :tag "Icon")))) + +(defvar ess-icon-directory + (expand-file-name "icons" ess-etc-directory) + "*Location for ESS icons. +This variable should be set automatically by the ESS install process. +Icons should be found in ESS/etc/icons/ directory. +If `ess-icon-directory' is invalid, please report a bug.") + +(unless (file-directory-p ess-icon-directory) + (ess-write-to-dribble-buffer + "`ess-icon-directory' does not exist; using `ess-etc-directory'.\n") + (setq ess-icon-directory ess-etc-directory)) + +(defvar ess-toolbar nil + "Toolbar items to be added to ESS editing buffers.") + +(defun ess-make-toolbar () + "Make the ESS toolbar." + ;; Under Emacs, only worth building the toolbar if tool-bar-map is + ;; available. e.g. when running Emacs within a terminal, tool-bar-map + ;; is not available, so no need to make the tool-bar. + (when (boundp 'tool-bar-map) + (setq ess-toolbar + (if (or ess-toolbar-own-icons (null tool-bar-map)) + (make-sparse-keymap) + (copy-keymap tool-bar-map))) + (let ((tool-bar-map ess-toolbar) + (load-path (list ess-icon-directory))) + ;; in Emacs 22, icons are found by examining load-path, bound here + ;; whereas Emacs 23 seems to want them in image-load-path, set at the + ;; bottom of this file. + (mapc #'ess-add-icon ess-toolbar-items)))) + +(defun ess-add-icon (x) + "Add an ESS item to the Emacs toolbar. +X should be a list, see `ess-toolbar-items' for the format." + ;; By using tool-bar-add-item-from-menu instead of tool-bar-add-item + ;; we get the tooltips "for free" from ess-mode-map. + (tool-bar-add-item-from-menu (car x) (cadr x) ess-mode-map)) + +(defun ess-add-toolbar () + "Add the ESS toolbar to a particular mode. +The toolbar is added iff `ess-toolbar-global' is nil, else the toolbar +is added globally when ess-toolbar.el is loaded." + (when (and ess-toolbar (not ess-toolbar-global)) + (setq-local tool-bar-map ess-toolbar))) + +;; Make the toolbars. Each toolbar is hopefully made only when this file +;; is loaded; we don't need it to be remade every time. +(if ess-use-toolbar + (progn + (ess-make-toolbar) + ;; After making the toolbar, if ESS toolbar is needed globally, + ;; add it here. + (if ess-toolbar-global + (setq tool-bar-map ess-toolbar) + (ess-write-to-dribble-buffer "Creating global Emacs toolbar")) + + ;; Check for toolbar support - needed iff ess-use-toolbar is non-nil. + (or + ;; Emacs support for images: + (and (fboundp 'display-images-p) (display-images-p)) + ;; if above tests failed, give a warning. + (progn + (message "Toolbar support for ESS not available in this Emacs.") + ;; Not sure if we want to delay startup of ESS. + ;;(sit-for 2) + )) + )) + +;; Following needed for Emacs 23, not Emacs 22 +(when (boundp 'image-load-path) + (add-to-list 'image-load-path ess-icon-directory)) + +(provide 'ess-toolbar) + +;;; ess-toolbar.el ends here diff --git a/elpa/ess-20230419.1527/ess-tracebug.el b/elpa/ess-20230419.1527/ess-tracebug.el new file mode 100644 index 00000000..74592dc4 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-tracebug.el @@ -0,0 +1,2801 @@ +;; ess-tracebug.el --- Tracing and debugging facilities for ESS. -*- lexical-binding: t; -*- + +;; Copyright (C) 2011-2022 Free Software Foundation, Inc. +;; Author: Vitalie Spinu +;; Maintainer: Vitalie Spinu +;; Created: Oct 14 14:15:22 2010 + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Ess-tracebug is a package for interactive debugging of R code from +;; ESS and provides such features as: +;; - visual debugging +;; - browser, recover and conditional breakpoints +;; - watch window and loggers +;; - on the fly debug/undebug of R functions and methods +;; - highlighting of error source references and easy error navigation +;; - interactive traceback. +;; +;; For a complete description please see the documentation in the ESS +;; manual. + +;;; Code: + +(eval-and-compile + (when (< emacs-major-version 26) + (require 'cl)) + (require 'cl-lib) + (require 'tramp) + (require 'subr-x) + (require 'ess-utils)) +(require 'comint) +(require 'compile) +(require 'ring) + + +(defvar text-scale-mode-amount) +(autoload 'text-scale-mode "face-remap" "[autoload]" nil) + +;; Silence the byte compiler. This is OK here because this file is +;; only loaded from ess-inf and has no autoloads. +;; TODO: This is a LOT. Can we move some of this around? +(defvar ess--dbg-del-empty-p) +(defvar inferior-ess-mode-map) +(defvar ess-mode-map) +(defvar ess--inhibit-presend-hooks) + +(declare-function ess--accumulation-buffer "ess-inf") +(declare-function ess--if-verbose-write-process-state "ess-inf") +(declare-function ess--run-presend-hooks "ess-inf") +(declare-function ess-boolean-command "ess-inf") +(declare-function ess-build-eval-command "ess-inf") +(declare-function ess-build-load-command "ess-inf") +(declare-function ess-command "ess-inf") +(declare-function ess-dirs "ess-inf") +(declare-function ess-eval-region--normalise-region "ess-inf" ) +(declare-function ess-force-buffer-current "ess-inf") +(declare-function ess-get-process "ess-inf") +(declare-function ess-get-process-variable "ess-inf") +(declare-function ess-get-words-from-vector "ess-inf") +(declare-function ess-get-words-from-vector--foreground "ess-inf") +(declare-function ess-process-get "ess-inf") +(declare-function ess-process-live-p "ess-inf") +(declare-function ess-process-put "ess-inf") +(declare-function ess-send-string "ess-inf") +(declare-function ess-switch-process "ess-inf" ()) +(declare-function ess-switch-to-ESS "ess-inf") +(declare-function ess-switch-to-end-of-ESS "ess-inf" ()) +(declare-function ess-wait-for-process "ess-inf") +(declare-function inferior-ess--set-status "ess-inf") +(declare-function inferior-ess-output-filter "ess-inf") +(declare-function inferior-ess-run-callback "ess-inf") + +(declare-function ess-helpobjs-at-point--read-obj "ess-help") +(declare-function ess-r-get-evaluation-env "ess-r-mode") +(declare-function ess-roxy--region-p "ess-roxy") + +(declare-function ess-r-package--all-source-dirs "ess-r-package") +(declare-function ess-r-package-name "ess-r-package") +(declare-function ess-r-package-source-dirs "ess-r-package") + + +;; Do not require tramp at runtime. It is expensive to load. Instead, +;; guard calls with (require 'tramp) and silence the byte compiler +;; here. +(declare-function tramp-dissect-file-name "tramp") +(declare-function tramp-get-remote-tmpdir "tramp") +;; The following declares can be removed once we drop Emacs 25 +(declare-function tramp-file-name-hop "tramp") +(declare-function tramp-file-name-host "tramp") +(declare-function tramp-file-name-localname "tramp") +(declare-function tramp-file-name-method "tramp") +(declare-function tramp-file-name-user "tramp") + + +(defgroup ess-tracebug nil + "Error navigation and debugging for ESS. +Currently only R is supported." + :link '(emacs-library-link :tag "Source Lisp File" "ess-tracebug.el") + :group 'ess) + +(defvar ess-tracebug-indicator " TB" + "String to be displayed in mode-line alongside the process name. +Indicates that ess-tracebug-mode is turned on.") + +(defvar ess-watch-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "k" #'ess-watch-kill) + ;; (define-key ess-watch-mode-map "u" #'ess-watch-undelete) + ;; editing requires a little more work. + (define-key map "a" #'ess-watch-add) + (define-key map "i" #'ess-watch-insert) + (define-key map "e" #'ess-watch-edit-expression) + (define-key map "r" #'ess-watch-rename) + (define-key map "q" #'ess-watch-quit) + (define-key map "u" #'ess-watch-move-up) + (define-key map "U" #'ess-watch-move-down) + (define-key map "d" #'ess-watch-move-down) + (define-key map "n" #'ess-watch-next-block) + (define-key map "p" #'ess-watch-previous-block) + ;; R mode keybindings. + (define-key map "\C-c\C-s" #'ess-switch-process) + (define-key map "\C-c\C-y" #'ess-switch-to-ESS) + (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) + map) + "Keymap for `ess-watch-mode'.") + + +(defcustom ess-tracebug-prefix nil + "Key to be used as prefix for all `ess-tracebug' commands. +Set this to a key combination you don't use often, like: + + (setq ess-tracebug-prefix \"\\M-t\") + +The postfix keys are defined in `ess-tracebug-map': +\\{ess-tracebug-map}" + :type '(choice (const nil) (string)) + :group 'ess-tracebug) + +(defcustom ess-tracebug-search-path nil + "List of directories to search for source files. +Elements should be directory names, not file names of directories." + :type '(choice (const :tag "Unset" nil) + (repeat :tag "Directory list" (string :tag "Directory"))) + :group 'ess-debug) + +(defvar ess-watch-buffer "*R watch*" + "Name of the watch buffer.") + +(defcustom ess-watch-height-threshold nil + "Minimum height for splitting *R* window sensibly to make space for watch window. +See `split-height-threshold' for a detailed description. + +If nil, the value of `split-height-threshold' is used." + :group 'ess-debug + :type '(choice (const nil) (integer))) + +(defcustom ess-watch-width-threshold nil + "Minimum width for splitting *R* window sensibly to make space for watch window. +See `split-width-threshold' for a detailed description. + +If nil, the value of `split-width-threshold' is used." + :group 'ess-debug + :type '(choice (const nil) (integer))) + +(defcustom ess-watch-scale-amount -1 + "The number of steps to scale the watch font down (up). +Each step scales the height of the default face in the watch +window by the variable `text-scale-mode-step' (a negative number +of steps decreases the height by the same amount)" + :group 'ess-debug + :type 'integer) + +(defvar-local ess-watch-current-block-overlay nil + "The overlay for currently selected block in the R watch buffer .") + +(defcustom ess-inject-source 'function-and-buffer + "Control the source injection into evaluated code. + +If t, always inject source reference. +If function, inject only for functions, +If function-and-buffer, inject for functions and whole buffer (the default), +If nil, never inject. + +When tracebug is active (the default), ESS instructs the +subprocess to keep the source code references. + +If this variable is t, you won't be able to execute blocks which +don't form a valid R expression. That is, if your expression +spreads multiple paragraphs, and you call +\\[ess-eval-region-or-function-or-paragraph-and-step] on first +paragraph, R will report an error." + :group 'ess-tracebug + :type '(choice (const nil) (const function) (const function-and-buffer) (const t))) + +(defcustom ess-tracebug-enter-hook nil + "List of functions to call on entry to `ess-tracebug' mode. +Use `add-hook' to insert append your functions to this list." + :group 'ess-tracebug + :type 'hook) + +(defcustom ess-tracebug-exit-hook nil + "List of functions to call on exit of `ess-tracebug' mode. +Use `add-hook' to insert append your functions to this list." + :group 'ess-tracebug + :type 'hook) + +(defvaralias 'ess-tracebug-map 'ess-dev-map) + +(defvar ess--tracebug-eval-index 0 + "This is used by to track source references in evaluation with source. +For example, each time `ess-eval-function' is called the evaluated +region is marked. When debugger enters the code it displays +this reference number. Ess-debug finds this number in the +referenced buffer.") + +;; these vars are org variables that store the src block locations +(defvar org-edit-src-beg-marker nil) +(defvar org-babel-current-src-block-location nil + "Marker pointing to the src block currently being executed. +This may also point to a call line or an inline code block. If +multiple blocks are being executed (e.g., in chained execution +through use of the :var header argument) this marker points to +the outer-most code block.") + +;; hash to store source references of the form: tmpname -> (filename . src_start) +(defvar ess--srcrefs (make-hash-table :test 'equal :size 100)) + +(defvar ess-tracebug-original-buffer-marker nil + "Marker pointing to the beginning of original source code. +If non-nil, tracebug will insert the source references based on +this location instead of the current buffer. This is useful for +applications, like org-babel, that call ess evaluation functions +from temporary buffers.") + +(defun ess-tracebug-p () + "Return non-nil if tracebug is running." + (ess-process-get 'tracebug)) + +(defun ess-make-source-refd-command (beg end visibly process) + "Saves a region to a temporary file in order to add source references. +BEG and END delimit the region. Returns a string containing an +inferior process command for loading the temporary file. This +command conforms to VISIBLY." + (let* ((filename buffer-file-name) + (proc-dir (ess-get-process-variable 'default-directory)) + (remote (when (file-remote-p proc-dir) + (require 'tramp) + ;; should this be done in process buffer? + (tramp-dissect-file-name proc-dir))) + (orig-marker (or ess-tracebug-original-buffer-marker + org-edit-src-beg-marker + org-babel-current-src-block-location)) + orig-beg) + (setq ess--tracebug-eval-index (1+ ess--tracebug-eval-index)) + (goto-char beg) + (skip-chars-forward " \t\n") + (setq beg (point)) + (goto-char end) + (skip-chars-backward " \t\n") + (setq end (point) + orig-beg beg) + + ;; Delete all old temp files + (when (and (not (ess-process-get 'busy)) + (< 1 (float-time + (time-subtract (current-time) + (ess-process-get 'last-eval))))) + (dolist (f (ess-process-get 'temp-source-files)) + (and (file-exists-p f) + (delete-file f))) + (ess-process-put 'temp-source-files nil)) + + (when (markerp orig-marker) + (setq filename (buffer-file-name (marker-buffer orig-marker))) + (setq orig-beg (+ beg (marker-position orig-marker)))) + + (let ((tmpfile + (expand-file-name (make-temp-name + (concat (file-name-nondirectory + (or filename "unknown")) "!")) + (if remote + (tramp-get-remote-tmpdir remote) + temporary-file-directory)))) + + (ess-process-put 'temp-source-files + (cons tmpfile (ess-process-get 'temp-source-files))) + + (when remote + ;; Get local name (should this be done in process buffer?) + (setq tmpfile (with-parsed-tramp-file-name tmpfile nil localname))) + + (if (not filename) + (puthash tmpfile (list nil ess--tracebug-eval-index nil) ess--srcrefs) + (puthash tmpfile (list filename ess--tracebug-eval-index orig-beg) ess--srcrefs) + (puthash (file-name-nondirectory tmpfile) ; R sometimes strips dirs + (list filename ess--tracebug-eval-index orig-beg) ess--srcrefs) + (with-silent-modifications + (put-text-property beg end 'tb-index ess--tracebug-eval-index))) + (let ((string (ess-process-buffer-substring process beg end))) + (or + ;; Sending string to subprocess is considerably faster than tramp file + ;; transfer. So, give priority to `ess-eval-command' if available + (ess-build-eval-command string visibly t tmpfile) + ;; When no `ess-eval-command' available, use `ess-load-command' + (progn + (write-region beg end tmpfile nil 'silent) + (ess-build-load-command tmpfile visibly t))))))) + +(defun ess-process-buffer-substring (process start end) + (ess--run-presend-hooks process (buffer-substring-no-properties start end))) + +;; Declare globally so that the bytecode compiler let-binds it +;; properly +(defvar-local ess-r-evaluation-env nil) + +(defun ess-tracebug-send-region (process start end &optional visibly message type) + "Send region to process adding source references as specified +by `ess-inject-source' variable." + ;; Disable evaluation env if we're sending a roxy region. This is + ;; not the ideal place to do this. + (let* ((se (ess-eval-region--normalise-region start end)) + (start (car se)) + (end (cdr se)) + (ess-r-evaluation-env (unless (ess-roxy--region-p start end) + (ess-r-get-evaluation-env))) + (inject-p (cond ((eq type 'function) + ess-inject-source) + ((eq type 'buffer) + (or (eq ess-inject-source t) + (eq ess-inject-source 'function-and-buffer))) + ((eq ess-inject-source t)) + ;; We need to always inject with namespaced + ;; evaluation (FIXME: not right place for + ;; this). + (ess-r-evaluation-env))) + (ess--dbg-del-empty-p (unless inject-p ess--dbg-del-empty-p)) + (string (if inject-p + (ess-make-source-refd-command start end visibly process) + (ess-process-buffer-substring process start end))) + (message (if (fboundp ess-build-eval-message-function) + (funcall ess-build-eval-message-function message) + message))) + ;; Don't run the presend hooks twice. + (let ((ess--inhibit-presend-hooks t)) + (process-put process :eval-visibly visibly) + ;; Visible evaluation is not nice when sourcing temporary files. You get + ;; .ess.eval(*code*) instead of *code*. + (setq visibly (unless inject-p visibly)) + (ess-send-string process string visibly message)))) + +(defun ess-tracebug-send-function (proc start end &optional visibly message) + "Like `ess-tracebug-send-region' but with tweaks for functions." + (ess-tracebug-send-region proc start end visibly message 'function)) + +;; * Input Ring: + +;; i . Goto input event marker forwards . `ess-debug-goto-input-event-marker' +;; I . Goto input event marker backwards . `ess-debug-goto-input-event-marker' + + +(defun ess-tracebug-show-help () + "Show help for `ess-tracebug'." + (interactive) + (if (fboundp 'describe-keymap) + (describe-keymap 'ess-tracebug-map) + (info "(ess) ESS tracebug"))) + +(defun ess-tracebug--propertize (dummy bitmap face &optional string ) + "If `window-system' propertize DUMMY with fringe BITMAP and FACE. +Otherwise, propertize line-prefix and margin with STRING and FACE" + (unless string + (setq string dummy)) + (if window-system + (propertize dummy 'display (list 'left-fringe bitmap face)) + (propertize dummy + 'display (list '(margin left-margin) + (propertize string + 'font-lock-face face + 'face face))))) + + +(defun ess-tracebug (&optional arg) + "Toggle `ess-tracebug' mode. +With ARG, turn `ess-tracebug' mode on if and only if ARG is +positive. + +This mode adds to ESS the interactive debugging, breakpoint and +error navigation functionality. Strictly speaking `ess-tracebug' +is not a minor mode. It integrates globally into ESS and iESS. + +Note: Currently, `ess-tracebug' does not detect some of R's debug +related messages in non-English locales. To set your R messages +to English add the following line to your .Rprofile init file: + + Sys.setlocale(\"LC_MESSAGES\", \"C\") + + +See `ess-tracebug-help' for the overview of ess-tracebug functionality." + + ;; Note: The functionality in ess-tracebug is divided on conceptual + ;; grounds in tracing and debugging and could be + ;; activated/deactivate separately with `ess--tb-start' and + ;; `ess-debug-start' respectively. + + (interactive "P") + (ess-force-buffer-current "R process to activate tracebug in: ") + (with-current-buffer (process-buffer (get-process ess-local-process-name)) + (when (equal ess-dialect "R") + (setq arg + (if arg + (prefix-numeric-value arg) + (if (ess-process-get 'tracebug) -1 1))) + (if (> arg 0) + (unless (ess-process-get 'tracebug) ;; only if not already active + (ess--tb-start) + (ess-debug-start) + ;; (dolist (bf (buffer-list)) + ;; (with-current-buffer bf + ;; (when (and (eq major-mode 'ess-mode) + ;; (equal ess-dialect "R")) + ;; (ess-bp-recreate-all)))) + ;; watch functionality + (if ess-tracebug-prefix + (let ((comm (key-binding ess-tracebug-prefix))) + ;; (message "ess-tracebug-prefix will be removed in future versions. Electric debug keys are now on [C-c] and [C-c C-t] maps.") + ;; (sit-for 1) + (when (commandp comm) + (define-key ess-tracebug-map ess-tracebug-prefix comm)) + (define-key ess-mode-map ess-tracebug-prefix ess-tracebug-map) + (define-key inferior-ess-mode-map ess-tracebug-prefix ess-tracebug-map) + (define-key ess-watch-mode-map ess-tracebug-prefix ess-tracebug-map))) + (run-hooks 'ess-tracebug-enter-hook) + (ess-process-put 'tracebug t) + (message "ess-tracebug mode enabled")) + (when (ess-process-get 'tracebug) ;;only when active + (ess-process-put 'tracebug nil) + ;; unset the map + (when ess-tracebug-prefix + (define-key ess-mode-map ess-tracebug-prefix nil) + (define-key inferior-ess-mode-map ess-tracebug-prefix nil)) + (ess--tb-stop) + (ess-debug-stop) + (run-hooks 'ess-tracebug-exit-hook) + (message "ess-tracebug mode disabled")))))) + +(defalias 'ess-toggle-tracebug #'ess-tracebug) + + +;;;_* TRACEBACK + +;; (defface ess--tb-last-input-face +;; '((((class grayscale) +;; (background light)) (:background "DimGray")) +;; (((class grayscale) +;; (background dark)) (:background "LightGray")) +;; (((class color) (background light) (min-colors 88)) +;; (:overline "medium blue" )) +;; (((class color) (background dark) (min-colors 88)) +;; (:overline "deep sky blue" )) +;; (((background light)) (:weight bold)) +;; (((background dark)) (:weight bold)) +;; ) +;; "Face to highlight currently debugged line." +;; :group 'ess-tracebug ) + +(defface ess-tracebug-last-input-fringe-face + '((((background light) (min-colors 88)) (:foreground "medium blue" :overline "medium blue")) + (((background dark) (min-colors 88)) (:foreground "deep sky blue" :overline "deep sky blue")) + (((background light) (min-colors 8)) (:foreground "blue")) + (((background dark) (min-colors 8)) (:foreground "cyan"))) + "Face for fringe bitmap for last-input position." + :group 'ess-tracebug) + +(if (fboundp 'define-fringe-bitmap) + (define-fringe-bitmap 'last-input-arrow + [#b00011111 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b00010000 + #b11010111 + #b01111100 + #b00111000 + #b00010000] nil nil 'top)) + + +(defvar ess--tb-last-input (make-marker) + "Marker pointing to the last user input position in iESS buffer. +This is the place where `ess--tb-last-input-overlay' is moved. +Local in iESS buffers with `ess-tracebug' mode enabled.") + +(defvar ess--tb-last-input-overlay nil + "Overlay to highlight the position of last input in iESS buffer. +Local in iESS buffers.") + +(defvar-local ess--busy-count 0 + "Used to compute the busy indicator.") + +;; (unless (boundp 'ess--busy-slash) +;; (defvar ess--busy-slash '(32 ?\u2014 92 47)) +;; (setq ess--busy-slash (mapcar (lambda (el) (format " %c " el)) +;; ess--busy-slash)) +;; ) + + +(defvar ess--busy-slash '(" " " - " " \\ " " / ")) +(defvar ess--busy-B '(" " " B " " ")) +(defvar ess--busy-stars '(" " " " " * " " ** " " *** " " **** ")) +(defvar ess--busy-vbars '(" " " " " | " " || " " ||| " " |||| ")) + +(defcustom ess-busy-strings ess--busy-slash + "List of strings to replace in turn for busy indication. +The first element of the list is used as an indicator of the +process being ready (i.e. not busy). Implemented lists that you +can use `ess--busy-slash', `ess--busy-B',`ess--busy-stars', +`ess--busy-vbars'" + :group 'ess + :type '(repeat string)) + +(defvar ess--busy-timer nil + "Timer used for busy process indication.") + +(defcustom inferior-ess-fix-misaligned-output nil + "If non-nil, try to correct misaligned process output." + :group 'ess-tracebug + :type 'boolean) + +(defcustom inferior-ess-replace-long+ t + "Determines if ESS replaces long + sequences in output. +If \\='strip, remove all such instances. Otherwise, if non-nil, `+ ++ + + ' containing 3 or more + is replaced by +`ess-long+replacement'. +This variable can be process-local but not buffer-local." + :group 'ess-tracebug + :type '(choice (const nil :tag "No replacement") + (const strip :tag "Replace all") + (const t :tag "Replace 3 or more +"))) + +(defvar ess-long+replacement ". + " + "Replacement used for long + prompt. +Please don't customize this or other prompt related variables. +ESS internal code assumes default R prompts.") + +(defmacro ess-copy-key (from-map to-map fun) + `(define-key ,to-map + (car (where-is-internal ,fun ,from-map)) + ,fun)) + +;;;_ + traceback functions +(defun ess--tb-make-last-input-overlay (beg end) + "Create an overlay to indicate the last input position." + (let ((ove (make-overlay beg end))) + (overlay-put ove 'before-string + (ess-tracebug--propertize "!" 'last-input-arrow 'ess-tracebug-last-input-fringe-face)) + ;; (overlay-put ove 'face 'ess--tb-last-input-face) + (overlay-put ove 'evaporate t) + ove)) + + +(defun ess--tb-start () + "Start traceback session." + (with-current-buffer (process-buffer (get-process ess-local-process-name)) + (unless ess-error-regexp-alist + (error "Can not activate the traceback for %s dialect" ess-dialect)) + (setq-local compilation-error-regexp-alist ess-error-regexp-alist) + (let (compilation-mode-font-lock-keywords) + (compilation-setup t)) + (setq next-error-function 'ess-tracebug-next-error-function) + ;; new locals + (make-local-variable 'ess--tb-last-input) + (make-local-variable 'ess--tb-last-input-overlay) + (make-local-variable 'compilation-search-path) + (setq compilation-search-path ess-tracebug-search-path) ;; TODO: make this dialect specific + (ess-tracebug--set-left-margin) + (save-excursion + (goto-char comint-last-input-start) + (setq ess--tb-last-input (point)) + (setq ess--tb-last-input-overlay + (ess--tb-make-last-input-overlay + (line-beginning-position) (line-end-position)))) + ;; busy timer + (setq mode-line-buffer-identification + (list (car (propertized-buffer-identification "%3b")) + `(:eval (nth ess--busy-count ess-busy-strings)))) ;; 'face 'mode-line-buffer-id)))) + (make-local-variable 'ess--busy-timer) + (setq ess--busy-timer + (run-with-timer 2 .5 (ess--make-busy-timer-function (get-buffer-process (current-buffer))))) + (add-hook 'kill-buffer-hook (lambda () (when ess--busy-timer (cancel-timer ess--busy-timer)))) + (add-hook 'comint-input-filter-functions #'ess-tracebug-set-last-input nil 'local) + + ;; redefine + ;; TODO: all this part should go (partially gone now) + (advice-add 'ess-parse-errors :override #'next-error))) + +(defun ess--tb-stop () + "Stop ess traceback session in the current ess process." + (with-current-buffer (process-buffer (get-process ess-current-process-name)) + ;; restore original definitions + (when (equal ess-dialect "R") + (advice-remove 'ess-parse-errors #'next-error)) + (if (local-variable-p 'ess--tb-last-input-overlay) + (delete-overlay ess--tb-last-input-overlay)) + (kill-local-variable 'ess--tb-last-input-overlay) + (kill-local-variable 'ess--tb-last-input) + (font-lock-remove-keywords nil (compilation-mode-font-lock-keywords)) + (font-lock-ensure) + (kill-local-variable 'compilation-error-regexp-alist) + (kill-local-variable 'compilation-search-path) + (cancel-timer ess--busy-timer) + (remove-hook 'comint-input-filter-functions #'ess-tracebug-set-last-input 'local) + (setq mode-line-buffer-identification (propertized-buffer-identification "%12b")))) + +(defvar ess--dbg-forward-ring (make-ring 10) + "Ring of markers to the positions of user inputs when the +debugger or traceback events are initiated. It is used in +`ess--dbg-goto-input-point'.") + +(defvar ess--dbg-backward-ring (make-ring 10) + "Ring of markers for the positions from `ess--dbg-goto-input-point'. +Marks the position from which it was called. See also +`ess--dbg-goto-debug-point'") + +;; (setq ess-R--tb-regexp-alist '(R R2 R3 R-recover)) +;;(pop compilation-error-regexp-alist-alist) + +(defun ess-show-traceback () + "Display R traceback and last error message. +Pop up a compilation/grep/occur like buffer. Usual global key +bindings are available (\\[next-error] and \\[previous-error]) +for `next-error' and `previous-error' respectively. + +You can bind `no-select' versions of this commands: +\(define-key compilation-minor-mode-map [(?n)] #\\='next-error-no-select) +\(define-key compilation-minor-mode-map [(?p)] #\\='previous-error-no-select)" + (interactive) + (cl-assert ess-traceback-command nil + "Not implemented for dialect %s" ess-dialect) + (ring-insert ess--dbg-forward-ring (point-marker)) + (ess-force-buffer-current "R process to use: ") + (let ((trbuf (get-buffer-create "*ess-traceback*")) + (lproc-name ess-local-process-name) + (alist ess-mode-editing-alist) + (cmd ess-traceback-command) + (inhibit-read-only t)) + (setq next-error-last-buffer trbuf) + (with-current-buffer trbuf + (setq ess-local-process-name lproc-name) + (ess-command cmd trbuf) + (goto-char (point-min)) + ;; fixme: this is R specific check + (cl-assert (not (re-search-forward "No traceback available" nil t)) nil + "No traceback available") + (ess-dirs) + (when (boundp 'ess-r-error-regexp-alist) + (setq-local compilation-error-regexp-alist ess-r-error-regexp-alist)) + (setq-local compilation-search-path ess-tracebug-search-path) + (ess-setq-vars-local alist) + (font-lock-refresh-defaults) + (compilation-minor-mode 1) + (setq next-error-function #'ess-tracebug-next-error-function) + (setq buffer-read-only t) + (pop-to-buffer trbuf)))) + +(defvar ess-call-stack-command nil) +(defun ess-show-call-stack () + "Display current call stack. +Also see `ess-show-traceback'" + (interactive) + (let ((ess-traceback-command ess-call-stack-command)) + (ess-show-traceback))) + +(defalias 'ess-show-R-traceback #'ess-show-traceback) + +(defun ess--tb-next-error-goto-process-marker () + ;; assumes current buffer is the process buffer with compilation enabled + ;; used in ess-tracebug-next-error-function + ; (with-current-buffer (process-buffer (get-process ess-local-process-name)) ; already in comint buffer .. no need + (comint-goto-process-mark) + (set-window-point (get-buffer-window) (point)) ;moves the cursor + ;; FIXME: Should jump to current-debug-position, but messes the things if in recover + ;; (when (ess-debug-is-active) + ;; (ess-debug-goto-current-debug-position) + ;; ) + ) + +(defun ess-tracebug-next-error-function (n &optional reset) + "Advance to the next error message and visits the file. +This is the value of `next-error-function' in iESS buffers." + ;; Modified version of `compilation-next-error-function'. + (interactive "p") + (if reset (goto-char (point-max))) + (let* (;; (columns compilation-error-screen-columns) ; buffer's local value + ;; (proc (or (get-buffer-process (current-buffer)) + ;; (error "Current buffer has no process"))) + (pbuff-p (get-buffer-process (current-buffer))) + (n (or n 1)) + (beg-pos ; from where the search for next error starts + (if (and pbuff-p + (>= n 0) + (comint-after-pmark-p)) + ess--tb-last-input + (point))) + (at-error t) + (msg + (condition-case nil + (compilation-next-error n nil beg-pos) + (error + (when pbuff-p + (ess--tb-next-error-goto-process-marker)) + (if (< n 0) + (message "Before first reference") + (message "Beyond last reference"));(error-message-string err)) + (setq at-error nil)))) + (msg (if (or (not pbuff-p) + (eq n 0) + (> (point) ess--tb-last-input)) + msg + (ess--tb-next-error-goto-process-marker) + (message "Beyond last-input marker") + (setq at-error nil))) + (marker (point-marker)) + loc) + (when at-error + (setq compilation-current-error (point-marker) + overlay-arrow-position (if (bolp) + compilation-current-error + (copy-marker (line-beginning-position))) + loc (if (fboundp 'compilation--message->loc) + (compilation--message->loc msg) + (car msg))) + (let* ((file (caar (nth 2 loc))) + (col (car loc)) + (line (cadr loc)) + (mkrs (ess--dbg-create-ref-marker file line col))) + (if mkrs + ;; is this really needed? Shall we go directly to the location? + (compilation-goto-locus marker (car mkrs) (cadr mkrs)) + (message "Reference to '%s' not found" file)))))) + + +(defun inferior-ess-move-last-input-overlay () + "Move the overlay to the point." + (let ((pbol (line-beginning-position))) + (move-overlay ess--tb-last-input-overlay + pbol (max (- (point) 2) (+ pbol 2))))) + + +;;;_* DEBUGGER +(defgroup ess-debug nil + "Debugging for ESS" + :link '(emacs-library-link :tag "Source Lisp File" "ess-tracebug.el") + :group 'ess-tracebug + :prefix "ess-debug-") + +(defcustom ess-debug-error-action-alist + '(( "" "NONE" "NULL" ) + ( " r" "RECOVER" "utils::recover") + ( " t" "TRACEBACK" "base::traceback")) + "Alist of `on-error' actions. +Toggled with `ess-debug-toggle-error-action'. Each element must +have the form (DISP SYMB ACTION) where DISP is the string to be +displayed in the mode line when the action is in place. SYMB is +the symbolic name of an action. ACTION is the string giving the +actual expression to be assigned to `error' user option. See R's +help ?options for more details." + :type '(alist :key-type string + :value-type (group string string)) + :group 'ess-debug) + +(defvar ess--dbg-output-buf-prefix " *ess.dbg" + "The prefix of the buffer name the R debug output is directed to." ) + +(defvar-local ess--dbg-current-ref (make-marker) + "Current debug reference in *ess.dbg* buffers (a marker).") + +(defvar-local ess--dbg-last-ref-marker (make-marker) + "Last debug reference in *ess.dbg* buffer (a marker).") + +(defvar-local ess--dbg-buf-p nil + "This is t in ess.dbg buffers.") + +;; (defcustom ess--dbg-auto-single-key-p t +;; "If t entering the debug state triggers single-key mode. +;; Set it to nil if you want to trigger single-key mode manually +;; with the `ess-tracebug-prefix' key. +;; ") + +(defvar ess--dbg-current-debug-position (make-marker) + "Marker to the current debugged line. +It always point to the beginning of the currently debugged line +and is used by overlay-arrow. +In no-windowed Emacs an `overlay-arrow' is displayed at this position.") + +(unless window-system + (add-to-list 'overlay-arrow-variable-list 'ess--dbg-current-debug-position)) + +(defface ess-debug-current-debug-line-face + '((default (:inherit highlight))) + "Face used to highlight currently debugged line." + :group 'ess-debug) + + +(defvar ess--dbg-current-debug-overlay + (let ((overlay (make-overlay (point) (point)))) + (overlay-put overlay 'face 'ess-debug-current-debug-line-face) + (overlay-put overlay 'evaporate t) + overlay) + ;; should be global variable!! + "The overlay for currently debugged line.") + + +(defcustom ess-debug-blink-interval .2 + "Time in seconds to blink the background of the debug line. +Currently two events are defined `ref-not-found' and `same-ref'. +Blinking colors for these events can be customized by +corresponding faces." + :group 'ess-debug + :type 'float) + +(defface ess-debug-blink-ref-not-found-face + '((((class grayscale) (background light)) (:background "DimGray")) + (((class grayscale) (background dark)) (:background "LightGray")) + (((class color) (background light) (min-colors 88)) (:background "IndianRed4")) + (((class color) (background dark) (min-colors 88)) (:background "dark red")) + (((background light) (min-colors 8)) (:foreground "red")) + (((background dark) (min-colors 8)) (:foreground "red"))) + "Face used to blink currently debugged line's background + when the reference file is not found. See also `ess-debug-ask-for-file'" + :group 'ess-debug ) + +(defface ess-debug-blink-same-ref-face + '((((class grayscale) (background light)) (:background "DimGray")) + (((class grayscale) (background dark)) (:background "LightGray")) + (((class color) (background light) (min-colors 88)) (:background "steel blue")) + (((class color) (background dark) (min-colors 88)) (:background "midnight blue")) + (((background light) (min-colors 8)) (:foreground "blue")) + (((background dark) (min-colors 8)) (:foreground "cyan"))) + "Face used to highlight currently debugged line when new debug +reference is the same as the preceding one. It is highlighted for +`ess-debug-blink-interval' seconds." + :group 'ess-debug ) + +(defcustom ess-debug-ask-for-file nil + "If non nil, ask for file if the current debug reference is not found. + +If nil, the currently debugged line is highlighted for +`ess-debug-blink-interval' seconds." + :group 'ess-debug + :type 'boolean) + +(defcustom ess-debug-skip-first-call t + "If non-nil, skip first debugger call. + +In R first call doesn't contain source references and is skipped +by default." + :group 'ess-debug + :type 'boolean) + +(defvar ess-electric-selection-map + (let (ess-electric-selection-map) + (define-prefix-command 'ess-electric-selection-map) + ;; command-c and command-Q are not always working reliably + (define-key ess-electric-selection-map "\M-N" #'ess-debug-command-continue) + (define-key ess-electric-selection-map "\M-C" #'ess-debug-command-continue) + (define-key ess-electric-selection-map "\M-Q" #'ess-debug-command-quit) + (define-key ess-electric-selection-map "0" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "1" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "2" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "3" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "4" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "5" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "6" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "7" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "8" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "9" #'ess-debug-command-digit) + (define-key ess-electric-selection-map "?" #'ess-tracebug-show-help) + ess-electric-selection-map) + "Keymap used to define commands for single key input mode. +This commands are triggered by `ess-electric-selection' . + +\\{ess-electric-selection-map}") + +;;;_ + debug functions +(defun ess-debug-set-error-action (spec) + "Set the on-error action. +The SPEC should be one of the components of +`ess-debug-error-action-alist'." + (let ((proc (get-process ess-local-process-name))) + (if spec + (with-current-buffer (process-buffer proc) + (process-put proc 'on-error-action (car spec)) + (ess-command (format "options(error= %s )\n" (nth 2 spec)))) + (error "Unknown action")))) + +(defun ess-debug-toggle-error-action () + "Toggle the `on-error' action. +The action list is in `ess-debug-error-action-alist'." + (interactive) + (ess-force-buffer-current) + (let* ((ev last-command-event) + (com-char (event-basic-type ev)) + (cur-action (or (ess-process-get 'on-error-action) "")) + actions act) + (setq actions + (cdr (member (assoc cur-action ess-debug-error-action-alist) + ess-debug-error-action-alist))) + (unless actions + (setq actions ess-debug-error-action-alist)) + (setq act (pop actions)) + (ess-debug-set-error-action act) + (message "On-error action set to: %s" + (propertize (cadr act) 'face 'font-lock-function-name-face)) + (while (eq (event-basic-type (setq ev (read-event))) com-char) + (unless actions + (setq actions ess-debug-error-action-alist)) + (setq act (pop actions)) + (ess-debug-set-error-action act) + (force-mode-line-update) + (message "On-error action set to: %s" + (propertize (cadr act) 'face 'font-lock-function-name-face))) + (push ev unread-command-events))) + +(defun ess--dbg-activate-overlays () + "Initialize active debug line overlays." + (move-overlay ess--dbg-current-debug-overlay + (line-beginning-position) (1+ (line-end-position))) + ;; used by overlay-arrow functionality on no-X, should be bol + (move-marker ess--dbg-current-debug-position (line-beginning-position))) + +(defun ess--dbg-deactivate-overlays () + "Delete debugger markers and overlays. +Overlay arrow remains to indicate the last debug position." + (delete-overlay ess--dbg-current-debug-overlay) + (set-marker ess--dbg-current-debug-position nil)) + + +;;;_ + Work Flow +(defun ess-debug-goto-input-event-marker () + "Jump to the point where the last debugger/traceback etc event occurred. + + Mainly useful during/after debugging, to jump to the place +from where the code was initially executed. This is an +electric-command, which means that after the command is triggered a +single key event is enough to navigate through the input-event-S-ring. +If the key-event which triggered the command is Shift modified +the input-event-S-ring is traversed backwards. + +The input-event-S-ring is a virtual object which consists of two +rings `ess--dbg-forward-ring' and `ess--dbg-backward-ring' which +are joint at their tops. + +See the more info at https://code.google.com/p/ess-tracebug/#Work-Flow" + (interactive) + (let* ((ev last-command-event) + (com-char (event-basic-type ev)) + (ring-el 0) + input-point) + (if (memq 'shift (event-modifiers ev)) + (setq input-point (ring-ref ess--dbg-backward-ring 0)) + (ring-insert ess--dbg-backward-ring (point-marker)) ;; insert in backward ring ;;TODO: check if the marker to this (close by?) position is already in the ring + (setq input-point (ring-ref ess--dbg-forward-ring 0))) + (when (marker-buffer input-point) ;; TODO: give a message here if buff is not found + (pop-to-buffer-same-window (marker-buffer input-point)) + (when (marker-position input-point) + (goto-char (marker-position input-point)))) + (while (eq (event-basic-type (event-basic-type (setq ev (read-event)))) com-char) + (if (memq 'shift (event-modifiers ev)) + (setq ring-el (1- ring-el)) + (setq ring-el (1+ ring-el))) + (if (< ring-el 0) + (setq input-point (ring-ref ess--dbg-backward-ring (- ring-el))) ;; get it from backward-ring + ;; get it from forward-ring + (setq input-point (ring-ref ess--dbg-forward-ring ring-el)) ) + (when (marker-buffer input-point) + (pop-to-buffer-same-window (marker-buffer input-point)) + (when (marker-position input-point) + (goto-char (marker-position input-point))))) + (push ev unread-command-events))) + +(defun ess-debug-goto-debug-point () + "Return to the debugging position. +Jump to markers stored in `ess--dbg-backward-ring'. If debug +session is active, first jump to current debug line. + +This is an electric-command. Shift triggers the opposite traverse +of the ring." + (interactive) + (let* ((debug-point (ring-ref ess--dbg-backward-ring 0)) + (ev last-command-event) + (com-char (event-basic-type ev)) + (ring-el 0)) + (if (ess--dbg-is-active-p) + (progn + (pop-to-buffer-same-window (marker-buffer ess--dbg-current-debug-position)) + (goto-char (marker-position ess--dbg-current-debug-position )) + (back-to-indentation)) + (pop-to-buffer-same-window (marker-buffer debug-point)) + (goto-char (marker-position debug-point))) + (while (eq (event-basic-type (setq ev (read-event))) com-char) + (if (memq 'shift (event-modifiers ev)) + (setq ring-el (1- ring-el)) + (setq ring-el (1+ ring-el))) + (setq debug-point (ring-ref ess--dbg-backward-ring ring-el)) + (when (marker-buffer debug-point) + (pop-to-buffer-same-window (marker-buffer debug-point)) + (when (marker-position debug-point) + (goto-char (marker-position debug-point))))) + (push ev unread-command-events))) + +(defun ess-debug-insert-in-forward-ring () + "Insert `point-marker' into the forward-ring." + (interactive) + (ring-insert ess--dbg-forward-ring (point-marker)) + (message "Point inserted into the forward-ring")) + +(defvar ess-debug-indicator " DB" + "String to be displayed in mode-line alongside the process name. +Indicates that ess-debug-mode is turned on. When the debugger is +in active state this string is shown in upper case and +highlighted.") + +(defvar-local ess--dbg-mode-line-debug + '(:eval (let ((proc (get-process ess-local-process-name))) + (if (and proc (process-get proc 'dbg-active)) + (let ((str ess-debug-indicator)) + (ess-debug-minor-mode 1) ; activate the keymap + (put-text-property 1 (length str) + 'face '(:foreground "white" :background "red") + str) + str) + (ess-debug-minor-mode -1) + "")))) +(put 'ess--dbg-mode-line-debug 'risky-local-variable t) + +(defvar-local ess--dbg-mode-line-error-action + '(:eval (or (and (ess-process-live-p) + (ess-process-get 'on-error-action)) + ""))) +(put 'ess--dbg-mode-line-error-action 'risky-local-variable t) + +(defun ess--dbg-remove-empty-lines (string) + "Remove empty lines from STRING (which interfere with evals) during debug. +This function is placed in `ess-presend-filter-functions'." + (if (and ess--dbg-del-empty-p (ess-process-get 'dbg-active)) + (replace-regexp-in-string "\n\\s *$" "" string) + string)) + + +(defun ess-debug-start () + "Start the debug session. +Add to ESS the interactive debugging functionality, breakpoints, +watch and loggers. Integrates into ESS and iESS modes by binding +`ess-tracebug-map' to `ess-tracebug-prefix' in +`ess-mode-map' and `inferior-ess-mode-map' respectively." + (interactive) + (let ((dbuff (get-buffer-create (concat ess--dbg-output-buf-prefix "." ess-current-process-name "*"))) ;TODO: make dbuff a string! + (proc (ess-get-process ess-local-process-name)) + (lpn ess-local-process-name)) + (process-put proc 'dbg-buffer dbuff); buffer were the look up takes place + (process-put proc 'dbg-active nil) ; t if the process is in active debug state. + ; Active debug states are usually those, in which prompt start with Browser[d]> + (set-process-filter proc #'inferior-ess-tracebug-output-filter) + (with-current-buffer (process-buffer proc) + (unless (equal ess-dialect "R") + (error "Can not activate the debugger for %s dialect" ess-dialect)) + (add-to-list 'ess--mode-line-process-indicator 'ess--dbg-mode-line-debug t) + (add-to-list 'ess--mode-line-process-indicator 'ess--dbg-mode-line-error-action t) + + (add-hook 'ess-presend-filter-functions #'ess--dbg-remove-empty-lines nil 'local)) + (with-current-buffer dbuff + (setq ess-local-process-name lpn) + (buffer-disable-undo) + ;; (setq buffer-read-only nil) + (make-local-variable 'overlay-arrow-position) ;; indicator for next-error functionality in the *ess.dbg*, useful?? + (goto-char (point-max)) + (setq ess--dbg-buf-p t ;; true if in *ess.dbg* buffer + ess--dbg-current-ref (point-marker) ;; used by goto-error functionality + ess--dbg-last-ref-marker (point-marker) ;; gives marker to reference of the last debugged line + ) + ;; (beginning-of-line) + ;; (setq buffer-read-only t) + ))) + +(defun ess-debug-stop () + "End the debug session. +Kill the *ess.dbg.[R_name]* buffer." + ;;; process plist is not removed, TODO?low priority + (interactive) + (let ((proc (get-process ess-current-process-name))) ;;local? + (with-current-buffer (process-buffer proc) + (if (member ess-dialect '("XLS" "SAS" "STA")) + (error "Can not deactivate the debugger for %s dialect" ess-dialect)) + (delq 'ess--dbg-mode-line-debug ess--mode-line-process-indicator) + (delq 'ess--dbg-mode-line-error-action ess--mode-line-process-indicator) + (remove-hook 'ess-presend-filter-functions #'ess--dbg-remove-empty-lines 'local)) + (set-process-filter proc #'inferior-ess-output-filter) + (kill-buffer (process-get proc 'dbg-buffer)) + (process-put proc 'dbg-buffer nil) + (process-put proc 'dbg-active nil) + ;; (when (buffer-live-p ess--dbg-buffer) + ;; ;; (with-current-buffer ess--dbg-buffer + ;; ;; (set-buffer-modified-p nil) + ;; ;; ) + ;; (kill-buffer ess--dbg-buffer) + ;; ) + )) + + +(defun ess--make-busy-timer-function (process) + "Display the spinner of prompt if PROCESS is busy." + `(lambda () + (let ((pb ,process)) + (when (eq (process-status pb) 'run) ;; only when the process is alive + (with-current-buffer (process-buffer pb) + (if (not (process-get pb 'busy)) ;; if ready + (when (> ess--busy-count 0) + (setq ess--busy-count 0) + (force-mode-line-update) + (redisplay)) + (setq ess--busy-count (1+ (mod ess--busy-count (1- (length ess-busy-strings))))) + (force-mode-line-update) + (redisplay))))))) + +;; (ess--make-busy-prompt-function (get-process "R")) + +(defun ess--dbg-is-active-p () + "Return t if the current R process is in active debugging state." + (and (ess-process-live-p) + (ess-process-get 'dbg-active))) + +(defun ess--dbg-is-recover-p () + "Return t if the current R process is in active debugging state." + (and (ess-process-live-p) + (ess-process-get 'is-recover))) + +(defun ess-debug-active-p (&optional proc) + (and (ess-process-live-p proc) + (or (ess-process-get 'dbg-active proc) + (ess-process-get 'is-recover proc)))) + +(defvar ess--dbg-regexp-reference "debug \\w+ +\\(.+\\)#\\([0-9]+\\):") +(defvar ess--dbg-regexp-jump "debug \\w+ ") ;; debug at ,debug bei ,etc +(defvar ess--dbg-regexp-skip + ;; don't anchor to bol; secondary prompt can occur before (anything else?) + ;; "\\(\\(?:Called from: \\)\\|\\(?:debugging in: \\)\\|\\(?:#[0-9]*: +recover()\\)\\)") + "\\(\\(?:Called from: \\)\\|\\(?:#[0-9]*: +recover()\\)\\)") + +(defvar ess--dbg-regexp-no-skip + ;; exceptions for first skip (magrittr) + "debug_pipe") + +(defvar ess--dbg-regexp-debug "\\(\\(?:Browse[][0-9]+\\)\\|\\(?:debug: \\)\\)") +(defvar ess--dbg-regexp-selection "\\(Selection: \\'\\)") +(defvar ess--dbg-regexp-input (concat ess--dbg-regexp-debug "\\|" + ess--dbg-regexp-selection)) + +(defvar ess--suppress-next-output? nil) + + + +;;; MPI + +;; http://jkorpela.fi/chars/c0.html +;; https://en.wikipedia.org/wiki/ANSI_escape_code#Escape_sequences +(defvar ess-mpi-message-start-delimiter "_") +(defvar ess-mpi-message-field-separator "") +(defvar ess-mpi-message-end-delimiter "\\") + +(define-obsolete-variable-alias 'ess-mpi-alist 'ess-mpi-handlers "ESS 19.04") +(defvar ess-mpi-handlers + '(("message" . ess-mpi:message) + ("error" . ess-mpi:error) + ("eval" . ess-mpi:eval) + ("y-or-n" . ess-mpi:y-or-n)) + "Alist of the MPI handlers. +Each element is of the form (TYPE . HANDLER), where TYPE is the +message type and HANDLER is a function (symbol) to be called on +the payload list of each message.") + +(defun ess-mpi:message (msg) + (message "%s" msg)) + +(defun ess-mpi:error (msg) + (error "MPI error: %s" msg)) + +(defun ess-mpi:eval (str &optional callback) + "Read STR and evaluate as Emacs expression. +If present, the CALLBACK string is passed through `format' with +returned value from EXPR and then sent to the subprocess." + (let ((result (eval (read str) t))) + (when callback + (ess-send-string (ess-get-process) (format callback result))))) + +(defun ess-mpi:y-or-n (prompt callback) + "Ask `y-or-n-p' with PROMPT. +The CALLBACK string is passed through `format' with returned +value from EXPR and then sent to the subprocess." + (let ((result (y-or-n-p prompt))) + (when callback + (let ((result (if result "TRUE" "FALSE"))) + (ess-send-string (ess-get-process) (format callback result)))))) + +(defun ess-mpi-convert (el) + (cond + ((string= el "nil") nil) + ((string= el "t") t) + (t el))) + +(defun ess-mpi-handle-messages (buf) + "Handle all mpi messages in BUF and delete them. +The MPI message has the form TYPEFIELD... where TYPE is the +type of the messages on which handlers in `ess-mpi-handlers' are +dispatched. And FIELDs are strings. Return :incomplete if BUF +ends with an incomplete message." + (let ((obuf (current-buffer)) + (out nil)) + (with-current-buffer buf + (goto-char (point-min)) + ;; This should be smarter because Emacs might cut it in the middle of the + ;; message. In practice this almost never happen because we are + ;; accumulating output into the cache buffer. + (while (search-forward ess-mpi-message-start-delimiter nil t) + (let ((mbeg0 (match-beginning 0)) + (mbeg (match-end 0))) + (if (search-forward ess-mpi-message-end-delimiter nil t) + (let* ((mend (match-beginning 0)) + (mend0 (match-end 0)) + (msg (buffer-substring mbeg mend)) + (payload (mapcar #'ess-mpi-convert + (split-string msg ess-mpi-message-field-separator))) + (head (pop payload)) + (handler (cdr (assoc head ess-mpi-handlers)))) + (unwind-protect + (if handler + (with-current-buffer obuf + (apply handler payload)) + (error "No handler defined for MPI message '%s" head)) + (goto-char mbeg0) + (delete-region mbeg0 mend0))) + (setq out :incomplete)))) + out))) + +(defun ess--replace-long+-in-prompt (proc prompt is-final) + "Replace long + + + in PROMPT based on `inferior-ess-replace-long+' value. +If IS-FINAL means that PROMPT occurs at the end of the process +chunk. If non-nil, special care is taken not to drop last '+' +value as it might be a continuation prompt." + ;; see #576 for interesting input examples + (let ((len (length prompt)) + (inferior-ess-replace-long+ (buffer-local-value + 'inferior-ess-replace-long+ + (process-buffer proc)))) + (if (or (null inferior-ess-replace-long+) + (< len 2)) + prompt + (let ((last+ (eq (elt prompt (- len 2)) ?+))) + (cond + ((eq inferior-ess-replace-long+ 'strip) + (if (and last+ is-final) + "+ " + "> ")) + ((eq inferior-ess-replace-long+ t) + (let ((prompt (replace-regexp-in-string "\\(\\+ \\)\\{2\\}\\(\\+ \\)+" + ess-long+replacement prompt))) + (if (and last+ (not is-final)) + ;; append > for aesthetic reasons + (concat prompt "> ") + prompt))) + (t (error "Invalid values of `inferior-ess-replace-long+'"))))))) + +(defun ess--offset-output (prev-prompt str) + "Add suitable offset to STR given the preceding PREV-PROMPT. +Do nothing if `inferior-ess-fix-misaligned-output' is nil." + (if (and inferior-ess-fix-misaligned-output prev-prompt) + (let ((len (length prev-prompt))) + ;; prompts have at least 2 chars + (if (eq (elt prev-prompt (- len 2)) ?+) + ;; when last + append > for aesthetic reasons + (concat "> \n" str) + (if (eq (elt str 0) ?\n) + ;; don't insert empty lines + str + (concat "\n" str)))) + str)) + +(defun ess--flush-accumulated-output (proc) + "Flush accumulated output of PROC into its output buffer. +Insertion happens chunk by chunk. A chunk is a region between two +prompts." + (let* ((abuf (ess--accumulation-buffer proc)) + (pbuf (process-buffer proc)) + (visibly (process-get proc :eval-visibly)) + (nowait (eq visibly 'nowait)) + (flush-timer (process-get proc 'flush-timer))) + (when (> (buffer-size abuf) 0) + (when (timerp flush-timer) + (cancel-timer flush-timer)) + (if (eq (buffer-local-value 'major-mode pbuf) 'fundamental-mode) + ;; FIXME: this cannot be, ess-command changes the filter + ;; Just in case if we are in *ess-command* buffer; restart the timer. + (process-put proc 'flush-timer + (run-at-time .02 nil #'ess--flush-accumulated-output proc)) + ;; Incomplete mpi should hardly happen. Only on those rare occasions + ;; when an mpi is issued after a long task and split by the Emacs input + ;; handler, or mpi printing itself takes very long. + (unless (eq :incomplete (ess-mpi-handle-messages abuf)) + (with-current-buffer abuf + ;; Uncomment this line when debugging. This pops up the + ;; accumulation buffer and causes point to follow + ;; automatically as the parsing progresses. + ;; (pop-to-buffer (current-buffer)) + (goto-char (point-min)) + (let ((case-fold-search nil)) + (when (re-search-forward "Error\\(:\\| +in\\)" nil t) + (unless (get-buffer-window pbuf 'visible) + (setq next-error-last-buffer pbuf) + (display-buffer pbuf nil t)))) + (goto-char (point-min)) + ;; First long + + in the output mirrors the sent input by the user and + ;; is unnecessary in nowait case. A single + can be a continuation in + ;; the REPL, thus we check if there is an extra output after the + . + (when nowait + (when (looking-at "\\([+>] \\)\\{2,\\}\n?") + (goto-char (match-end 0)) + (when (eq (point) (point-max)) + ;; if this is the last prompt in the output back-up one prompt + ;; (cannot happen after \n) + (backward-char 2)))) + (let ((do-clean (not (eq visibly t))) + (pos2 (point)) + (pos1 (point)) + (tpos nil) + (prompt nil) + (regexp (if nowait + ;; we cannot disambiguate printed input fields and + ;; prompts in output in this case; match 2+ pluses or + ;; > and 2+ spaces + "\\(^\\([+>] \\)\\{2,\\}\\)\\|\\(> \\) +" + "^\\([+>] \\)+")) + (prev-prompt (process-get proc 'prev-prompt))) + (while (re-search-forward regexp nil t) + (setq pos1 (match-beginning 0) + tpos (if nowait + (or (match-end 1) (match-end 3)) + (match-end 0))) + (when (> pos1 pos2) + (let ((str (buffer-substring pos2 pos1))) + (comint-output-filter proc (ess--offset-output prev-prompt str)))) + (setq pos2 tpos) + (setq prompt (let ((prompt (buffer-substring pos1 pos2))) + (if do-clean + (ess--replace-long+-in-prompt proc prompt (eq pos2 (point-max))) + prompt))) + ;; Cannot bypass this trivial call to comint-output-filter because + ;; external tools could rely on prompts (org-babel [#598] for + ;; example). Setting dummy regexp in order to avoid comint erasing + ;; this prompt which contrasts to how we output prompts in all + ;; other cases. + (with-current-buffer pbuf + (let ((comint-prompt-regexp "^$")) + (comint-output-filter proc prompt))) + (setq prev-prompt (and do-clean prompt) + pos1 pos2)) + ;; insert last chunk if any + (unless (eq pos1 (point-max)) + (let ((str (buffer-substring-no-properties pos1 (point-max)))) + (comint-output-filter proc (ess--offset-output prev-prompt str)) + (setq prev-prompt nil))) + (process-put proc 'prev-prompt prev-prompt) + (process-put proc 'flush-time (and (process-get proc 'busy) + (float-time))) + (erase-buffer)))))))) + +(defun inferior-ess-tracebug-output-filter (proc string) + "Standard output filter for the inferior ESS process. +When `ess-debug' is active, this is the filter. Call +`inferior-ess-output-filter'. Check for debug +reg-expressions (see `ess--dbg-regexp-debug',...), when found +puts iESS in the debugging state. If in debugging state, mirrors +the output into *ess.dbg* buffer." + (let* ((is-iess (or (derived-mode-p 'ess-watch-mode) + (derived-mode-p 'inferior-ess-mode))) + (pbuf (process-buffer proc)) + (abuf (ess--accumulation-buffer proc)) + (dbuff (process-get proc 'dbg-buffer)) + (wbuff (get-buffer ess-watch-buffer)) + (was-in-dbg (process-get proc 'dbg-active)) + (was-in-recover (process-get proc 'is-recover)) + (input-point (point-marker)) + (match-jump (string-match ess--dbg-regexp-jump string)) + (match-input (string-match ess--dbg-regexp-input string)) + (match-selection (and match-input + (match-string 2 string))) ;; Selection: + (match-skip (and ess-debug-skip-first-call + (string-match ess--dbg-regexp-skip string) + (not (string-match ess--dbg-regexp-no-skip string)))) + (match-dbg (or match-skip (and match-input (not match-selection)))) + (is-ready (inferior-ess--set-status proc string)) + (new-time (float-time)) + (last-time (process-get proc 'flush-time)) + (flush-timer (process-get proc 'flush-timer))) + + ;; current-buffer is still the user's input buffer here + (ess--if-verbose-write-process-state proc string "tracebug-filter") + (inferior-ess-run-callback proc string) + (process-put proc 'is-recover match-selection) + + (if (or (process-get proc 'suppress-next-output?) + ess--suppress-next-output?) + + ;; works only for suppressing short output, enough for now (for callbacks) + (process-put proc 'suppress-next-output? nil) + + (with-current-buffer abuf + (goto-char (point-max)) + (insert string)) + + ;; cancel the timer each time we enter this filter + (when (timerp flush-timer) + (cancel-timer flush-timer) + (process-put proc 'flush-timer nil)) + + (unless last-time ;; don't flush for the first time + (setq last-time new-time) + (process-put proc 'flush-time new-time)) + + ;; flush periodically + (let ((fast-flush (or is-ready + ;; for the sake of ess-eval-linewise + (process-get proc 'sec-prompt)))) + (if (or + ;; theoretically we should flush asynchronously in all cases but + ;; somewhat unexpectedly it introduces much more randomness during + ;; batch testing. TODO: flush directly for now and either remove or + ;; improve on the next refactoring iteration + fast-flush + (> (- new-time last-time) .5) + (bound-and-true-p edebug-mode) + ;; the flush is not getting called if the third party call + ;; accept-process-output in a loop (e.g. org-babel-execute-src-block) + (bound-and-true-p org-babel-current-src-block-location)) + (ess--flush-accumulated-output proc) + ;; Setup new flush timer. Ideally also for fast-flush case in order to + ;; avoid detecting intermediate prompts as end-of-output prompts. + (let ((timeout (if fast-flush .01 .2))) + (process-put proc 'flush-timer + (run-at-time timeout nil #'ess--flush-accumulated-output proc)))))) + + ;; WATCH + (when (and is-ready wbuff) ;; refresh only if the process is ready and wbuff exists, (not only in the debugger!!) + (ess-watch-refresh-buffer-visibly wbuff)) + + ;; JUMP to line if debug expression was matched + (when match-jump + (with-current-buffer dbuff ;; insert string in *ess.dbg* buffer + (goto-char (point-max)) + (insert (concat "|-" string "-|"))) + (ess--dbg-goto-last-ref-and-mark dbuff is-iess)) + + ;; (with-current-buffer dbuff ;; un-comment to see the value of STRING just before debugger exists + ;; (let ((inhibit-read-only t)) + ;; (goto-char (point-max)) + ;; (insert (concat " ---\n " string "\n ---")) + ;; )) + + ;; SKIP if needed + (when (and match-skip (not was-in-recover)) + (process-send-string proc "n\n")) + + ;; EXIT the debugger + (when (and was-in-dbg + (not (or match-jump match-dbg)) + (or is-ready match-selection)) + (ess--dbg-deactivate-overlays) + (process-put proc 'dbg-active nil) + ;; (message "|<-- exited debugging -->|") + (when wbuff + (ess-watch-refresh-buffer-visibly wbuff))) + + ;; ACTIVATE the debugger if entered for the first time + (when (and (not was-in-dbg) + (not match-selection) + (or match-jump match-dbg)) + (unless is-iess + (ring-insert ess--dbg-forward-ring input-point)) + (process-put proc 'dbg-active t) + (message + (ess--debug-keys-message-string)) + (unless match-jump + ;; no source reference, simply show the inferior + (display-buffer pbuf))) + + (when (and match-selection (not is-iess)) ;(and (not was-in-recover) match-selection) + (ess-electric-selection t)))) + + +(defvar ess-debug-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "M-C") #'ess-debug-command-continue) + (define-key map [(control meta ?C)] #'ess-debug-command-continue-multi) + (define-key map (kbd "M-N") #'ess-debug-command-next) + (define-key map [(control meta ?N)] #'ess-debug-command-next-multi) + (define-key map (kbd "M-Q") #'ess-debug-command-quit) + (define-key map (kbd "M-U") #'ess-debug-command-up) + map) + "Keymap active when ESS process is in debugging state. +\\{ess-debug-minor-mode-map}") + + +(define-minor-mode ess-debug-minor-mode + "Minor mode activated when ESS process is in debugging state." + :lighter nil + :keymap ess-debug-minor-mode-map) + +(defun ess--dbg-goto-last-ref-and-mark (dbuff &optional other-window) + "Open the most recent debug reference and set the necessary marks and overlays. +It's called from `inferior-ess-tracebug-output-filter'. DBUFF +must be the *ess.dbg* buffer associated with the process. If +OTHER-WINDOW is non nil, attempt to open the location in a +different window." + (let (t-debug-position ref) + (with-current-buffer dbuff + (setq ref (ess--dbg-get-next-ref -1 (point-max) ess--dbg-last-ref-marker + ess--dbg-regexp-reference)) ; sets point at the end of found ref + (when ref + (move-marker ess--dbg-last-ref-marker (line-end-position)) + ;; each new step repositions the current-ref! + (move-marker ess--dbg-current-ref ess--dbg-last-ref-marker))) + (when ref + (let ((buf (apply #'ess--dbg-goto-ref other-window ref))) + (if buf + ;; if referenced buffer has been found, put overlays: + (with-current-buffer buf + (setq t-debug-position (copy-marker (line-beginning-position))) + (if (equal t-debug-position ess--dbg-current-debug-position) + (progn ;; highlights the overlay for ess--dbg-blink-interval seconds + (overlay-put ess--dbg-current-debug-overlay 'face 'ess--dbg-blink-same-ref-face) + (run-with-timer ess-debug-blink-interval nil + (lambda () + (overlay-put ess--dbg-current-debug-overlay 'face 'ess-debug-current-debug-line-face)))) + ;; else + (ess--dbg-activate-overlays))) + ;;else, buffer is not found: highlight and give the corresponding message + (overlay-put ess--dbg-current-debug-overlay 'face 'ess--dbg-blink-ref-not-found-face) + (run-with-timer ess-debug-blink-interval nil + (lambda () + (overlay-put ess--dbg-current-debug-overlay 'face 'ess-debug-current-debug-line-face))) + (message "Reference %s not found" (car ref))))))) + +(defun ess--dbg-goto-ref (other-window file line &optional col) + "Opens the reference given by FILE, LINE and COL. +Try to open in a different window if OTHER-WINDOW is nil. Return +the buffer if found, or nil otherwise be found. +`ess--dbg-find-buffer' is used to find the FILE and open the +associated buffer. If FILE is nil return nil." + (let ((mrk (car (ess--dbg-create-ref-marker file line col))) + (lpn ess-local-process-name)) + (when mrk + (let ((buf (marker-buffer mrk))) + (if (not other-window) + (pop-to-buffer-same-window buf) + (let ((this-frame (window-frame (get-buffer-window (current-buffer))))) + (display-buffer buf) + ;; simple save-frame-excursion + (unless (eq this-frame (window-frame (get-buffer-window buf t))) + (ess-select-frame-set-input-focus this-frame)))) + ;; set or re-set to lpn as this is the process with debug session on + (with-current-buffer buf + (setq ess-local-process-name lpn) + (goto-char mrk) + (set-window-point (get-buffer-window buf) mrk)) + buf)))) + +;; temporary, hopefully org folks implement something similar +(defvar org-babel-tangled-file nil) +(declare-function org-babel-tangle-jump-to-org "ob-tangle.el") + +(defun ess--dbg-create-ref-marker (file line &optional col) + "Create markers to the reference given by FILE, LINE and COL. +Return list of two markers MK-start and MK-end. MK-start is the +position of error. Mk-end is the end of the line where error +occurred. If buffer associated with FILE is not found, or line is +nil, or TB-INDEX is not found return nil." + (if (stringp line) (setq line (string-to-number line))) + (if (stringp col) (setq col (string-to-number col))) + (let* ((srcref (gethash file ess--srcrefs)) + (file (replace-regexp-in-string "^\n" "" ;; hack for gnu regexp + (or (car srcref) file))) + (tb-index (cadr srcref)) + (buffer (ess--dbg-find-buffer file)) + pos) + (when (and buffer line) + (save-excursion + (with-current-buffer buffer + (save-restriction + (widen) ;; how does this behave in narrowed buffers? tothink: + (goto-char 1) + (setq pos (point)) + (when tb-index + (while (and (not (eq tb-index (get-text-property pos 'tb-index))) + (setq pos (next-single-property-change pos 'tb-index))))) + (unless pos + ;; use beg position if index not found + (setq pos (nth 2 srcref))) + (when pos + (goto-char pos) + (forward-line (1- line)) + (if col + (goto-char (+ (line-beginning-position) col)) + (back-to-indentation)) + (when (bound-and-true-p org-babel-tangled-file) + (org-babel-tangle-jump-to-org)) + (list (point-marker) (copy-marker (line-end-position)))))))))) + +(defvar ess-r-package-library-paths) +(defun ess--dbg-find-buffer (filename) + "Find a buffer for file FILENAME. +If FILENAME is not found at all, ask the user where to find it if +`ess--dbg-ask-for-file' is non-nil. Search the directories in +`ess-tracebug-search-path' and `ess-r-package-library-paths'." + (let ((dirs (append + (ess-r-package-source-dirs) + ess-r-package-library-paths + (cl-loop for d in (append ess-tracebug-search-path) + append (ess-r-package--all-source-dirs d)))) + (filematch (format "%s\\'" filename)) + buffer name) + (setq dirs (delq nil (cons (with-ess-process-buffer t default-directory) dirs))) + ;; 1. The file name is absolute. Use its explicit directory as + ;; the first in the search path, and strip it from FILENAME. + (when (and (null buffer) + (file-name-absolute-p filename)) + (setq filename (abbreviate-file-name (expand-file-name filename)) + dirs (cons (file-name-directory filename) dirs) + filename (file-name-nondirectory filename))) + (or + ;; 2. Search the path. + (while (and (null buffer) dirs) + (let ((thisdir (pop dirs))) + (setq name (expand-file-name filename thisdir) + buffer (and (file-exists-p name) + (find-file-noselect name))))) + buffer + + ;; 3. search already open buffers for match (associated file might not even exist yet) + (cl-dolist (bf (buffer-list)) + (with-current-buffer bf + (when (and buffer-file-name + (string-match filematch buffer-file-name)) + (setq buffer bf) + (cl-return)))) + buffer + + ;; 4. Ask for file if not found (tothink: maybe remove this part?) + (when ess-debug-ask-for-file + (save-excursion ;This save-excursion is probably not right. + (let* ((pop-up-windows t) + (name (read-file-name + (format "Find next line in (default %s): " filename) + nil filename t nil)) + (origname name)) + (cond + ((not (file-exists-p name)) + (message "Cannot find file `%s'" name) + (ding) (sit-for 2)) + ((and (file-directory-p name) + (not (file-exists-p + (setq name (expand-file-name filename name))))) + (message "No `%s' in directory %s" filename origname) + (ding) (sit-for 2)) + (t + (setq buffer (find-file-noselect name))))))) + buffer))) + +(defun ess--dbg-get-next-ref (n &optional pt BOUND REG nF nL nC) + "Move point to the next reference in the *ess.dbg* buffer. + +Must be called from *ess.dbg* buffer. +It returns the reference in the form (file line col) /all strings/ , +or NIL if not found . Prefix arg N says how many error messages +to move forwards (or backwards, if negative). Optional arg PT, +if non-nil, specifies the value of point to start looking for the +next message, default to (point). BOUND is the limiting position +of the search. REG is the regular expression to search with. nF +- sub-expression of REG giving the `file'; defaults to 1. nL - +giving the `line'; defaults to 2. nC - sub-expr giving the +`column'; defaults to 3." + (unless ess--dbg-buf-p + (error "Not in *ess.dbg* buffer")) + (setq nF (or nF 1) + nL (or nL 2) + nC (or nC 3)) + (or pt (setq pt (point))) + ;; (message "ess--dbg-last-ref-marker%s vs pt%s vs point-max%s" ess--dbg-last-ref-marker pt (point-max)) + (goto-char pt) + (if (search-forward-regexp REG BOUND t n) + (list (match-string nF) (match-string-no-properties nL) (match-string-no-properties nC)) + nil)) + +(defun ess--debug-keys-message-string (&optional map) + (let ((overriding-local-map (or map ess-debug-minor-mode-map))) + (substitute-command-keys + (mapconcat #'identity + '("(\\[ess-debug-command-continue])cont" + "(\\[ess-debug-command-continue-multi])cont-multi" + "(\\[ess-debug-command-next])next" + "(\\[ess-debug-command-next-multi])next-multi" + "(\\[ess-debug-command-up])up" + "(\\[ess-debug-command-quit])quit") + " ")))) + +(defun ess-electric-selection (&optional wait) + "Call commands defined in `ess-electric-selection-map'. +Single-key input commands are those, which once executed do not +require the prefix command for subsequent invocation. + +If WAIT is t, wait for next input and ignore the keystroke which +triggered the command." + (interactive) + (ess--execute-electric-command ess-electric-selection-map + "Selection: " wait + (not (ess-process-get 'is-recover)))) + +(defun ess-debug-command-digit (&optional ev) + "Digit commands in selection mode. +If supplied, EV must be a proper key event or a string representing the digit." + (interactive) + (ess-force-buffer-current) + (unless (ess--dbg-is-recover-p) + (error "Recover is not active")) + (unless ev + (setq ev last-command-event)) + (let* ((ev-char (if (stringp ev) + ev + (char-to-string (event-basic-type ev)))) + (proc (get-process ess-current-process-name)) + (mark-pos (marker-position (process-mark proc))) + (comint-prompt-read-only nil) + prompt depth) + (with-current-buffer (process-buffer proc) + (goto-char mark-pos) + (save-excursion + (when (re-search-backward "\\(?: \\|^\\)\\([0-9]+\\):[^\t]+Selection:" ess--tb-last-input t) + (setq depth (string-to-number (match-string 1))) + (when (> depth 9) + (setq ev-char (ess-completing-read "Selection" (mapcar #'number-to-string + (number-sequence depth 0 -1)) + nil t ev-char nil))))) + (setq prompt (delete-and-extract-region (line-beginning-position) mark-pos)) + (insert (concat prompt ev-char "\n")) + (ess-send-string proc ev-char) + (move-marker (process-mark proc) (max-char))))) + +(defun ess-debug-command-next () + "Step next in debug mode. +Equivalent to `n' at the R prompt." + (interactive) + (ess-force-buffer-current) + (unless (ess--dbg-is-active-p) + (error "Debugger is not active")) + (if (ess--dbg-is-recover-p) + (ess-send-string (ess-get-process) "0") + (ess-send-string (ess-get-process) "n"))) + +(defun ess-debug-command-next-multi (&optional N) + "Ask for N and step (n) N times in debug mode." + (interactive) + (ess-force-buffer-current) + (unless (ess--dbg-is-active-p) + (error "Debugger is not active")) + (let ((N (or N (read-number "Number of steps: " 10))) + (ess--suppress-next-output? t)) + (while (and (ess--dbg-is-active-p) (> N 0)) + (ess-debug-command-next) + (ess-wait-for-process) + (setq N (1- N)))) + (ess-debug-command-next)) + +(defun ess-debug-command-continue-multi (&optional N) + "Ask for N, and continue (c) N times in debug mode." + (interactive) + (ess-force-buffer-current) + (unless (ess--dbg-is-active-p) + (error "Debugger is not active")) + (let ((N (or N (read-number "Number of continuations: " 10))) + (ess--suppress-next-output? t)) + (while (and (ess--dbg-is-active-p) (> N 1)) + (ess-debug-command-continue) + (ess-wait-for-process) + (setq N (1- N)))) + (ess-debug-command-continue)) + +(defun ess-debug-command-up () + "Step up one call frame.." + (interactive) + (ess-force-buffer-current) + (unless (ess--dbg-is-active-p) + (error "Debugger is not active")) + (let ((up-cmd "try(browserSetDebug(), silent=T)\nc\n")) + (ess-send-string (ess-get-process) up-cmd))) + +;; (defun ess-debug-previous-error (&optional ev) +;; "Go to previous reference during the debug process. +;; R doesn't support step backwards. This command just takes you through +;; debug history." +;; (interactive) +;; (previous-error)) + +(defun ess-debug-command-quit () + "Quits the browser/debug in R process. +Equivalent of `Q' at the R prompt." + (interactive) + (ess-force-buffer-current) + (cond ((ess--dbg-is-recover-p) + (ess-send-string (ess-get-process) "0" t)) + ;; if recover is called in a loop the following stalls Emacs + ;; (ess-wait-for-process proc nil 0.05) + ((ess--dbg-is-active-p) + (ess-send-string (ess-get-process) "Q" t)) + (t + (error "Debugger is not active")))) + +(defun ess-debug-command-continue () + "Continue the code execution. +Equivalent of `c' at the R prompt." + (interactive) + (ess-force-buffer-current) + (cond ((ess--dbg-is-recover-p) + (ess-send-string (ess-get-process) "0")) + ((ess--dbg-is-active-p) + (ess-send-string (ess-get-process) "c")) + (t + (error "Debugger is not active")))) + +(defun ess-tracebug-set-last-input (&rest _args) + "Move `ess--tb-last-input' marker to the process mark. +ARGS are ignored to allow using this function in process hooks." + (let* ((last-input-process (get-process ess-local-process-name)) + (last-input-mark (copy-marker (process-mark last-input-process)))) + (with-current-buffer (process-buffer last-input-process) + (when (local-variable-p 'ess--tb-last-input) ;; TB might not be active in all processes + (save-excursion + (setq ess--tb-last-input last-input-mark) + (goto-char last-input-mark) + (inferior-ess-move-last-input-overlay)))))) + +;;;_ + BREAKPOINTS + +(defface ess-bp-fringe-inactive-face + '((((class color) (background light) (min-colors 88)) (:foreground "DimGray")) + (((class color) (background dark) (min-colors 88)) (:foreground "LightGray")) + (((background light) (min-colors 8)) (:foreground "blue")) + (((background dark) (min-colors 8)) (:foreground "cyan"))) + "Face used to highlight inactive breakpoints." + :group 'ess-debug) + +(defface ess-bp-fringe-logger-face + '((((class color) (background light) (min-colors 88)) (:foreground "dark red")) + (((class color) (background dark) (min-colors 88)) (:foreground "tomato1")) + (((background light) (min-colors 8)) (:foreground "blue")) + (((background dark) (min-colors 8)) (:foreground "cyan"))) + "Face used to highlight loggers." + :group 'ess-debug) + +(defface ess-bp-fringe-browser-face + '((((class color) (background light) (min-colors 88)) (:foreground "medium blue")) + (((class color) (background dark) (min-colors 88)) (:foreground "deep sky blue")) + (((background light) (min-colors 8)) (:foreground "blue")) + (((background dark) (min-colors 8)) (:foreground "cyan"))) + "Face used to highlight `browser' breakpoints." + :group 'ess-debug) + +(defface ess-bp-fringe-recover-face + '((((class color) (background light) (min-colors 88)) (:foreground "dark magenta")) + (((class color) (background dark) (min-colors 88)) (:foreground "magenta")) + (((background light) (min-colors 8)) (:foreground "magenta")) + (((background dark) (min-colors 8)) (:foreground "magenta"))) + "Face used to highlight `recover' breakpoints fringe." + :group 'ess-debug) + +(defun ess--bp-pipe-block-p () + (save-excursion + (let ((inhibit-field-text-motion t)) + (forward-line -1) + (end-of-line) + (looking-back "%>%[ \t]*" (line-beginning-position))))) + +(defun ess--bp-pipe-native-block-p () + (save-excursion + (let ((inhibit-field-text-motion t)) + (forward-line -1) + (end-of-line) + (looking-back "|>[ \t]*" (line-beginning-position))))) + +(defvar ess--bp-identifier 1) +(defcustom ess-bp-type-spec-alist + '((pipe ".ess_pipe_browser() %%>%%" "B %>%\n" filled-square ess-bp-fringe-browser-face ess--bp-pipe-block-p) + (pipe-native ".ess_pipe_browser() |>" "B |>\n" filled-square ess-bp-fringe-browser-face ess--bp-pipe-native-block-p) + (browser "browser(expr=is.null(.ESSBP.[[%s]]));" "B>\n" filled-square ess-bp-fringe-browser-face) + (recover "recover()" "R>\n" filled-square ess-bp-fringe-recover-face)) + "List of lists of breakpoint types. +Each sublist has five elements: +1- symbol giving the name of specification +2- R expression to be inserted (%s is substituted with unique identifier). +3- string to be displayed instead of the expression +4- fringe bitmap to use +5- face for fringe and displayed string +6- optional, a function which should return nil if this BP + doesn't apply to current context." + :group 'ess-debug + :type '(alist :key-type symbol + :value-type (group string string symbol face))) + +(defcustom ess-bp-inactive-spec + '(inactive "##" filled-square ess-bp-fringe-inactive-face) + "List giving the inactive breakpoint specifications." + ;; List format is identical to that of the elements of + ;; `ess-bp-type-spec-alist' except that the second element giving + ;; the R expression is meaningless here." ;;fixme: second element is missing make it nil for consistency with all other specs + :group 'ess-debug + :type 'list) + +(defcustom ess-bp-conditional-spec + '(conditional "browser(expr={%s})" "CB[ %s ]>\n" question-mark ess-bp-fringe-browser-face) + "List giving the conditional breakpoint specifications. +List format is identical to that of the elements of +`ess-bp-type-spec-alist'. User is asked for the conditional +expression to be replaced instead of %s in the second and third +elements of the specifications." + :group 'ess-debug + :type 'list) + +(defcustom ess-bp-logger-spec + '(logger ".ess_log_eval('%s')" "L[ \"%s\" ]>\n" hollow-square ess-bp-fringe-logger-face) + "List giving the loggers specifications. +List format is identical to that of `ess-bp-type-spec-alist'." + :group 'ess-debug + :type 'list) + + +(defun ess-bp-get-bp-specs (type &optional condition no-error) + "Get specs for TYPE." + (let ((spec-alist (cond + ((eq type 'conditional) + (let ((tl (copy-sequence ess-bp-conditional-spec))) + (when (eq (length condition) 0) + (setq condition "TRUE")) + (setcar (cdr tl) (format (cadr tl) condition)) + (setcar (cddr tl) (format (caddr tl) condition)) + (list tl))) + ((eq type 'logger) + (let ((tl (copy-sequence ess-bp-logger-spec))) + (when (eq (length condition) 0) + (setq condition "watchLog")) + (setcar (cdr tl) (format (cadr tl) condition)) + (setcar (cddr tl) (format (caddr tl) condition)) + (list tl))) + (t (copy-sequence ess-bp-type-spec-alist))))) + (or (assoc type spec-alist) + (if no-error + nil + (error "Undefined breakpoint type %s" type))))) + +(defun ess-bp-create (type &optional condition no-error) + "Set breakpoint for the current line. +Returns the beginning position of the hidden text." + (let* ((bp-specs (ess-bp-get-bp-specs type condition no-error)) + (init-pos (point-marker)) + (fringe-bitmap (nth 3 bp-specs)) + (fringe-face (nth 4 bp-specs)) + (displ-string (nth 2 bp-specs)) + (bp-id (format "\"@%s@\"" + (setq ess--bp-identifier (1+ ess--bp-identifier)))) + (bp-command (concat (format (nth 1 bp-specs) bp-id) + "##:ess-bp-end:##\n")) + (dummy-string (format "##:ess-bp-start::%s@%s:##\n" (car bp-specs) condition)) + insertion-pos) + (when bp-specs + (set-marker init-pos (1+ init-pos)) + (setq displ-string (propertize displ-string + 'face fringe-face + 'font-lock-face fringe-face)) + (setq bp-command (propertize bp-command + 'ess-bp t + 'bp-id bp-id + 'bp-active t + 'cursor-intangible 'ess-bp + 'rear-nonsticky '(cursor-intangible ess-bp bp-type) + 'bp-type type + 'bp-substring 'command + 'display displ-string)) + (setq dummy-string (propertize + (ess-tracebug--propertize dummy-string fringe-bitmap fringe-face "*") + 'ess-bp t + 'cursor-intangible 'ess-bp + 'bp-type type + 'bp-substring 'dummy)) + (ess-tracebug--set-left-margin) + (back-to-indentation) + (setq insertion-pos (point) ) + (insert (concat dummy-string bp-command)) + (indent-for-tab-command) + (goto-char (1- init-pos)) ;; sort of save-excursion + insertion-pos))) + +(defun ess-bp-recreate-all () + "Internal function to recreate all bp." + (save-excursion + (save-restriction + (with-silent-modifications + (cursor-intangible-mode) + (widen) + (goto-char (point-min)) + (while (re-search-forward + "\\(##:ess-bp-start::\\(.*\\):##\n\\)\\(.+##:ess-bp-end:##\n\\)" nil t) + (let ((dum-beg (match-beginning 1)) + (dum-end (match-end 1)) + (comm-beg (match-beginning 3)) + (comm-end (match-end 3)) + (type (match-string 2)) + (bp-command (match-string 3)) + bp-id dum-props condition) + (when (string-match "^\\(\\w+\\)@\\(.*\\)\\'" type) + (setq condition (match-string 2 type)) + (setq type (match-string 1 type))) + (setq bp-id + (if (string-match "\"@[0-9]+@\"" bp-command) + (match-string 0 bp-command) + (setq ess--bp-identifier (1+ ess--bp-identifier)))) + (setq type (intern type)) + (let* ((bp-specs (ess-bp-get-bp-specs type condition t)) + (displ-string (nth 2 bp-specs)) + (fringe-face (nth 4 bp-specs)) + (fringe-bitmap (nth 3 bp-specs))) + (when bp-specs + (setq displ-string (propertize displ-string + 'face fringe-face + 'font-lock-face fringe-face)) + (add-text-properties comm-beg comm-end + (list 'ess-bp t + 'bp-id bp-id + 'cursor-intangible 'ess-bp + 'rear-nonsticky '(cursor-intangible ess-bp bp-type) + 'bp-type type + 'bp-substring 'command + 'display displ-string)) + (setq dum-props + (if window-system + (list 'display (list 'left-fringe fringe-bitmap fringe-face)) + (list 'display (list '(margin left-margin) + (propertize "dummy" + 'font-lock-face fringe-face + 'face fringe-face))))) + (add-text-properties dum-beg dum-end + (append dum-props + (list 'ess-bp t + 'cursor-intangible 'ess-bp + 'bp-type type + 'bp-substring 'dummy))) + ;; (when comment-beg + ;; (add-text-properties comment-beg comment-end + ;; (list 'ess-bp t + ;; 'bp-id bp-id + ;; 'cursor-intangible 'ess-bp + ;; 'display (propertize (nth 1 ess-bp-inactive-spec) 'face fringe-face) + ;; 'bp-type type + ;; 'bp-substring 'comment))) + )))))))) + +(add-hook 'ess-r-mode-hook #'ess-bp-recreate-all) + + +(defun ess-bp-get-bp-position-nearby () + "Get nearby break points. +Return the cons (beg . end) of breakpoint limit points closest to +the current position. Only currently visible region of the buffer +is searched. This command is intended for use in interactive +commands like `ess-bp-toggle-state' and `ess-bp-kill'. Use +`ess-bp-previous-position' in programs." + (interactive) + (let* ((pos-end (if (get-char-property (1- (point)) 'ess-bp) + (point) + (previous-single-property-change (point) 'ess-bp nil (window-start)))) + (pos-start (if (get-char-property (point) 'ess-bp) ;;check for bobp + (point) + (next-single-property-change (point) 'ess-bp nil (window-end)))) + dist-up dist-down) + (unless (eq pos-end (window-start)) + (setq dist-up (- (line-number-at-pos (point)) + (line-number-at-pos pos-end)))) + (unless (eq pos-start (window-end)) + (setq dist-down (- (line-number-at-pos pos-start) + (line-number-at-pos (point))))) + (if (and dist-up dist-down) + (if (< dist-up dist-down) + (cons (previous-single-property-change pos-end 'ess-bp nil (window-start)) pos-end) + (cons pos-start (next-single-property-change pos-start 'ess-bp nil (window-end)))) + (if dist-up + (cons (previous-single-property-change pos-end 'ess-bp nil (window-start)) pos-end) + (if dist-down + (cons pos-start (next-single-property-change pos-start 'ess-bp nil (window-end)))))))) + + +(defun ess-bp-previous-position () + "Get previous breakpoints. +Return the cons (beg . end) of breakpoint limit points closest +to the current position, nil if not found." + (let* ( (pos-end (if (get-char-property (1- (point)) 'ess-bp) + (point) + (previous-single-property-change (point) 'ess-bp )))) + (if pos-end + (cons (previous-single-property-change pos-end 'ess-bp) pos-end)))) + +(defun ess-bp-set () + "Set a breakpoint." + (interactive) + (let* ((pos (ess-bp-get-bp-position-nearby)) + (same-line (and pos + (<= (line-beginning-position) (cdr pos)) + (>= (line-end-position) (car pos)))) + (types ess-bp-type-spec-alist) + (ev last-command-event) + (com-char (event-basic-type ev)) + bp-type) + (when same-line + ;; set bp-type to next type in types + (setq bp-type (get-text-property (car pos) 'bp-type)) + (setq types (cdr (member (assq bp-type types) types))) ; nil if bp-type is last in the list + (when (null types) + (setq types ess-bp-type-spec-alist)) + (ess-bp-kill) + (indent-for-tab-command)) + ;; skip contextual bps + (while (and (nth 5 (car types)) + (not (funcall (nth 5 (car types))))) + (pop types)) + (setq bp-type (pop types)) + (ess-bp-create (car bp-type)) + (while (eq (event-basic-type (setq ev (read-event (format "'%c' to cycle" com-char)))) + com-char) + (if (null types) (setq types ess-bp-type-spec-alist)) + (ess-bp-kill) + ;; skip contextual bps + (while (and (nth 5 (car types)) + (not (funcall (nth 5 (car types))))) + (pop types)) + (setq bp-type (pop types)) + (ess-bp-create (car bp-type)) + (indent-for-tab-command)) + (push ev unread-command-events))) + + +(defun ess-bp-set-conditional (condition) + (interactive "sBreakpoint condition: ") + (ess-bp-create 'conditional condition) + (indent-for-tab-command)) + +(defun ess-bp-set-logger (name) + (interactive "sLogger name : ") + (ess-bp-create 'logger name) + (indent-for-tab-command)) + +(defun ess-bp-kill (&optional interactive?) + "Remove the breakpoint nearby." + (interactive "p") + (let ((pos (ess-bp-get-bp-position-nearby)) + (init-pos (make-marker))) + (if (null pos) + (if interactive? (message "No breakpoints nearby")) + (if (eq (point) (line-end-position)) + (goto-char (1- (point)))) ;; work-around for issue 3 + (set-marker init-pos (point)) + (goto-char (car pos)) + (delete-region (car pos) (cdr pos)) + (indent-for-tab-command) + (goto-char init-pos) + (if (eq (point) (line-end-position)) (forward-char))))) + +(defun ess-bp-kill-all nil + "Delete all breakpoints in current buffer." + (interactive) + (let ((count 0) + (init-pos (make-marker)) + pos) + (set-marker init-pos (1+ (point))) + (save-excursion ;; needed if error + (goto-char (point-max)) + (while (setq pos (ess-bp-previous-position)) + (goto-char (car pos)) + (delete-region (car pos) (cdr pos)) + (indent-for-tab-command) + (setq count (1+ count))) + (if (eq count 1) + (message "Killed 1 breakpoint") + (message "Killed %d breakpoint(s)" count))) + (goto-char (1- init-pos)))) + + +(defun ess-bp-toggle-state () + "Toggle the breakpoint between active and inactive states. + +For standard breakpoints, the effect of this command is +immediate, that is you don't need to source your code and it +works even in the process of debugging. + +For loggers, recover and conditional breakpoints this command +just comments the breakpoint in the source file. + +If there is no active R session, this command triggers an error." + (interactive) + (unless (and ess-local-process-name + (get-process ess-local-process-name)) + (error "No R session in this buffer")) + (save-excursion + (let ((pos (ess-bp-get-bp-position-nearby)) + (fringe-face (nth 3 ess-bp-inactive-spec)) + (cursor-sensor-inhibit 'ess-bp-toggle-state) + bp-id bp-specs beg-pos-command) + (if (null pos) + (message "No breakpoints in the visible region") + (goto-char (car pos)) + (setq beg-pos-command (previous-single-property-change + (cdr pos) 'bp-substring nil (car pos)) + bp-id (get-char-property beg-pos-command 'bp-id)) + (goto-char beg-pos-command) + (if (get-char-property beg-pos-command 'bp-active) + (progn + (put-text-property (car pos) beg-pos-command ;; dummy display change + 'display (list 'left-fringe (nth 2 ess-bp-inactive-spec) fringe-face)) + (put-text-property beg-pos-command (cdr pos) + 'bp-active nil) + (ess-command (format ".ESSBP.[[%s]] <- TRUE\n" bp-id))) + (setq bp-specs (assoc (get-text-property (point) 'bp-type) ess-bp-type-spec-alist)) + (put-text-property beg-pos-command (cdr pos) + 'bp-active t) + (put-text-property (car pos) beg-pos-command + 'display (list 'left-fringe (nth 3 bp-specs) (nth 4 bp-specs))) + (ess-command (format ".ESSBP.[[%s]] <- NULL\n" bp-id)) + ;; (insert (propertize "##" + ;; 'ess-bp t + ;; 'cursor-intangible 'ess-bp + ;; 'display (propertize (nth 1 ess-bp-inactive-spec) 'face fringe-face) + ;; 'bp-type (get-char-property (point) 'bp-type) + ;; 'bp-substring 'comment)) + ))))) + + +(defun ess-bp-make-visible () + "Make bp text visible." + (interactive) + (let ((pos (ess-bp-get-bp-position-nearby))) + (set-text-properties (car pos) (cdr pos) (list 'display nil)))) + + + +(defun ess-bp-next nil + "Goto next breakpoint." + (interactive) + (when-let ((bp-pos (next-single-property-change (point) 'ess-bp))) + (save-excursion + (goto-char bp-pos) + (when (get-text-property (1- (point)) 'ess-bp) + (setq bp-pos (next-single-property-change bp-pos 'ess-bp)))) + (if bp-pos + (goto-char bp-pos) + (message "No breakpoints found")))) + + +(defun ess-bp-previous nil + "Goto previous breakpoint." + (interactive) + (if-let ((bp-pos (previous-single-property-change (point) 'ess-bp))) + (goto-char (or (previous-single-property-change bp-pos 'ess-bp) + bp-pos)) + (message "No breakpoints before the point found"))) + +;;;_ + WATCH + +(defvar ess-watch-command + ;; assumes that every expression is a structure of length 1 as returned by parse. + ".ess_watch_eval()\n") + +(if (fboundp 'define-fringe-bitmap) ;;not clear to me why is this not bound in SSH session? - :TODO check + (define-fringe-bitmap 'current-watch-bar + [#b00001100] nil nil '(top t))) + +(defun ess-tracebug--set-left-margin () + "Set the margin on non-X displays." + (unless window-system + (when (= left-margin-width 0) + (setq left-margin-width 1) + (set-window-buffer (selected-window) (current-buffer))))) + +(define-derived-mode ess-watch-mode special-mode "ESS watch" + "Major mode in `ess-watch' window." + :group 'ess-tracebug + (let ((cur-block (max 1 (ess-watch-block-at-point))) + (dummy-string + (ess-tracebug--propertize "|" 'current-watch-bar 'font-lock-keyword-face))) + (ess-tracebug--set-left-margin) + (setq-local revert-buffer-function #'ess-watch-revert-buffer) + (turn-on-font-lock) + (setq ess-watch-current-block-overlay + (make-overlay (point-min) (point-max))) + (overlay-put ess-watch-current-block-overlay 'line-prefix dummy-string) + (overlay-put ess-watch-current-block-overlay 'face 'ess-watch-current-block-face) + (ess-watch-set-current cur-block) ;; + (require 'face-remap) + ;; scale the font + (setq text-scale-mode-amount ess-watch-scale-amount) + (text-scale-mode))) + +(defun ess-watch () + "Run `ess-watch-mode' on R objects. +This is the trigger function. See documentation of +`ess-watch-mode' for more information." + (interactive) + (ess-force-buffer-current) + (let ((wbuf (get-buffer-create ess-watch-buffer)) + (pname ess-local-process-name)) + (pop-to-buffer wbuf + ;; not strongly dedicated + '(nil . ((dedicated . 1)))) + (setq ess-local-process-name pname) + (ess-watch-mode) + ;; evals the ess-command and displays the buffer if not visible + (ess-watch-refresh-buffer-visibly wbuf))) + + +(defun ess-watch-refresh-buffer-visibly (wbuf &optional sleep no-prompt-check) + "Eval `ess-watch-command' and direct the output into the WBUF. +Call `ess-watch-buffer-show' to make the buffer visible, without +selecting it. SLEEP and NO-PROMPT-CHECK get passed to `ess-command'. + +This function is used for refreshing the watch window after each step during +the debugging." + ;; assumes that the ess-watch-mode is on!! + ;; particularly ess-watch-current-block-overlay is installed + (ess-watch-buffer-show wbuf) ;; if visible do nothing + (let ((pname ess-local-process-name)) ;; watch might be used from different dialects, need to reset + (with-current-buffer wbuf + (let ((curr-block (max 1 (ess-watch-block-at-point))) ;;can be 0 if + (inhibit-read-only t)) + (when pname + (setq ess-local-process-name pname)) + (ess-command ess-watch-command wbuf sleep no-prompt-check) + ;; delete the ++++++> line ;; not very reliable but works fine so far. + (goto-char (point-min)) + (delete-region (line-beginning-position) (+ 1 (line-end-position))) + (ess-watch-set-current curr-block) + (set-window-point (get-buffer-window wbuf) (point)))))) + +(defun ess-watch-buffer-show (buffer-or-name) + "Make watch buffer BUFFER-OR-NAME visible, and position accordingly. +If already visible, do nothing. + +Currently the only positioning rule implemented is to split the R +process window in half. The behavior is controlled by +`split-window-sensibly' with parameters `split-height-threshold' +and `split-width-threshold' replaced by +`ess-watch-height-threshold' and `ess-watch-width-threshold' +respectively." + (interactive) + (unless (get-buffer-window ess-watch-buffer 'visible) + (save-selected-window + (ess-switch-to-ESS t) + (let* ((split-width-threshold (or ess-watch-width-threshold + split-width-threshold)) + (split-height-threshold (or ess-watch-height-threshold + split-height-threshold)) + (win (split-window-sensibly (selected-window)))) + (if win + (set-window-buffer win buffer-or-name) + (display-buffer buffer-or-name) ;; resort to usual mechanism if could not split + ))))) + + +(defun ess-watch-revert-buffer (_ignore _noconfirm) + "Update the watch buffer. +Arguments IGNORE and NOCONFIRM currently not used." + (ess-watch) + (message "Watch reverted")) + + +(defface ess-watch-current-block-face + '((default (:inherit highlight))) + "Face used to highlight current watch block." + :group 'ess-debug) + +(defvar ess-watch-start-block "@----" ;; fixme: make defcustom and modify the injected command correspondingly + "String indicating the beginning of a block in watch buffer." + ;; :group 'ess-debug + ;; :type 'string + ) + +(defvar ess-watch-start-expression "@---:" + "String indicating the beginning of an R expression in watch buffer." + ;; :group 'ess-debug + ;; :type 'string + ) + +(defun ess-watch-block-limits-at-point () + "Return start and end positions of the watch block." + (interactive) + (save-excursion + (let ((curr (point)) + start-pos end-pos) + (end-of-line) + (setq start-pos + (if (re-search-backward ess-watch-start-block nil t ) + (point) + (point-min))) + (goto-char curr) + (beginning-of-line) + (setq end-pos + (if (re-search-forward ess-watch-start-block nil t) + (match-beginning 0) + (point-max))) + (list start-pos end-pos)))) + +(defun ess-watch-block-at-point () + "Return the current block's order count, 0 if no block was found." + (save-excursion + (let ((cur-point (point)) + (count 0)) + (goto-char (point-min)) + (while (re-search-forward ess-watch-start-block cur-point t) + (setq count (1+ count))) + count))) + +(defun ess-watch-set-current (nr) + "Move the overlay over the block with count NR in current watch buffer." + (goto-char (point-min)) + (re-search-forward ess-watch-start-expression nil t nr) + (goto-char (match-end 0)) + (apply #'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) + + +(defun ess-watch--make-alist () + "Create an alist of expressions from the current watch buffer. +Each element of assoc list is of the form (pos name expr) where +pos is an unique integer identifying watch blocks by position, +name is a string giving the name of expression block, expr is a +string giving the actual R expression." + (interactive) + (save-excursion + (let* ((reg-name (concat "^" ess-watch-start-block " *\\(\\S-*\\).*$")) + (reg-expr (concat "^" ess-watch-start-expression "\\s-*\\(.*\\)$")) + (reg-all (concat "\\(" reg-name "\\)\n\\(" reg-expr "\\)")) + (pos 0) wal name expr) + (goto-char (point-min)) + (while (re-search-forward reg-all nil t) + (setq pos (+ 1 pos)) + (setq name (match-string-no-properties 2)) + (setq expr (match-string-no-properties 4)) + (if (not (eq (string-to-number name) 0)) ;;if number of any kind set the name to "" + (setq name "")) + (setq wal + (append wal (list (list pos name expr))))) + wal))) + +(defun ess-watch--parse-assoc (al) + "Return a string command ready to be passed to R process. +The command is of the form `assign(\".ess_watch_expressions\", +list(a = parse(expr_a), b= parse(expr_b)), envir = .GlobalEnv)'. +AL is an association list as return by `ess-watch--make-alist'" + (concat ".ess_watch_assign_expressions(list(" + (mapconcat (lambda (el) + (if (> (length (cadr el) ) 0) + (concat "`" (cadr el) "` = parse(text = '" (caddr el) "')") + (concat "parse(text = '" (caddr el) "')"))) + al ", ") + "))\n")) + +(defun ess-watch--install-.ess_watch_expressions () + ;; used whenever watches are added/deleted/modified from the watch + ;; buffer. this is the only way to insert expressions into + ;; .ess_watch_expressions object in R. Assumes R watch being the current + ;; buffer, otherwise will most likely install empty list. + (interactive) + (process-send-string (ess-get-process ess-current-process-name) + (ess-watch--parse-assoc (ess-watch--make-alist))) + ;;TODO: delete the prompt at the end of proc buffer TODO: defun ess-send-string!! + (sleep-for 0.05) ;; need here, if ess-command is used immediately after, for some weird reason the process buffer will not be changed + ) + + +(defun ess-watch-quit () + "Quit (kill) the watch buffer. +If watch buffer exists, it is displayed during the debug +process. The only way to avoid the display, is to kill the +buffer." + (interactive) + (kill-buffer) ;; dedicated, window is deleted unless not the only one + ) + +;;;_ + MOTION +(defun ess-watch-next-block (&optional n) + "Move the overlay over the next block. +Optional N if supplied gives the number of steps forward `backward-char'." + (interactive "P") + (setq n (prefix-numeric-value n)) + (goto-char (overlay-end ess-watch-current-block-overlay)) + (unless (re-search-forward ess-watch-start-expression nil t n) + (goto-char (point-min)) ;;circular but always moves to start! + (re-search-forward ess-watch-start-expression nil t 1)) + (apply #'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) + +(defun ess-watch-previous-block (&optional n) + "Move the overlay over the previous block. +Optional N if supplied gives the number of backward steps." + (interactive "P") + (setq n (prefix-numeric-value n)) + (goto-char (overlay-start ess-watch-current-block-overlay)) + (unless (re-search-backward ess-watch-start-expression nil t n) + (goto-char (point-max)) ;;circular but always moves to last! + (re-search-backward ess-watch-start-expression nil t 1)) + (goto-char (match-end 0)) + (apply #'move-overlay ess-watch-current-block-overlay (ess-watch-block-limits-at-point))) + +;;;_ + BLOCK MANIPULATION and EDITING +(defun ess-watch-rename () + "Rename the currently selected watch block." + (interactive) + (end-of-line) + (unless (re-search-backward ess-watch-start-block nil t) + (error "Can not find a watch block")) + (let ((reg-name (concat ess-watch-start-block " *\\(\\S-*\\).*$")) + name start end) + ;; (reg-expr (concat "^" ess-watch-start-expression "\\s-*\\(.*\\)$")) + ;; (reg-all (concat "\\(" reg-name "\\)\n\\(" reg-expr "\\)")) + ;; (pos 0) wal name expr) + (unless (re-search-forward reg-name (line-end-position) t) + (error "Can not find the name substring in the current watch block ")) + (setq name (match-string-no-properties 1)) + (setq start (match-beginning 1)) + (setq end (match-end 1)) + (goto-char start) + ;; TODO: highlight the name in R-watch here + (setq name (read-string (concat "New name (" name "): ") nil nil name) ) + (setq buffer-read-only nil) + (delete-region start end) + (insert name) + (setq buffer-read-only t) + (ess-watch--install-.ess_watch_expressions) + (ess-watch-refresh-buffer-visibly (current-buffer)))) + +(defun ess-watch-edit-expression () + "Edit in the minibuffer the R expression from the current watch block." + (interactive) + (end-of-line) + (unless (re-search-backward ess-watch-start-block nil 1) + (error "Can not find a watch block")) + (let ((reg-expr (concat ess-watch-start-expression " *\\(.*\\)$")) + expr start end) + (unless (re-search-forward reg-expr nil t) + (error "Can not find an expression string in the watch block")) + (setq expr (match-string-no-properties 1)) + (setq start (match-beginning 1)) + (setq end (match-end 1)) + (goto-char start) + ;; TODO: highlight the name in R-watch here + (setq expr (read-string "New expression: " expr nil expr) ) + (setq buffer-read-only nil) + (delete-region start end) + (insert expr) + (setq buffer-read-only t) + (ess-watch--install-.ess_watch_expressions) + (ess-watch-refresh-buffer-visibly (current-buffer)))) + +(defun ess-watch-add () + "Ask for new R expression and append to the current list of watch expressions." + (interactive) + (let (nr expr name) + (goto-char (point-max)) + (setq nr (number-to-string (1+ (ess-watch-block-at-point)))) + (setq name nr) + ;; (setq name (read-string (concat "Name (" nr "):") nil nil nr )) ;;this one is quite annoying and not really needed than for logging + (setq expr (read-string "New expression: " nil nil "\"Empty watch!\"")) + (setq buffer-read-only nil) + (insert (concat "\n" ess-watch-start-block " " name " -@\n" ess-watch-start-expression " " expr "\n")) + (setq buffer-read-only t) + (ess-watch--install-.ess_watch_expressions))) + +(defun ess-watch-insert () + "Ask for new R expression and name and insert it in front of current watch block." + (interactive) + (let (nr expr name) + (setq nr (number-to-string (ess-watch-block-at-point))) + (setq name nr) + ;; (setq name (read-string (concat "Name (" nr "):") nil nil nr )) + (setq expr (read-string "New expression: " nil nil "\"Empty watch!\"")) + (re-search-backward ess-watch-start-block nil 1) ;;point-min if not found + (setq buffer-read-only nil) + (insert (concat "\n" ess-watch-start-block " " name " -@\n" ess-watch-start-expression " " expr "\n")) + (setq buffer-read-only t) + (ess-watch--install-.ess_watch_expressions))) + +(defun ess-watch-move-up () + "Move the current block up." + (interactive) + (let ((nr (ess-watch-block-at-point)) + wbl) + (when (> nr 1) + (setq buffer-read-only nil) + (setq wbl (apply #'delete-and-extract-region (ess-watch-block-limits-at-point))) + (re-search-backward ess-watch-start-block nil t 1) ;; current block was deleted, point is at the end of previous block + (insert wbl) + (ess-watch--install-.ess_watch_expressions) + (setq buffer-read-only t)))) + + +(defun ess-watch-move-down () + "Move the current block down." + (interactive) + (let ((nr (ess-watch-block-at-point)) + (nr-all (save-excursion (goto-char (point-max)) + (ess-watch-block-at-point))) + wbl) + (when (< nr nr-all) + (setq buffer-read-only nil) + (setq wbl (apply #'delete-and-extract-region (ess-watch-block-limits-at-point))) + (end-of-line) + (when (re-search-forward ess-watch-start-block nil t 1) ;; current block was deleted, point is at the end of previous block or point-max + (goto-char (match-beginning 0))) + (insert wbl) + (ess-watch--install-.ess_watch_expressions) + (setq buffer-read-only t)))) + +(defun ess-watch-kill () + "Kill the current block." + (interactive) + (setq buffer-read-only nil) + (apply #'delete-region (ess-watch-block-limits-at-point)) + (ess-watch--install-.ess_watch_expressions)) + +;;;_ + Debug/Undebug at point +(defun ess--dbg-get-signatures (method) + "Get signatures for the method METHOD." + (let ((tbuffer (get-buffer-create " *ess-command-output*")); initial space: disable-undo + signatures) + (save-excursion + (ess-if-verbose-write (format "ess-get-signatures*(%s).. " method)) + (ess-command (concat "showMethods(\"" method "\")\n") tbuffer) + (message "%s" ess-local-process-name) + (message "%s" ess-current-process-name) + (ess-if-verbose-write " [ok] ..\n") + (set-buffer tbuffer) + (goto-char (point-min)) + (if (not (re-search-forward "Function:" nil t)) + (progn (ess-if-verbose-write "not seeing \"Function:\".. \n") + (error (buffer-string)) + ;; (error "Cannot trace method '%s' (Is it a primitive method which you have already traced?)" method) + ) + ;; (setq curr-point (point)) + ;; (while (re-search-forward ", " nil t) ;replace all ", " with ":" for better readability in completion buffers?? + ;; (replace-match ":")) + ;; (goto-char curr-point) + (while (re-search-forward "^.+$" nil t) + (setq signatures (cons (match-string-no-properties 0) signatures)))) + ; (kill-buffer tbuffer) + ) + signatures)) + + +(defun ess-debug-flag-for-debugging () + "Set the debugging flag on a function. +Ask the user for a function and if it turns to be generic, ask +for signature and trace it with browser tracer." + (interactive) + (ess-force-buffer-current "Process to use: ") + (let* ((tbuffer (get-buffer-create " *ess-command-output*")) ;; output buffer name is hard-coded in ess-inf.el + (pkg (ess-r-package-name)) + (all-functions (ess-get-words-from-vector--foreground + (if pkg + (format ".ess_all_functions(c('%s'))\n" pkg) + ".ess_all_functions()\n"))) + (obj-at-point (ess-helpobjs-at-point--read-obj)) + (default (and + obj-at-point + (let* ((reg (regexp-quote obj-at-point)) + (matches (cl-loop for el in all-functions + if (string-match reg el) collect el))) + (car (sort matches (lambda (a b) (< (length a) (length b)))))))) + (ufunc (ess-completing-read "Debug" all-functions + nil nil nil nil (or default obj-at-point))) + signature) + ;; FIXME: Most of the following logic should be in R + (if (ess-boolean-command (format "as.character(isGeneric('%s'))\n" ufunc)) + + ;; it's S4 generic: + (save-excursion + ;; ask for exact signature + (setq signature + (ess-completing-read (concat "Method for generic '" ufunc "'") + (ess--dbg-get-signatures ufunc) ;signal an error if not found + nil t nil nil "*default*")) + (if (equal signature "*default*") + ;;debug, the default ufunc + (ess-command (format "trace('%s', tracer = browser)\n" ufunc) tbuffer) + (ess-command (format "trace('%s', tracer = browser, signature = c('%s'))\n" ufunc signature) tbuffer)) + (with-current-buffer tbuffer + ;; give appropriate message or error + (message "%s" (buffer-substring-no-properties (point-min) (point-max))))) + + ;;else, not an S4 generic + (when (ess-boolean-command (format "as.character(.knownS3Generics['%s'])\n" ufunc)) + ;; it's S3 generic: + (setq all-functions + (ess-get-words-from-vector + (format "local({gens<-methods('%s');as.character(gens[attr(gens, 'info')$visible])})\n" ufunc))) + (setq all-functions + ;; cannot debug non-visible methods + (delq nil (mapcar (lambda (el) + (if (not (char-equal ?* (aref el (1- (length el))))) el)) + all-functions))) + (setq ufunc (ess-completing-read (format "Method for S3 generic '%s'" ufunc) + (cons ufunc all-functions) nil t))) + (ess-command (format ".ess_dbg_flag_for_debuging('%s')\n" ufunc))))) + + +(defun ess-debug-unflag-for-debugging () + "Prompt for the debugged/traced function or method and undebug/untrace it." + (interactive) + (let ((tbuffer (get-buffer-create " *ess-command-output*")); initial space: disable-undo\ + (debugged (ess-get-words-from-vector + (if nil ;; FIXME: was checking `ess-developer-packages` + (format ".ess_dbg_getTracedAndDebugged(c('%s'))\n" + (mapconcat 'identity ess-developer-packages "', '")) + ".ess_dbg_getTracedAndDebugged()\n"))) + out-message fun def-val) + ;; (prin1 debugged) + (if (eq (length debugged) 0) + (setq out-message "No debugged or traced functions/methods found") + (setq def-val (if (eq (length debugged) 1) + (car debugged) + "*ALL*")) + (setq fun (ess-completing-read "Undebug" debugged nil t nil nil def-val)) + (if (equal fun "*ALL*" ) + (ess-command (concat ".ess_dbg_UndebugALL(c(\"" (mapconcat 'identity debugged "\", \"") "\"))\n") tbuffer) + (ess-command (format ".ess_dbg_UntraceOrUndebug(\"%s\")\n" fun) tbuffer)) + (with-current-buffer tbuffer + (if (= (point-max) 1) ;; not reliable TODO: + (setq out-message (format "Undebugged '%s' " fun)) + (setq out-message (buffer-substring-no-properties (point-min) (point-max))) ;; untrace info or warning, or error occurred + ))) + (message "%s" out-message))) + +;;;_ * Kludges and Fixes +;;; delete-char and delete-backward-car do not delete whole intangible text +(defun ess--tracebug-delete-char (n &rest _) + "When deleting an intangible char, delete the whole intangible region. +Only do this when N is 1" + (when (and (ess-derived-mode-p) + (= n 1) + (get-text-property (point) 'cursor-intangible)) + (kill-region (point) (or (next-single-property-change (point) 'cursor-intangible) + (point-max))) + (indent-according-to-mode))) + +(advice-add 'delete-char :before-until #'ess--tracebug-delete-char) + +(defun ess--tracebug-delete-backward-char (n &rest _) + "When deleting an intangible char, delete the whole intangible region. +Only do this when called interactively and N is 1" + (when (and (ess-derived-mode-p) + (= n 1) + (> (point) (point-min)) + (get-text-property (1- (point)) 'cursor-intangible)) + (kill-region (or (previous-single-property-change (point) 'cursor-intangible) + (point-min)) + (point)))) + +(advice-add 'delete-backward-char :before-until #'ess--tracebug-delete-backward-char) + +(provide 'ess-tracebug) + +;;; ess-tracebug.el ends here diff --git a/elpa/ess-20230419.1527/ess-trns.el b/elpa/ess-20230419.1527/ess-trns.el new file mode 100644 index 00000000..42a62e97 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-trns.el @@ -0,0 +1,232 @@ +;;; ess-trns.el --- Support for manipulating S transcript files -*- lexical-binding: t; -*- + +;; Copyright (C) 1989-2020 Free Software Foundation, Inc. +;; Author: David Smith +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Code for dealing with ESS transcripts. + +;;; Code: + + ; Requires and autoloads + +(require 'ess-mode) +(require 'ess-inf) +(require 'comint) + +(declare-function ess-display-help-on-object "ess-help" (object &optional command)) + + ; ess-transcript-mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; In this section: +;;;; +;;;; * The major mode ess-transcript-mode +;;;; * Commands for ess-transcript-mode +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defcustom ess-transcript-mode-hook nil + "Hook for customizing ESS transcript mode." + :group 'ess-hooks + :type 'hook) + +;;*;; Major mode definition +(defvar ess-transcript-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-c\C-s" #'ess-switch-process) + (define-key map "\C-c\C-r" #'ess-eval-region) + (define-key map "\C-c\M-r" #'ess-eval-region-and-go) + (define-key map "\C-c\C-k" #'ess-force-buffer-current) + (define-key map "\C-c\C-q" #'ess-quit) + (define-key map "\C-c\C-j" #'ess-transcript-send-command) + (define-key map "\C-c\M-j" #'ess-transcript-send-command-and-move) + (define-key map "\M-\C-a" #'ess-goto-end-of-function-or-para) + (define-key map "\M-\C-e" #'ess-goto-end-of-function-or-para) + (define-key map "\C-c\C-y" #'ess-switch-to-ESS) + (define-key map "\C-c\C-z" #'ess-switch-to-end-of-ESS) + (define-key map "\C-c\C-v" #'ess-display-help-on-object) + (define-key map "\C-c\C-d" #'ess-dump-object-into-edit-buffer) + (define-key map "\C-a" #'comint-bol) + (define-key map "\M-\t" #'comint-replace-by-expanded-filename) + (define-key map "\M-?" #'comint-dynamic-list-completions) + (define-key map "\C-c\C-k" #'ess-request-a-process) + (define-key map "{" #'skeleton-pair-insert-maybe) + (define-key map "}" #'skeleton-pair-insert-maybe) + (define-key map "\e\C-h" #'ess-mark-function-or-para) + (define-key map "\e\C-q" #'ess-indent-exp) + (define-key map "\t" #'ess-indent-command) + (define-key map "\C-c\C-p" #'comint-previous-prompt) + (define-key map "\C-c\C-n" #'comint-next-prompt) + (define-key map "\r" #'ess-transcript-send-command-and-move) + (define-key map "\M-\r" #'ess-transcript-send-command) + (define-key map "\C-c\r" #'ess-transcript-copy-command) + (define-key map "\C-c\C-w" #'ess-transcript-DO-clean-region) + (define-key map "\C-c\M-c" #'ess-transcript-clean-buffer) + map) + "Keymap for `ess-transcript-mode'.") + +(easy-menu-define + ess-transcript-mode-menu ess-transcript-mode-map + "Menu for use in S transcript mode." + '("ESS-trans" + ["Describe" describe-mode t] + ["About" (ess-goto-info "Transcript Mode") t] + ["Send bug report" ess-submit-bug-report t] + "------" + ["Mark cmd group" mark-paragraph t] + ["Previous prompt" comint-previous-prompt t] + ["Next prompt" comint-next-prompt t] + "------" + ["Send and move" ess-transcript-send-command-and-move t] + ["Copy command" ess-transcript-copy-command t] + ["Send command" ess-transcript-send-command t] + ["Clean Region" ess-transcript-DO-clean-region t] + ["Clean Whole Buffer" ess-transcript-clean-buffer t] + ["Switch S process" ess-switch-process t] + )) + +;;;###autoload +(define-derived-mode ess-transcript-mode ess-mode "ESS Transcript" + "Major mode for transcript files. + +Type \\[ess-transcript-send-command] to send a command in the +transcript to the current inferior process. \\[ess-transcript-copy-command] +copies the command but does not execute it, allowing you to edit it in +the process buffer first. + +Type \\[ess-transcript-clean-region] to delete all outputs and prompts +in the region, leaving only the commands." + :group 'ess + (setq buffer-read-only t + ess-local-process-name nil + mode-line-process '(" [" ess-local-process-name "]")) + ;; TODO: Set this more normally in various major modes + (unless inferior-ess-prompt ;; For S languages it is set in custom-alist + (setq inferior-ess-prompt + ;; Do not anchor to bol with `^' + (concat "\\(" + inferior-ess-primary-prompt + "\\|" + inferior-ess-secondary-prompt + "\\)"))) + (setq-local paragraph-start (concat "^" inferior-ess-prompt "\\|^\^L")) + (setq-local paragraph-separate "^\^L") + (setq-local comint-use-prompt-regexp t) + (setq-local comint-prompt-regexp (concat "^" inferior-ess-prompt)) + (setq font-lock-defaults '(ess-build-font-lock-keywords + nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))) + +;;*;; Commands used in S transcript mode + +(defun ess-transcript-send-command () + "Send the command at point in the transcript to the ESS process. +The line should begin with a prompt. The ESS process buffer is displayed if it +is not already." + (interactive) + (let* ((proc (or ess-local-process-name + (ess-request-a-process "Evaluate into which process? " t))) + (ess-buf (ess-get-process-buffer proc))) + (setq ess-local-process-name proc) + (if (get-buffer-window ess-buf) nil + (display-buffer ess-buf t)) + (let ((input (inferior-ess-get-old-input))) + (with-current-buffer ess-buf + (goto-char (point-max)) + (ess-eval-linewise input))))) + +(defun ess-transcript-send-command-and-move () + "Send the command on this line, and move point to the next command." + (interactive) + (let* ((proc (or ess-local-process-name + (ess-request-a-process "Evaluate into which process? " t))) + (ess-buf (ess-get-process-buffer proc))) + (setq ess-local-process-name proc) + (if (get-buffer-window ess-buf) nil + (display-buffer ess-buf t)) + (let ((input (inferior-ess-get-old-input))) + (with-current-buffer ess-buf + (goto-char (point-max)) + (ess-eval-linewise input nil nil nil 1)))) + (comint-next-prompt 1)) + +(defun ess-transcript-copy-command () + "Copy the command at point to the command line of the ESS process." + (interactive) + (let* ((proc (or ess-local-process-name + (ess-request-a-process "Evaluate into which process? " t))) + (ess-buf (process-buffer (get-process proc))) + (input (inferior-ess-get-old-input))) + (setq ess-local-process-name proc) + (if (get-buffer-window ess-buf) nil + (display-buffer ess-buf t)) + (with-current-buffer ess-buf + (goto-char (point-max)) + (insert input))) + (ess-switch-to-end-of-ESS)) + +(defun ess-transcript-clean-region (beg end even-if-read-only) + "Strip the transcript in the region, leaving only (R/S/Lsp/..) commands. +Deletes any lines not beginning with a prompt, and then removes the +prompt from those lines that remain. Prefix argument means to +clean even if the buffer is \\[read-only]." + (interactive "r\nP") + (unless inferior-ess-prompt + (error "Cannot clean ESS transcript region in this mode! + That only works in ess-transcript-mode or inferior-ess-mode ('*R*' etc)." + ;; Maybe call ess-clean-region-in-new-transcript ?")) + )) + (let ((do-toggle (and buffer-read-only even-if-read-only)) + (ess-prompt-rx (if inferior-ess-secondary-prompt + (concat "^\\(\\(" + inferior-ess-prompt + "\\)\\|\\(" + inferior-ess-secondary-prompt + "\\)\\)") + (concat "^" inferior-ess-prompt)))) + (save-excursion + (if do-toggle (setq buffer-read-only nil)) + (save-restriction + (deactivate-mark) + (narrow-to-region beg end) + (goto-char (point-min)) + (delete-non-matching-lines ess-prompt-rx) + (goto-char (point-min)) + ;; (replace-regexp * * ) : + (while (re-search-forward ess-prompt-rx nil t) + (replace-match "" nil nil))) + + (if do-toggle (setq buffer-read-only t))))) + +(defun ess-transcript-DO-clean-region (beg end) + "Clean the current via \\[ess-transcript-clean-region] even if the buffer is read-only." + (interactive "r") + (ess-transcript-clean-region beg end 'In-ANY-case)) + +(defun ess-transcript-clean-buffer () + "Cleanup the whole buffer. +Use point-min/max to obey `narrow-to-region'." + (interactive) + (ess-transcript-clean-region (point-min) (point-max) 'In-ANY-case)) + +(provide 'ess-trns) + +;;; ess-trns.el ends here diff --git a/elpa/ess-20230419.1527/ess-utils.el b/elpa/ess-20230419.1527/ess-utils.el new file mode 100644 index 00000000..98084753 --- /dev/null +++ b/elpa/ess-20230419.1527/ess-utils.el @@ -0,0 +1,1138 @@ +;;; ess-utils.el --- General Emacs utility functions used by ESS -*- lexical-binding: t; -*- + +;; Copyright (C) 1998-2022 Free Software Foundation, Inc. +;; Author: Martin Maechler +;; Created: 9 Sept 1998 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; Various utilities for ESS. + +;;; Code: + +(require 'cl-lib) +(require 'comint) +(require 'project) +(eval-when-compile + (require 'tramp)) +;; The only ESS file this file should depend on is ess-custom.el +(require 'ess-custom) + +(defvar ac-modes) +(declare-function ess-eval-linewise "ess-inf" (text &optional invisibly eob even-empty wait-last-prompt sleep-sec wait-sec)) +(declare-function color-lighten-name "color" (name percent)) +(declare-function tramp-dissect-file-name "tramp" (name &optional nodefault)) +;; The following declares can be removed once we drop Emacs 25 +(declare-function tramp-file-name-method "tramp") +(declare-function tramp-file-name-user "tramp") +(declare-function tramp-file-name-host "tramp") +(declare-function tramp-file-name-localname "tramp") +(declare-function tramp-file-name-hop "tramp") + + +;;*;; elisp tools + +(defun ess-next-code-line (&optional arg skip-to-eob) + "Move ARG lines of code forward (backward if ARG is negative). +If `ess-eval-empty' is non-nil, skip past all empty and comment +lines. ARG is 1 by default. If ARG is 0 only comments are skipped +forward. Don't skip the last empty and comment lines in the +buffer unless SKIP-TO-EOB is non-nil. On success, return 0. +Otherwise go as far as possible and return -1." + (interactive "p") + (if (or ess-eval-empty + (and (fboundp 'ess-roxy-entry-p) + (ess-roxy-entry-p))) + (forward-line arg) + (setq arg (or arg 1)) + (beginning-of-line) + (let ((pos (point)) + (inc (if (>= arg 0) 1 -1)) + (cnt (if (= arg 0) 1 arg)) + (out 0)) + ;; when orig-arg == 0, we skip only comments + (while (and (/= cnt 0) (= out 0)) + (unless (= arg 0) + (setq out (forward-line inc))) ; out==0 means success + (comment-beginning) + (beginning-of-line) + (forward-comment (* inc (buffer-size))) ;; as suggested in info file + (if (or skip-to-eob + (not (looking-at ess-no-skip-regexp))) ;; don't go to eob or whatever + (setq cnt (- cnt inc)) + (goto-char pos) + (setq cnt 0) + (forward-line inc)) ;; stop at next empty line + (setq pos (point))) + (goto-char pos) + out))) + +(defun ess-goto-line (line) + "Go to LINE in the widened buffer." + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line (1- line)))) + +(defun ess-skip-thing (thing) + "Leave point at the end of THING. +THING can be \\='function, \\='paragraph, or \\='line." + (cond + ((eql thing 'line) (goto-char (line-end-position))) + ((eql thing 'paragraph) (forward-paragraph)) + ((eql thing 'function) (end-of-defun) (skip-chars-backward " \t\n")))) + +(defun ess-search-except (regexp &optional except backward) + "Search for a REGEXP and store as match 1. +Optionally ignore strings that match EXCEPT. If BACKWARD is +non-nil, search backward." + (let ((continue t) (exit nil)) + (while continue + (if (or (and backward (search-backward-regexp regexp nil t)) + (and (not backward) (search-forward-regexp regexp nil t))) + (progn + (setq exit (match-string 1)) + (setq continue (and except (string-match except exit))) + (if continue (setq exit nil))) + ;;else + (setq continue nil))) + exit)) + +(defun ess-save-and-set-local-variables () + "If buffer was modified, save file and set Local Variables if defined. +Return t if buffer was modified, nil otherwise." + (let ((ess-temp-return-value (buffer-modified-p))) + (save-buffer) + (hack-local-variables) + ess-temp-return-value)) + +(defun ess-get-file-or-buffer (file-or-buffer) + "Return FILE-OR-BUFFER if it is a buffer. +Otherwise return the buffer associated with the file which must +be qualified by it's path; if the buffer does not exist, return +nil." + (declare (side-effect-free t) + (obsolete nil "ESS 19.04")) + (if (bufferp file-or-buffer) + file-or-buffer + (find-buffer-visiting file-or-buffer))) + +(defun ess-file-content (file) + "Return the content of FILE as string." + (if (file-exists-p file) + (with-temp-buffer + (insert-file-contents-literally file) + (buffer-string)) + (error "File '%s' does not exist" file))) + +(defun ess-uniq (list predicate) + "Uniquify LIST, stably, deleting elements using PREDICATE. +Return the list with subsequent duplicate items removed by side effects. +PREDICATE is called with an element of LIST and a list of elements from LIST, +and should return the list of elements with occurrences of the element removed. +This function will work even if LIST is unsorted. See also `delete-dups'." + (declare (obsolete 'delete-dups "ESS 19.04")) + (let ((list list)) + (while list + (setq list (setcdr list (funcall predicate (car list) (cdr list)))))) + list) + +(define-obsolete-function-alias 'ess-uniq-list #'delete-dups "ESS 19.04") + +(defalias 'ess-flatten-list + ;; `flatten-tree' is a function in Emacs 27 + (if (fboundp 'flatten-tree) + 'flatten-tree + (lambda (list) + "Take the arguments and flatten them into one long LIST. +Drops `nil' entries." + ;; Taken from lpr.el + ;; `lpr-flatten-list' is defined here (copied from "message.el" and + ;; enhanced to handle dotted pairs as well) until we can get some + ;; sensible autoloads, or `flatten-list' gets put somewhere decent. + (ess-flatten-list-1 list)))) + +(defun ess-flatten-list-1 (list) + "Internal helper for `ess-flatten-list', which see for LIST." + (cond + ((null list) (list)) + ((consp list) + (append (ess-flatten-list-1 (car list)) + (ess-flatten-list-1 (cdr list)))) + (t (list list)))) + +(define-obsolete-function-alias 'ess-delete-blank-lines + #'delete-blank-lines "ESS 19.04") + +(define-obsolete-function-alias 'ess-line-to-list-of-words #'split-string "ESS 19.04") + +(defmacro ess--exit-protect (body &rest exit) + "Run EXIT when BODY exits early. +Unlike `unwind-protect', the unwind forms only run in case of +early exits. Unlike `condition-case', they run inconditionally, +no matter the reason for exiting early (e.g. error or quit)." + (declare + (indent 1) + (debug (form &rest form))) + `(let ((--early-exit t)) + (unwind-protect + (prog1 ,body (setq --early-exit nil)) + (when --early-exit + ,@exit)))) + + +;;*;; System + +(defun ess-revert-wisely () + "Revert from disk if file and buffer last modification times are different." + (interactive) + ;; whether or not a revert is needed, force load local variables + ;; for example, suppose that you change the local variables and then + ;; save the file, a revert is unneeded, but a force load is + (hack-local-variables) + (unless (verify-visited-file-modtime (current-buffer)) + (progn + (let ((ess-temp-store-point (point))) + (revert-buffer t t) + (goto-char ess-temp-store-point)) + t))) + +(define-obsolete-function-alias 'ess-find-exec #'ess-find-exec-completions "ESS 19.04") +(defun ess-find-exec-completions (root) + "Given the ROOT of an executable file name, find all possible completions. +Search for the executables in the variable `exec-path'." + (let (executables) + (dolist (dir exec-path) + (when (and (> (length dir) 0) + (file-accessible-directory-p dir)) + ;; the first test above excludes "" from exec-path, which can be + ;; problematic with Tramp. + (dolist (f (file-name-all-completions root dir)) + (setq f (expand-file-name f dir)) + (when (and (file-executable-p f) + (not (backup-file-name-p f)) + (not (file-directory-p f))) + (push f executables))))) + executables)) + +(defun ess-drop-non-directories (file-strings) + "Drop all entries in FILE-STRINGS that do not \"look like\" directories." + (ess-flatten-list (mapcar #'file-name-directory file-strings))) + +(defun ess--parent-dir (path n) + "Return Nth parent of PATH." + (let ((opath path)) + (while (and path (> n 0)) + (setq path (file-name-directory (directory-file-name opath))) + (if (equal path opath) + (setq path nil) + (setq opath path + n (1- n)))) + path)) + + +;;*;; Interaction with inferiors + +(defmacro ess-when-new-input (time-var &rest body) + "BODY is evaluate only if the value of process variable TIME-VAR +is bigger than the time of the last user input (stored in +`last-eval' process variable). TIME-VAR is the name of the +process variable which holds the access time. See the code for +`ess-synchronize-dirs' and `ess-cache-search-list'. + +Returns nil when no current process, or process is busy, or +time-var > last-eval. Otherwise, execute BODY and return the last +value. + +If BODY is executed, set process variable TIME-VAR +to (current-time). + +Variable *proc* is bound to the current process during the +evaluation of BODY. + +Should be used in `ess-idle-timer-functions' which call the +process to avoid excessive requests." + (declare (indent 1) (debug t)) + `(with-ess-process-buffer 'no-error + (let ((le (process-get *proc* 'last-eval)) + (tv (process-get *proc* ',time-var))) + (when (and (or (null tv) (null le) (time-less-p tv le)) + (not (process-get *proc* 'busy))) + (let ((out (progn ,@body))) + (process-put *proc* ',time-var (current-time)) + out))))) + +(defmacro with-ess-process-buffer (no-error &rest body) + "Execute BODY in the process buffer of `ess-current-process-name'. +If NO-ERROR is t don't trigger error when there is not current +process. Symbol *proc* is bound to the current process during the +evaluation of BODY." + (declare (indent 1) (debug t)) + `(let ((*proc* (and ess-local-process-name (get-process ess-local-process-name)))) + (if *proc* + (with-current-buffer (process-buffer *proc*) + ,@body) + (unless ,no-error + (error "No current ESS process"))))) + + +;;*;; Emacs Integration + +(defun ess-derived-mode-p () + "Non-nil if the current major mode is an ESS major mode." + (or (derived-mode-p 'ess-mode) + (derived-mode-p 'ess-julia-mode))) + +(defun ess--generate-eval-visibly-submenu (_menu) + '(["yes" (lambda () (interactive) (setq ess-eval-visibly t)) + :style radio :enable t :selected (eq ess-eval-visibly t)] + ["nowait" (lambda () (interactive) (setq ess-eval-visibly 'nowait)) + :style radio :enable t :selected (eq ess-eval-visibly 'nowait) ] + ["no" (lambda () (interactive) (setq ess-eval-visibly nil)) + :style radio :enable t :selected (eq ess-eval-visibly nil) ])) + +;; Font Lock + +(defun ess--fl-keywords-values () + "Return a cons (STANDARD-VALUE . CUSTOM-VALUE) of `ess-font-lock-keywords'." + (let ((sym ess-font-lock-keywords)) + (if (and (symbolp sym) + (custom-variable-p sym)) + (cons + (eval (car (get sym 'standard-value)) t) + (symbol-value sym)) + (error "`ess-font-lock-keywords' must be a symbol of a custom variable")))) + +(defun ess--extract-fl-keywords () + (let ((values (ess--fl-keywords-values))) + (mapcar (lambda (kv) + (let ((cust-kv (assoc (car kv) (cdr values)))) + (when cust-kv + (setcdr kv (cdr cust-kv)))) + kv) + (copy-alist (car values))))) + +(defun ess-build-font-lock-keywords () + "Retrieve `font-lock-keywords' from ess-[dialect]-font-lock-keywords. +Merge the customized values of that variable on top of the +standard values and return the new list. For this to work, +`ess-font-lock-keywords' should be a name of the +ess-[dialect]-font-lock-keywords variable." + (delq nil + (mapcar (lambda (c) + (when (cdr c) + (symbol-value (car c)))) + (ess--extract-fl-keywords)))) + +(defun ess-font-lock-toggle-keyword (keyword) + "Toggle KEYWORD font-lock." + (interactive + (list (intern (ess-completing-read + "Keyword to toggle" + (mapcar (lambda (el) (symbol-name (car el))) + (car (ess--fl-keywords-values))) + nil t)))) + (let* ((values (ess--fl-keywords-values)) + (kwd (cond + ;; already in custom values + ((assoc keyword (cdr values))) + ;; if keyword is not already in custom values (can happen if + ;; we add new keywords but the user has the old value saved in + ;; .emacs-custom.el) + ((let ((kwd (assoc keyword (car values))) + (sym ess-font-lock-keywords)) + (when kwd + (set sym (cons kwd (symbol-value sym))) + kwd))) + (t (error "Invalid keyword %s" keyword))))) + (setcdr kwd (not (cdr kwd))) + (let ((mode major-mode) + (dialect ess-dialect)) + ;; refresh font-lock defaults in all relevant buffers + (mapc (lambda (b) + (with-current-buffer b + (when (and (eq major-mode mode) + (eq ess-dialect dialect)) + (font-lock-refresh-defaults)))) + (buffer-list))))) + +(defun ess--generate-font-lock-submenu (_menu) + "Generate ESS font-lock submenu." + (append (mapcar (lambda (el) + `[,(symbol-name (car el)) + (lambda () (interactive) + (ess-font-lock-toggle-keyword ',(car el))) + :style toggle + :enable t + :selected ,(cdr el)]) + (ess--extract-fl-keywords)) + (list "-----" + ["Save to custom" + (lambda () (interactive) + (customize-save-variable ess-font-lock-keywords + (ess--extract-fl-keywords))) + t]))) + +(declare-function untrace-function "trace" ()) +(defvar ess--is-tracing nil) + +;;;###autoload +(define-minor-mode ess-elisp-trace-mode + "Toggle tracing of ess-prefixed functions. +Tracing is useful for debugging background ESS behaviour. When +enabled, all functions prefixed in `ess-' and `inferior-ess' are +instrumented with `trace-function'. Tracing is turned off by +calling `untrace-function' on these functions." + :global t + :group 'ess + (let ((fns (append (all-completions "ess-" obarray) + (all-completions "inferior-ess-" obarray) + (list "update-ess-process-name-list" + "forward-ess-r-expr" + "forward-ess-r-sexp" + "backward-ess-r-expr" + "backward-ess-r-sexp" + "company-ess-julia-objects" + "run-ess-r" + "run-ess-r-newest"))) + (do (symbol-function (if ess-elisp-trace-mode + #'untrace-function + #'trace-function)))) + (dolist (fn fns) + (when (symbol-function (intern fn)) + (funcall do (intern fn)))))) + + +;;*;; External modes + +;; Define these here for the byte compiler since ido dynamically +;; let-binds them: +(defvar ido-choice-list) +(defvar ido-context-switch-command) +(defvar ido-directory-too-big) +(defvar ido-directory-nonreadable) +(defvar ido-current-directory) +(defvar ido-enable-flex-matching) +(declare-function ido-choose-completion-string "ido") +(declare-function ido-minibuffer-setup "ido") +(declare-function ido-read-internal "ido" (item prompt hist &optional default require-match initial)) + +(defun ess-completing-read (prompt collection &optional predicate + require-match initial-input hist def) + "Read a string in the minibuffer, with completion. +Use `ido-completing-read' if IDO interface is present, or fall +back on classical `completing-read' otherwise. Meaning of PROMPT, +COLLECTION, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, HIST, and +DEF is as in `completing-read'. PROMPT is automatically suffixed +with ': ' and (default %s) when needed. If HIST is nil use +`ess--completing-hist' as history. See also `ess-use-ido'." + (let ((use-ido (and ess-use-ido (require 'ido nil t)))) + (setq hist (or hist 'ess--completing-hist)) + (when (and def (not use-ido)) ;; ido places in front and highlights the default + (setq prompt (format "%s(default %s)" prompt def))) + (setq prompt (concat prompt ": ")) + (if use-ido + (let ((reset-ido (and use-ido (not ido-mode))) ;people not using ido but having it) + (ido-current-directory nil) + (ido-directory-nonreadable nil) + (ido-directory-too-big nil) + (ido-context-switch-command 'ignore) + (ido-enable-flex-matching ess-ido-flex-matching) ;it's fast and useful, may be get into options + (ido-choice-list (copy-sequence collection)) ;ido removes the match (reported) + sel) + (unwind-protect + (progn + (add-hook 'minibuffer-setup-hook #'ido-minibuffer-setup) + (add-hook 'choose-completion-string-functions #'ido-choose-completion-string) + (setq sel (ido-read-internal 'list prompt hist def require-match initial-input)) + (when hist ;; ido does not push into hist the whole match if C-SPC or RET is used (reported) + (unless (string= sel (car (symbol-value hist))) + (set hist (cons sel (symbol-value hist)))))) + (when reset-ido + (remove-hook 'minibuffer-setup-hook #'ido-minibuffer-setup) + (remove-hook 'choose-completion-string-functions #'ido-choose-completion-string))) + sel) + ;; else usual completion + (completing-read prompt collection predicate require-match initial-input hist def)))) + +(defun ess--setup-auto-complete (sources &optional inferior) + "Setup auto-complete depending on user settings. +SOURCES gets added to `ac-sources', INFERIOR should be t for +inferior buffers." + ;; auto-complete + (when (and (boundp 'ac-sources) + (if inferior + (eq ess-use-auto-complete t) + ess-use-auto-complete)) + (add-to-list 'ac-modes major-mode) + ;; files should be in front; ugly, but needed + (setq ac-sources + (delq 'ac-source-filename ac-sources)) + (mapc (lambda (el) (add-to-list 'ac-sources el)) + sources) + (add-to-list 'ac-sources 'ac-source-filename))) + +(defun ess--setup-company (sources &optional inferior) + "Setup company depending on user settings. +SOURCES gets added to `company-backends', and when t, INFERIOR +specifies inferior buffers." + ;; company + (when (and (boundp 'company-backends) + (if inferior + (eq ess-use-company t) + ess-use-company)) + (setq-local company-backends + (cl-copy-list (append sources company-backends))) + (delq 'company-capf company-backends))) + +(defun ess--setup-eldoc (fun) + "Setup support for eldoc. +FUN is the function to return data for eldoc." + (when ess-use-eldoc + (if (not (boundp 'eldoc-documentation-functions)) + ;; older versions of Eldoc included in Emacs 27 and previous + (add-function :before-until (local 'eldoc-documentation-function) + fun) + ;; new eldoc, in Emacs 28+ + (add-hook 'eldoc-documentation-functions fun nil t) + ;; Eldoc is on GNU ELPA so you can have new eldoc + Emacs 27.1 + ;; or older, see bug#1130 and Emacs bug # 47388 for why we have + ;; to do this + (when (and (fboundp 'eldoc-documentation-default) + (function-equal #'ignore eldoc-documentation-function)) + (setq-local eldoc-documentation-function #'eldoc-documentation-default))))) + +(defmacro ess--execute-electric-command (map &optional prompt wait exit-form &rest args) + "Execute keys defined in MAP till a key is pressed which is not in MAP. +Single-key input commands are those that once executed do not +require the prefix command for subsequent invocation. Return the +value of the lastly executed command. PROMPT is passed to +`read-event'. + +If WAIT is t, wait for next input and ignore the keystroke which +triggered the command. + +Each command in map should accept one at least one argument, the +most recent event (as read by `read-event'). ARGS are the +supplementary arguments passed to the commands. + +EXIT-FORM should be supplied for a more refined control of the +read-even loop. The loop is exited when EXIT-FORM evaluates to +t. See examples in the tracebug code." + ;;VS[09-06-2013]: check: it seems that set-temporary-overlay-map is designed + ;;for this type of things; see also repeat.el package. + `(let* ((ev last-command-event) + (command (lookup-key ,map (vector ev))) + out exit ) + (if (not (or ,wait command)) + (message "%s is undefined" (key-description (this-command-keys))) + (unless ,wait + (setq out (and command (funcall command ev ,@args)))) + (while (and (not exit) + (setq command + (lookup-key ,map + (vector (setq ev (read-event ,prompt)))))) + (setq out (funcall command ev ,@args)) + (sleep-for .01) + (setq exit ,exit-form)) + (unless exit ;; push only if an event triggered the exit + (push ev unread-command-events)) + out))) + +(cl-defgeneric ess-build-tags-command () + "Command passed to generate tags. +If nil, `ess-build-tags-for-directory' uses the mode's imenu +expression. Otherwise, it should be a string with two %s +formats: one for directory and another for the output file." + nil) + + +;;*;; Emacs itself + +(defun ess-yank-cleaned-commands () + "Yank and strip the code, leaving only (R/S/Lsp/..) commands. +Deletes any lines not beginning with a prompt, and then removes +the prompt from those lines that remain. Invoke this command with +\\[universal-argument] \\[universal-argument] \\\\[yank]." + (setq yank-window-start (window-start)) + (let ((beg (point))) + (push-mark beg) + (setq this-command t) + (insert-for-yank (current-kill 0)) + (when (and (require 'ess-trns) (fboundp 'ess-transcript-clean-region)) + (ess-transcript-clean-region beg (point) nil)) + (if (eq (point) beg) + (message "No commands found")) + (if (eq this-command t) + (setq this-command 'yank)))) + +(defun ess-yank (&optional arg) + "Variant of `yank' that optionally extracts commands from transcripts. +When called with double prefix ARG (\\[universal-argument] +\\[universal-argument]), calls `ess-transcript-clean-region' +before yanking. See `ess-yank-cleaned-commands'." + (interactive "*P") + (if (equal '(16) arg) + (ess-yank-cleaned-commands) + (let* ((remapped (command-remapping 'yank (point))) + (command (cond ((eq remapped 'ess-yank) 'yank) + ((null remapped) 'yank) + (t remapped)))) + (funcall command arg)))) + +(put 'ess-yank 'delete-selection 'yank) + +(defun ess-build-tags-for-directory (dir tagfile) + "Ask for directory and tag file and build tags for current dialect. +If the current language defines `ess-build-tags-command' use it +and ask the subprocess to build the tags. Otherwise use imenu +regexp and call find .. | etags .. in a shell command. You must +have `find' and `etags' programs installed. + +Use M-. to navigate to a tag. \\[visit-tags-table] to +append/replace the currently used tag table. + +If prefix is given, force tag generation based on imenu. Might be +useful when different language files are also present in the +directory (.cpp, .c etc)." + (interactive "DDirectory to tag: +GTags file (default TAGS): ") + (when (or (eq (length (file-name-nondirectory tagfile)) 0) + (file-directory-p tagfile)) + (setq tagfile (concat (file-name-as-directory tagfile) "TAGS"))) + ;; Emacs find-tags doesn't play well with remote TAG files :( + (when (file-remote-p tagfile) + (require 'tramp) + (setq tagfile (with-parsed-tramp-file-name tagfile foo foo-localname))) + (when (file-remote-p dir) + (require 'tramp) + (setq dir (with-parsed-tramp-file-name dir foo foo-localname))) + (if (and (ess-build-tags-command) (null current-prefix-arg)) + (ess-eval-linewise (format (ess-build-tags-command) dir tagfile)) + ;; else generate from imenu + (unless imenu-generic-expression + (error "No ess-tag-command found, and no imenu-generic-expression defined")) + (let* ((find-cmd + (format "find %s -type f -size 1M \\( -regex \".*\\.\\(cpp\\|jl\\|[RsrSch]\\(nw\\)?\\)$\" \\)" dir)) + (regs (delq nil (mapcar (lambda (l) + (if (string-match "'" (cadr l)) + nil ;; remove for time being + (format "/%s/\\%d/" + (replace-regexp-in-string "/" "\\/" (nth 1 l) t) + (nth 2 l)))) + imenu-generic-expression))) + (tags-cmd (format "etags -o %s --regex='%s' -" tagfile + (mapconcat #'identity regs "' --regex='")))) + (message "Building tags: %s" tagfile) + (when (= 0 (shell-command (format "%s | %s" find-cmd tags-cmd))) + (message "Building tags .. ok!"))))) + + +;;*;; UI + +(defvar ess-current-region-overlay + (let ((overlay (make-overlay (point) (point)))) + (overlay-put overlay 'face 'highlight) + overlay) + "The overlay for highlighting currently evaluated region or line.") + +(defun ess-blink-region (start end) + "Blink from START to END depending on option `ess-blink-region'." + (when ess-blink-region + (move-overlay ess-current-region-overlay start end) + (run-with-timer ess-blink-delay nil + (lambda () + (delete-overlay ess-current-region-overlay))))) + +(defun ess-deactivate-mark () + "Deactivate the mark, if active. +If `evil-mode' is on, switch to `evil-normal-state'." + (if (and (bound-and-true-p evil-mode) + (fboundp 'evil-visual-state-p) + (evil-visual-state-p)) + (when (fboundp 'evil-normal-state) + (evil-normal-state)) + (when mark-active + (deactivate-mark)))) + +;; SJE: 2009-01-30 -- this contribution from +;; Erik Iverson + +(defun ess-tooltip-show-at-point (text xo yo) + "Show a tooltip displaying TEXT at (around) point. +XO and YO are x- and y-offsets for the toolbar from point." + (let ( + (fx (frame-parameter nil 'left)) + (fy (frame-parameter nil 'top)) + (fw (frame-pixel-width)) + (fh (frame-pixel-height)) + frame-left frame-top my-x-offset my-y-offset) + ;; The following comment was found before code looking much like that + ;; of frame-left and frame-top below in the file + ;; tooltip-help.el. I include it here for acknowledgment, and I did observe + ;; the same behavior with the Emacs window maximized under Windows XP. + + ;; -----original comment-------- + ;; handles the case where (frame-parameter nil 'top) or + ;; (frame-parameter nil 'left) return something like (+ -4). + ;; This was the case where e.g. Emacs window is maximized, at + ;; least on Windows XP. The handling code is "shamelessly + ;; stolen" from cedet/speedbar/dframe.el + ;; (contributed by Andrey Grigoriev) + (setq frame-left (if (not (consp fx)) + fx + (if (eq (car fx) '-) + (- (display-pixel-width) (car (cdr fx)) fw) + (car (cdr fx))))) + (setq frame-top (if (not (consp fy)) + fy + (if (eq (car fy) '-) + (- (display-pixel-height) (car (cdr fy)) fh) + (car (cdr fy))))) + ;; calculate the offset from point, use xo and yo to adjust to preference + (setq my-x-offset (+ (car(window-inside-pixel-edges)) + (car(posn-x-y (posn-at-point))) + frame-left xo)) + (setq my-y-offset (+ (cadr(window-inside-pixel-edges)) + (cdr(posn-x-y (posn-at-point))) + frame-top yo)) + (let ((tooltip-frame-parameters + (cons (cons 'top my-y-offset) + (cons (cons 'left my-x-offset) + tooltip-frame-parameters)))) + (tooltip-show text)))) + +(defun ess-select-frame-set-input-focus (frame) + "Select FRAME, raise it, and set input focus, if possible. +Copied almost verbatim from gnus-utils.el (but with test for mac added)." + ;; The function `select-frame-set-input-focus' won't set + ;; the input focus under Emacs 21.2 and X window system. + ;;((fboundp 'select-frame-set-input-focus) + ;; (defalias 'gnus-select-frame-set-input-focus + ;; 'select-frame-set-input-focus) + ;; (select-frame-set-input-focus frame)) + (raise-frame frame) + (select-frame frame) + (cond ((and + (memq window-system '(x mac)) + (fboundp 'x-focus-frame)) + (x-focus-frame frame)) + ((and (eq window-system 'w32) + ;; silence byte compiler warnings about w32-fns + (fboundp 'w32-focus-frame)) + (w32-focus-frame frame))) + (when focus-follows-mouse + (set-mouse-position frame (1- (frame-width frame)) 0))) + +(define-obsolete-function-alias 'ess-do-auto-fill #'do-auto-fill "ESS 19.04") + + +;;*;; Syntax + +(defun ess-containing-sexp-position () + "Return the `cadr' of `syntax-ppss'." + (cadr (syntax-ppss))) + +(defun ess-code-end-position () + "Like (line-end-position) but stops at comments." + (save-excursion + (goto-char (1+ (line-end-position))) + (forward-comment -1) + (point))) + +;; FIXME: The following function pattern stuff is specific to R but is +;; used throughout ESS +(defvar ess-r-set-function-start + ;; [MGAR].. <=> {setMethod(), set[Group]Generic(), setAs(), setReplaceMethod()} + ;; see also set-S4-exp in ess-r-function-pattern below + "^set[MGAR][GMa-z]+\\s-?(") + +(defvar ess-function-pattern nil ; in R set to ess-r-function-pattern + "Regexp to match the beginning of a function in S buffers.") + +(defvar ess-r-symbol-pattern + "\\(\\sw\\|\\s_\\)" + "The regular expression for matching an R symbol.") + +(defvar ess-r-name-pattern + (concat "\\(" ess-r-symbol-pattern "+\\|\\(`\\).+`\\)") + "The regular expression for matching a R name.") + +(defvar ess--r-s-function-pattern + (let* ((Q "\\s\"") ; quote + (Sym-0 "\\(\\sw\\|\\s_\\)") ; symbol + (Symb (concat Sym-0 "+")) + (xSymb "[^ \t\n\"']+") ;; (concat "\\[?\\[?" Sym-0 "*")); symbol / [ / [[ / [symbol / [[symbol + ;; FIXME: allow '%foo%' but only when quoted; don't allow [_0-9] at beg. + (space "\\(\\s-\\|\n\\)*") ; white space + + (part-1 (concat + "\\(" ;;--------outer Either------- + "\\(\\(" ; EITHER + Q xSymb Q ; any function name between quotes + "\\)\\|\\(" + Symb ; (beginning of name) + ess-r-symbol-pattern + "\\)\\)")) ; END EITHER OR + + (set-S4-exp + (concat + "^set\\(As\\|Method\\|Generic\\|GroupGeneric\\|ReplaceMethod\\)(" ; S4 ... + Q xSymb Q "," space + ;; and now often `` signature(......), : '' + ".*" ;; <<< FIXME ??? + )) + + (part-2 (concat + "\\|" ;;--------outer Or --------- + set-S4-exp + "\\)" ;;--------end outer Either/Or------- + + "\\(" space "\\s<.*\\s>\\)*" ; whitespace, comment + ;; FIXME: in principle we should skip 'definition *= *' here + space "function\\s-*(" ; whitespace, function keyword, parenthesis + ))) + `(,part-1 ,part-2)) + "Partial regex for matching functions. + +Placeholder for use in constructing `ess-r-function-pattern' and +`ess-s-function-pattern'.") + +(defvar ess-r-function-pattern + (concat (car ess--r-s-function-pattern) + "\\s-*\\(<-\\|=\\)" ; whitespace, assign + (nth 1 ess--r-s-function-pattern)) + "The regular expression for matching the beginning of an R function.") + +(defvar ess-s-function-pattern + (concat (car ess--r-s-function-pattern) + "\\s-*\\(<-\\|_\\|=\\)" ; whitespace, assign (incl. "_") + (nth 1 ess--r-s-function-pattern)) + "The regular expression for matching the beginning of an S function.") + +(defvar ess--fn-name-start-cache nil) + +(defun ess--fn-name-start () + "Return (FN-NAME . START-POS). +FN-NAME is a function name located before the pointer. START-POS +is the position where FN-NAME starts. Store this cons in variable +`ess--fn-name-start-cache'." + (save-excursion + (save-restriction + (let* ((proc (get-buffer-process (current-buffer))) + (mark (and proc (process-mark proc)))) + (if (and mark (>= (point) mark)) + (narrow-to-region mark (point))) + (and (fboundp 'ess-noweb-narrow-to-chunk) + (bound-and-true-p ess-noweb-mode) + (ess-noweb-narrow-to-chunk)) + (unless (ess-inside-string-p) + (setq ess--fn-name-start-cache + (condition-case nil ;; check if it is inside a function + (progn + ;; for the sake of big buffers, look only 1000 chars back + (narrow-to-region (max (point-min) (- (point) 1000)) (point)) + (up-list -1) + (while (not (looking-at "(")) + (up-list -1)) + (let ((funname (symbol-name (ess-symbol-at-point)))) + (when (and funname + (not (member funname ess-S-non-functions))) + (cons funname (- (point) (length funname)))))) + (error nil)))))))) + +(defun ess-symbol-at-point () + "Like `symbol-at-point' but consider fully qualified names. +Fully qualified names include accessor symbols (like aaa$bbb and +aaa@bbb in R)." + (with-syntax-table (or ess-mode-completion-syntax-table + (syntax-table)) + (symbol-at-point))) + +(defun ess-bounds-of-symbol () + "Get bounds of symbol at point. +Intended for completion." + (let ((bounds (with-syntax-table (or ess-mode-completion-syntax-table + (syntax-table)) + (bounds-of-thing-at-point 'symbol)))) + (and bounds + (not (save-excursion + (goto-char (car bounds)) + (looking-at "/\\|[.0-9]"))) + bounds))) + +(defun ess-symbol-start () + "Get initial position for objects completion. +Symbols are fully qualified names that include accessor +symbols (like aaa$bbb and aaa@bbb in R)." + (car (ess-bounds-of-symbol))) + +(defun ess-arg-start () + "Get initial position for args completion." + (when (not (ess-inside-string-p)) + (when (ess--fn-name-start) + (if (looking-back "[(,]+[ \t\n]*" nil) + (point) + (ess-symbol-start))))) + +(defun ess-inside-string-p (&optional pos) + "Return non-nil if POS is inside string. +POS defaults to `point'." + (let ((pos (or pos (point)))) + (nth 3 (syntax-ppss pos)))) + +(defun ess-inside-comment-p (&optional pos) + "Return non-nil if POS is inside string. +POS defaults to `point'." + (let ((pos (or pos (point)))) + (nth 4 (syntax-ppss pos)))) + +(defun ess-inside-string-or-comment-p (&optional pos) + "Return non-nil if POS is inside a string or comment. +POS defaults to `point'." + (or (ess-inside-string-p pos) + (ess-inside-comment-p pos))) + +(defun ess-inside-brackets-p (&optional pos curly?) + "Return t if position POS is inside brackets. +POS defaults to point if no value is given. If CURLY?? is non nil +also return t if inside curly brackets." + (save-excursion + (let ((ppss (syntax-ppss pos)) + (r nil)) + (while (and (> (nth 0 ppss) 0) + (not r)) + (goto-char (nth 1 ppss)) + (when (or (char-equal ?\[ (char-after)) + (and curly? + (char-equal ?\{ (char-after)))) + (setq r t)) + (setq ppss (syntax-ppss))) + r))) + + +;;*;; String manipulation + +(defun ess-quote-special-chars (string) + "Quote special characters in STRING." + (replace-regexp-in-string + "\"" "\\\\\\&" + (replace-regexp-in-string ;; replace backslashes + "\\\\" "\\\\" string nil t))) + +(defun ess-rep-regexp (regexp to-string &optional fixedcase literal verbose) + "Instead of (replace-regexp..) -- do NOT replace in strings or comments. +If FIXEDCASE is non-nil, do *not* alter case of replacement text. +If LITERAL is non-nil, do *not* treat `\\' as special. +If VERBOSE is non-nil, (message ..) about replacements." + (let ((case-fold-search (and case-fold-search + (not fixedcase))); t <==> ignore case in search + (ppt (point)); previous point + (p)) + (while (and (setq p (re-search-forward regexp nil t)) + (< ppt p)) + (setq ppt p) + (cond ((not (ess-inside-string-or-comment-p (1- p))) + (if verbose + (let ((beg (match-beginning 0))) + (message "buffer in (match-beg.,p)=(%d,%d) is '%s'" + beg p (buffer-substring beg p)))) + (replace-match to-string fixedcase literal)))))) + +(defun ess-replace-regexp-dump-to-src (regexp to-string &optional dont-query verbose) + "Replace REGEXP matches from beginning of buffer with TO-STRING. +If DONT-QUERY is non-nil, call `ess-rep-regexp' else call +`query-replace-regexp'. VERBOSE can be passed to `ess-rep-regexp'." + (save-excursion + (goto-char (point-min)) + (if dont-query + (ess-rep-regexp regexp to-string nil nil verbose) + (query-replace-regexp regexp to-string nil)))) + +(defun ess-space-around (word &optional from verbose) + "Replace-regexp .. ensuring space around all occurrences of WORD. +Start at from FROM, which defaults to point." + (interactive "d\nP"); Defaults: point and prefix (C-u) + (save-excursion + (goto-char from) + (ess-rep-regexp (concat "\\([^ \t\n]\\)\\(\\<" word "\\>\\)") + "\\1 \\2" nil nil verbose) + (goto-char from) + (ess-rep-regexp (concat "\\(\\<" word "\\>\\)\\([^ \t\n]\\)") + "\\1 \\2" nil nil verbose))) + +(defun ess-time-string (&optional clock) + "Return a string for use as a timestamp, like \"13 Mar 1992\". +Include hr:min if CLOCK is non-nil. Redefine to taste." + (declare (obsolete format-time-string "ESS 19.04")) + (format-time-string (concat "%e %b %Y" (if clock ", %H:%M")))) + +(defun ess-replace-in-string (str regexp newtext &optional literal) + "Replace all matches in STR for REGEXP with NEWTEXT string. +Optional LITERAL non-nil means do a literal replacement. +Otherwise treat \\ in NEWTEXT string as special: + \\& means substitute original matched text, + \\N means substitute match for \(...\) number N, + \\\\ means insert one \\." + (if (not (stringp str)) + (error "(replace-in-string): First argument must be a string: %s" str)) + (if (stringp newtext) + nil + (error "(replace-in-string): 3rd arg must be a string: %s" + newtext)) + (let ((rtn-str "") + (start 0) + (special) + match prev-start) + (while (setq match (string-match regexp str start)) + (setq prev-start start + start (match-end 0) + rtn-str + (concat + rtn-str + (substring str prev-start match) + (cond (literal newtext) + (t (mapconcat + (function + (lambda (c) + (if special + (progn + (setq special nil) + (cond ((eq c ?\\) "\\") + ((eq c ?&) + (substring str + (match-beginning 0) + (match-end 0))) + ((and (>= c ?0) (<= c ?9)) + (if (> c (+ ?0 (length + (match-data)))) + ;; Invalid match num + (error "(replace-in-string) Invalid match num: %c" c) + (setq c (- c ?0)) + (substring str + (match-beginning c) + (match-end c)))) + (t (char-to-string c)))) + (if (eq c ?\\) (progn (setq special t) nil) + (char-to-string c))))) + newtext "")))))) + (concat rtn-str (substring str start)))) + +(defvar ess-nuke-trailing-whitespace-p nil;disabled by default 'ask + "[Dis]activates (ess-nuke-trailing-whitespace). +Disabled if nil; if t, it works unconditionally, otherwise, +the user is queried. +Note that setting the default to t may not be a good idea when you edit +binary files!") + +;;; MM: Newer Emacsen now have delete-trailing-whitespace +;;; -- but no customization like nuke-trailing-whitespace-p .. +(defun ess-nuke-trailing-whitespace () + "Nuke all trailing whitespace in the buffer. +Whitespace in this case is just spaces or tabs. This is a useful +function to put on `write-file-hooks'. If the variable +`ess-nuke-trailing-whitespace-p' is nil, this function is +disabled. If t, unreservedly strip trailing whitespace. If not +nil and not t, query for each instance." + (interactive) + (let ((bname (buffer-name))) + (cond ((or + (string= major-mode "rmail-mode") + (string= bname "RMAIL") + nil)); do nothing.. + (t + (and (not buffer-read-only) + ess-nuke-trailing-whitespace-p + (save-match-data + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (cond ((eq ess-nuke-trailing-whitespace-p t) + (while (re-search-forward "[ \t]+$" (point-max) t) + (delete-region (match-beginning 0) + (match-end 0)))) + (t + (query-replace-regexp "[ \t]+$" ""))))))))) + ;; always return nil, in case this is on write-file-hooks. + nil)) + +(defun ess--strip-final-newlines (string) + (replace-regexp-in-string "\n+$" "" string)) + + +;;*;; Debugging tools + +(defun ess-write-to-dribble-buffer (text) + "Write TEXT to `ess-dribble-buffer'." + (when (or ess-verbose ess-write-to-dribble) + (with-current-buffer (get-buffer-create ess-dribble-buffer) + (goto-char (point-max)) + (insert-before-markers text)))) + +(defun ess-if-verbose-write (text) + "Write TEXT to `ess-dribble-buffer' only if `ess-verbose' is non-nil." + (when ess-verbose (ess-write-to-dribble-buffer text))) + +(defun ess-kill-last-line () + (save-excursion + (goto-char (point-max)) + (forward-line -1) + (delete-region (line-end-position) (point-max)))) + +(defun ess-sleep () + "Put Emacs to sleep for `ess-sleep-for-shell' seconds (floats work)." + (sleep-for ess-sleep-for-shell)) + +(defun ess-setq-vars-local (alist &optional buf) + "Set language variables from ALIST, in buffer BUF, if desired." + (when buf (set-buffer buf)) + (mapc (lambda (pair) + (make-local-variable (car pair)) + (set (car pair) (eval (cdr pair) t)) + (when (bound-and-true-p ess--make-local-vars-permanent) + (put (car pair) 'permanent-local t))) ;; hack for Rnw + alist)) + +(defmacro ess--alist (vars) + "Build a self-named alist from VARS. +VARS must be a list of symbols." + (declare (debug 0)) + `(list ,@(mapcar (lambda (var) `(cons ',var ,var)) vars))) + +(defvar ess-error-regexp "^\\(Syntax error: .*\\) at line \\([0-9]*\\), file \\(.*\\)$" + "Regexp to search for errors.") + +(define-obsolete-function-alias 'ess-beginning-of-function #'beginning-of-defun "ESS 19.04") +(define-obsolete-function-alias 'ess-end-of-function #'end-of-defun "ESS 19.04") + +(with-no-warnings + (defalias 'ess--project-root + ;; TODO: Remove once we drop support for Emacs 27 + (if (and (fboundp 'project-root) + ;; Issues caused unless we confirm `project-roots' is obsolete, see bug#1052 + (get 'project-roots 'byte-obsolete-info)) + 'project-root + (lambda (project) "See `project-roots'." + (car (project-roots project)))))) + +(provide 'ess-utils) + +;;; ess-utils.el ends here diff --git a/elpa/ess-20230419.1527/ess.el b/elpa/ess-20230419.1527/ess.el new file mode 100644 index 00000000..31cac957 --- /dev/null +++ b/elpa/ess-20230419.1527/ess.el @@ -0,0 +1,234 @@ +;;; ess.el --- Emacs Speaks Statistics -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. + +;; Author: David Smith +;; A.J. Rossini +;; Richard M. Heiberger +;; Kurt Hornik +;; Martin Maechler +;; Rodney A. Sparapani +;; Stephen Eglen +;; Sebastian P. Luque +;; Henning Redestig +;; Vitalie Spinu +;; Lionel Henry +;; J. Alexander Branham +;; +;; Maintainer: ESS Core Team +;; Created: 7 Jan 1994 +;; Version: 18.10.3snapshot +;; URL: https://ess.r-project.org/ +;; Package-Requires: ((emacs "25.1")) +;; ESSR-Version: 1.8 + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: +;; +;; Emacs Speaks Statistics (ESS) is a package designed to support editing of +;; scripts and interaction with various statistical analysis programs such as R, +;; S-Plus, SAS, Stata and OpenBUGS/JAGS. For more details please visit ESS home +;; page at https://ess.r-project.org/ + +;;; Code: + +(require 'ess-utils) +(require 'cl-generic) +(require 'lisp-mnt) +(defvar reporter-prompt-for-summary-p) + + +;; Versions + +(defconst ess-version (eval-when-compile + (lm-version (or (and (boundp 'load-true-file-name) + load-true-file-name) + load-file-name + buffer-file-name))) + "Version of ESS currently loaded.") + +(defconst essr-version (eval-when-compile + (lm-with-file (or (and (boundp 'load-true-file-name) + load-true-file-name) + load-file-name + buffer-file-name) + (lm-header "ESSR-Version"))) + "Version of ESSR package.") + +(defvar ess-revision nil + "The revision and date of ESS. +Is set by \\[ess-version-string].") + +;;;###autoload +(defun ess-version () + "Return a string with ESS version information." + (interactive) + (message (format "ess-version: %s (loaded from %s)" + (ess-version-string) + (file-name-directory ess-lisp-directory)))) + +(defun ess-version-string () + (let* ((ess-dir (file-name-directory ess-lisp-directory)) ; if() the top-level 'ess/' + (is-release (file-exists-p (concat ess-etc-directory ".IS.RELEASE"))) + (rel-string (if is-release "Released ")) + (git-ref-fn (concat ess-dir ".git/HEAD")) + (git-ref (when (file-exists-p git-ref-fn) + (with-current-buffer (find-file-noselect git-ref-fn) + (goto-char (point-min)) + (when (re-search-forward "ref: \\(.*\\)\n" nil t) + (match-string 1))))) + (git-fname (if git-ref + (concat ess-dir ".git/" git-ref) + ;; For release + (concat ess-etc-directory "git-ref"))) + (git-rev (when (file-exists-p git-fname) + (with-current-buffer (find-file-noselect git-fname) + (goto-char (point-min)) + (concat "git: "(buffer-substring + (point-min) (line-end-position)))))) + (elpa-fname (concat ess-dir "ess-pkg.el")) + (elpa-rev (when (file-exists-p elpa-fname) + ;; Get it from ELPA dir name, (probably won't work if installed manually) + (concat "elpa: " + (replace-regexp-in-string "ess-" "" + (file-name-nondirectory + (substring ess-dir 1 -1))))))) + ;; Set the "global" ess-revision: + (setq ess-revision (format "%s%s%s" + (or rel-string "") + (or git-rev "") + (or elpa-rev ""))) + (when (string= ess-revision "") + (setq ess-revision "")) + (concat ess-version " [" ess-revision "]"))) + + +;;; Bug Reporting + +;;;###autoload +(defun ess-submit-bug-report () + "Submit a bug report to the ESS maintainers." + (interactive) + (let ((reporter-prompt-for-summary-p 't)) + (reporter-submit-bug-report + "ess-bugs@r-project.org" + (concat "ess-mode " (ess-version-string)) + (list 'ess-language + 'ess-dialect + 'ess-ask-for-ess-directory + 'ess-ask-about-transfile + 'default-directory + 'ess-keep-dump-files + 'ess-source-directory + 'ess-use-ido + 'ess-use-eldoc + 'ess-use-tracebug + 'ess-use-auto-complete + 'ess-use-company + 'ess-eval-visibly-p + 'ess-can-eval-in-background + 'ess-local-process-name) + nil + (lambda () + ;;(goto-char (point-max)) + (rfc822-goto-eoh) + (forward-line 1) + (insert "\n\n-------------------------------------------------------\n") + (insert "This bug report will be sent to the ESS bugs email list\n") + (insert "Press C-c C-c when you are ready to send your message.\n") + (insert "-------------------------------------------------------\n\n") + (insert (with-current-buffer ess-dribble-buffer + (goto-char (point-max)) + (forward-line -100) + (buffer-substring-no-properties (point) (point-max)))))))) + + + +;;; Timer + +(defcustom ess-idle-timer-interval 1 + "Number of seconds to wait before running function in `ess-idle-timer-functions'." + :type '(integer) + :group 'ess) + +(defvar ess-idle-timer-functions nil + "A list of functions to run each `ess-idle-timer-interval' idle seconds. +If your function calls the process, you better use +`ess-when-new-input' to wrap your call. If you call the +subprocess please respect `ess-can-eval-in-background' variable. + +These functions are run with `run-hooks'. Use `add-hook' to add +symbols to this variable. + +Most likely you will need a local hook. Then you should specify +the LOCAL argument to `add-hook' and initialize it in +`ess-mode-hook' or `ess-post-run-hook', or one of the more +specialized hooks `ess-r-post-run-hook',`ess-stata-post-run-hook' +etc.") + +(defun ess--idle-timer-function nil + "Internal function executed by `ess--idle-timer'." + (run-hooks 'ess-idle-timer-functions)) + +(require 'timer) +(defvar ess--idle-timer + (run-with-idle-timer ess-idle-timer-interval 'repeat + #'ess--idle-timer-function) + "Timer used to run `ess-idle-timer-functions'.") + + +;;; Dispatch on ess-dialect +;; Inspired by major-mode specializer in cl-generic.el + +;; FIXME: Implement a notion of derived dialects. major-mode specializer cannot +;; be used here as we need same dialect in different major-modes. + +;; Two parts: +;; 1) first define a specializer (ess-dialect= DIALECT) to match symbols +;; representing ess dialects. +;; 2) then define a context-rewriter so you can write +;; `&context (ess-dialect "R")` rather than +;; `&context (ess-dialect (ess-dialect= "R"))`. + +(cl-generic-define-generalizer ess--generic-dialect-generalizer + 95 + (lambda (name &rest _) `(if (stringp ,name) (intern ,name) + (if (symbolp ,name) ,name))) + (lambda (tag &rest _) `((ess-dialect= ,tag)))) + +(cl-defmethod cl-generic-generalizers ((_specializer (head ess-dialect=))) + "Support for (ess-dialect DIALECT) context specializer." + (list ess--generic-dialect-generalizer)) + +(cl-generic-define-context-rewriter ess-dialect (dialect) + `(ess-dialect (ess-dialect= ,(if (stringp dialect) + (intern dialect) + dialect)))) + +;; (cl-defgeneric ess-print-dialect () +;; (error "unknown dialect %s" ess-dialect)) +;; (cl-defmethod ess-print-dialect (&context (ess-dialect "R")) +;; (message "dialect: R")) +;; (cl-defmethod ess-print-dialect (&context (ess-dialect "julia")) +;; (message "dialect: julia")) + +(provide 'ess) + +;;; ess.el ends here diff --git a/elpa/ess-20230419.1527/ess.info b/elpa/ess-20230419.1527/ess.info new file mode 100644 index 00000000..9c96dfc7 --- /dev/null +++ b/elpa/ess-20230419.1527/ess.info @@ -0,0 +1,5133 @@ +This is ess.info, produced by makeinfo version 6.7 from ess.texi. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* ESS: (ess). Emacs Speaks Statistics (R/S/S+, SAS, BUGS/JAGS and Stata). +END-INFO-DIR-ENTRY + +ESS -- Emacs Speaks Statistics +****************************** + + +File: ess.info, Node: Top, Next: Introduction, Up: (dir) + +ESS: Emacs Speaks Statistics +**************************** + +ESS version 18.10.3snapshot + + by A.J. Rossini, + R.M. Heiberger, + K. Hornik, + M. Maechler, + R.A. Sparapani, + S.J. Eglen, + S.P. Luque, + H. Redestig, + V. Spinu, + L. Henry, + and J.A. Branham. + + Emacs Speaks Statistics (ESS) provides an intelligent, consistent + interface between the user and the software. ESS interfaces with + R, SAS, S-PLUS, BUGS/JAGS and other statistical analysis packages + on GNU/Linux, other Unix-like systems such as macOS, and Microsoft + Windows. ESS is itself a package within the Emacs text editor and + uses Emacs features to streamline the creation and use of + statistical software. ESS knows the syntax and grammar of + statistical analysis packages and provides consistent display and + editing features based on that knowledge. ESS assists in + interactive and batch execution of statements written in these + statistical analysis languages. + + The source and documentation of ESS is free software. You can +redistribute it and/or modify it under the terms of the GNU General +Public License as published by the Free Software Foundation; either +version 2, or (at your option) any later version. + + ESS is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License in +the file COPYING in the same directory as this file for more details. + +* Menu: + +* Introduction:: Overview of features provided by this package +* Installation:: Installing ESS on your system +* Interactive ESS:: Interacting with statistical programs +* Entering commands:: Interacting with the ESS process +* Evaluating code:: Sending code to the ESS process +* Transcript Mode:: Manipulating saved transcript files +* Editing objects:: How to create/edit objects and functions +* Help:: Reading help files +* Completion:: Various completion mechanisms +* Developing with ESS:: Tools for package development and debugging +* Extras:: Other ESS features for the S family +* ESS for R:: Overview of ESS features for the S family +* ESS for SAS:: +* ESS for BUGS:: +* ESS for JAGS:: +* Mailing lists/bug reports:: How to get assistance with ESS +* Customization:: Customizing ESS +* Indices:: + + +File: ess.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +1 Introduction to ESS +********************* + +ESS provides a generic interface, through Emacs, to statistical +packages. It currently supports R (and the rest of the S family), SAS, +BUGS/JAGS, Stata, and Julia with the level of support roughly in that +order. + + Throughout this manual, _Emacs_ refers to _GNU Emacs_ by the Free +Software Foundation. Although previous versions of ESS supported other +Emacsen, current versions only support GNU Emacs. + + There are two main ways of interacting with ESS: through "regular" +modes or "inferior" modes. Regular modes act like normal Emacs major +modes. ESS major modes are displayed in the mode-line in the format +'ESS[dialect]', where 'dialect' can take values such as 'R', 'SAS', or +'S'. + + ESS also provides easy access to an "inferior process," which is an +Emacs buffer associated with a running process. This can be an R +session, for example. These inferior processes are referred to as +inferior ESS ('iESS'), and are shown in the modeline by 'iESS +[dialect]'. + + Currently, the documentation contains many references to ''R'' where +actually any supported (statistics) language is meant, i.e., 'R' could +also mean 'S' or 'SAS.' + + For exclusively interactive users of R, ESS provides a number of +features to make life easier. There is an easy to use command history +mechanism, including a quick prefix-search history. To reduce typing, +command-line completion is provided for all R objects and "hot keys" are +provided for common R function calls. Help files are easily accessible, +and a paging mechanism is provided to view them. Finally, an incidental +(but very useful) side-effect of ESS is that a transcript of your +session is kept for later saving or editing. + + No special knowledge of Emacs is necessary when using R interactively +under ESS. + + For those that use R in the typical edit-test-revise cycle when +writing R functions, ESS provides for editing of R functions in Emacs +buffers. Unlike the typical use of R where the editor is restarted +every time an object is edited, ESS uses the current Emacs session for +editing. In practical terms, this means that you can edit more than one +function at once, and that the ESS process is still available for use +while editing. Error checking is performed on functions loaded back +into R, and a mechanism to jump directly to the error is provided. ESS +also provides for maintaining text versions of your R functions in +specified source directories. + +* Menu: + +* Features:: Why should I use ESS? +* New features:: +* Credits:: Authors of and contributors to ESS +* Manual:: How to read this manual + + +File: ess.info, Node: Features, Next: New features, Up: Introduction + +1.1 Why should I use ESS? +========================= + +Statistical packages are powerful software systems for manipulating and +analyzing data, but their user interfaces often leave something to be +desired: they offer weak editor functionality and they differ among +themselves so markedly that you have to re-learn how to do those things +for each package. ESS is a package which is designed to make editing +and interacting with statistical packages more uniform, user-friendly +and give you the power of Emacs as well. + + Additionally, both Emacs and ESS (and R) are free software designed +to give users full control over their computer. For more on what this +means, visit . + +* Menu: + +* Current Features:: + + +File: ess.info, Node: Current Features, Up: Features + +1.1.1 Features Overview +----------------------- + + * Languages Supported: + * S family (R, S, and S+ AKA S-PLUS) + * SAS + * BUGS/JAGS + * Stata + * Julia + * Editing source code (S family, SAS, BUGS/JAGS, Stata, Julia) + * Syntactic indentation and highlighting of source code + * Partial evaluation of code + * Loading and error-checking of code + * Source code revision maintenance + * Batch execution (SAS, BUGS/JAGS) + * Use of imenu to provide links to appropriate functions + * Interacting with the process (S family, SAS, Stata, Julia) + * Command-line editing + * Searchable Command history + * Command-line completion of S family object names and file + names + * Quick access to object lists and search lists + * Transcript recording + * Interface to the help system + * Transcript manipulation (S family, Stata) + * Recording and saving transcript files + * Manipulating and editing saved transcripts + * Re-evaluating commands from transcript files + * Interaction with Help Pages and other Documentation (R) + * Fast Navigation + * Sending Examples to running ESS process. + * Fast Transfer to Further Help Pages + * Help File Editing (R) + * Syntactic indentation and highlighting of source code. + * Sending Examples to running ESS process. + * Previewing + + For source code buffers, ESS offers several features: + + * Support for multiple indentation styles R code *Note Indenting::. + + * Facilities for loading and error-checking source files, including a + keystroke to jump straight to the position of an error in a source + file. *Note Error Checking::. + + * Source code revision maintenance, which allows you to keep historic + versions of R source files. *Note Source Files::. + + * Facilities for evaluating R code such as portions of source files, + or line-by-line evaluation of files (useful for debugging). *Note + Evaluating code::. + + ESS also provides features that make it easier to interact with +inferior ESS (iESS) process (a connection between your buffer and the +statistical package which is waiting for you to input commands). These +include: + + * Command-line editing for fixing mistakes in commands before they + are entered. *Note Command-line editing::. + + * Searchable command history for recalling previously-submitted + commands. *Note Command History::. + + * Command-line completion of both object and file names for quick + entry. *Note Completion::. + + * Hot-keys for quick entry of commonly-used commands in 'R' such as + 'objects()', and 'search()'. *Note Hot keys::. + + * Transcript recording for a complete record of all the actions in an + R session. *Note Transcript::. + + * Interface to the help system, with a specialized mode for viewing R + help files. *Note Help::. + + * Object editing. ESS allows you to edit more than one function + simultaneously in dedicated Emacs buffers. The ESS process may + continue to be used while functions are being edited. *Note Edit + buffer::. + + Finally, ESS provides features for re-submitting commands from saved +transcript files, including: + + * Evaluation of previously entered commands, stripping away + unnecessary prompts. *Note Transcript resubmit::. + + +File: ess.info, Node: New features, Next: Credits, Prev: Features, Up: Introduction + +1.2 New features in ESS +======================= + +Changes and New Features in 19.04 (unreleased): + + * ESS[R]: When a background command is interrupted with C-g, ESS now + asks the user if they want to disable background evaluations + altogether. This is a resiliency measure against cases where + background evals cause cascading errors or hangs. + + * ESS[R]: Background commands now propagate errors to Emacs. + + * ESS[R]: Background commands can now be disabled by process instad + of globally. For instance when a process has failed to initialize + properly, background evals are disabled for that particular process + to avoid cascading errors. Other processes may still use + background commands. + + * ESS[R]: ESSR commands are now more robust when ESSR is not in + scope. This can happen when using 'browser()' in an environment + that doesn't inherit from the search path. + + * ESS[R]: Unexpected exits are now detected during startup. In that + case an error is thrown with advice about how to recover. + + * ESS[R]: 'options(width = )' is now set on startup based on the + width of the inferior window. + + * ESS[R]: Add support for R projects and start R by default in the + project folder. + + * ESS[R]: Backticked symbols in the process buffer are no longer + fontified as strings. + + * ESS[R]: 'ess-command' now runs R code in a sandboxed environment. + Use '.ess.environment()' to inspect the current environment. + + * ESS[R]: Added support for new syntax in R 4.0 and R 4.1. This + concerns raw strings, lambda functions, and the pipe operator. + + * ESS[R]: Highlight error locations in rlang style backtraces + + * ESS[R]: Fixed issue that caused ESS-help to hang when usage blocks + include R comments (#1025). Fix contributed by Bill Evans. + + * ESS: New 'ess-elisp-trace-mode' minor mode. Toggle it to start or + stop tracing all 'ess'-prefixed functions with 'trace-function'. + Tracing is useful for debugging background ESS behaviour. + + * ESS[R]: 'ess-get-help-aliases-list' now caches the aliases on the R + side. This should speed up help lookup when the search path has + changed and the aliases are read again. + + * ESS: 'ess-command' now uses a default timeout of 30 seconds. It + should normally be avoided with long-running tasks because it + causes Emacs to block while the command is running. If the timeout + is reached, an error is thrown. An interrupt is also sent to the + process in case of early exit. + + This is a behaviour change: you will now have to explicitly opt in + blocking the whole Emacs UI for more than 30 seconds by supplying a + larger timeout (use 'most-positive-fixnum' for infinity). + + * ESS: 'ess-wait-for-process' now returns nil if a timeout is + reached. + + * ESS: 'ess-get-words-from-vector' gains a 'timeout' argument. + + * ESS[R]: Fixed performance issue with argument completions. The + help summary for the argument is no longer displayed in the echo + area. This fixes delays and hangs (#1062). + + * ESS[R]: 'ess-command' is now more robust and resilient to hangs and + custom prompts (#1043). It also strips continuation prompts ('+' + prompts) automatically and reliably (#1116). + + * ESS[R]: 'ess-command' now handles sinked consoles correctly. + + * ESS[R]: 'ess-command' no longer changes '.Last.value'. As a + result, background tasks like completions no longer affect the last + value binding (#1058). + + * ESS[R]: Namespaced evaluation is disable in roxygen examples + (#1026). Part of this change is that namespaced evaluation has + become a buffer-local rather than process-local setting (#1046). + This makes it possible to disable namespaced evaluation in specific + buffers or contexts. + + * iESS: Inferior processes can now properly reuse frames (#987). + Fixed issue that caused the current buffer to be incorrectly + displayed in the new frame when 'display-buffer' is set to pop up + frames. + + * ESS[R]: Better support for tramp. Fixed package evaluation on + remote servers with Tramp (#950); process reloading (#1001); and an + evaluation issue (#1024). These fixes were contributed by David + Pritchard. + + * ESS[R]: Automatic offsetting of R process output is now disabled by + default because it produces undesirable output in some situations. + To re-enable, set 'inferior-ess-fix-misaligned-output' to t. + + * ESS[R]: Improved 'xref' lookup ('M-.'). Function locations are now + always detected for package libraries listed in + 'ess-r-package-library-paths'. + + * ESS[R]: Evaluated lines starting with the Roxygen prefix are now + always stripped from the prefix, so they can be sent to the process + easily. Previously, this was only the case inside the 'examples' + field. Since roxygen is switching to R markdown, it becomes useful + to evaluate chunks of R outside examples. + + * stata support is now obsolete since we were unable to elicit FSF + paperwork from some of the original authors: see the lisp/obsolete + sub-directory on the ESS github repo + + * 'ess-set-working-directory' no longer changes the active directory + (as defined by the buffer-local variable 'default-directory') of + the buffer where the command is called. Instead, the active + directory of the inferior buffer is updated to the new working + directory. + + * The default of ess-eval-visibly is now ''nowait'. With this change + you should no longer experience freezes while evaluating code. + + * ESS[R]: There is a new menu entry for reloading the R process. It + is otherwise bound to 'C-c C-e C-r'. Reloading now reuses the same + process name and start arguments that were used to start the + process. + + * iESS: Process runners now return the inferior buffer. Note that + callers of inferior runners should not assume that the current + buffer has been set to the inferior buffer. Instead, use + 'with-current-buffer' with the return value of the inferior. + + * iESS[SAS]: The SAS keymap was only set in iESS buffers called + '*SAS*'. This is now fixed. + + * ESS[R]: Fixed longstanding indentation issues involving '::' and + ':::' operators. + + * Implement a more reliable check for the process busy state. + Background actions such as completion and directory synchronization + should not block the process and should not cause printing of the + extraneous output to the interpreter. + + * Activate 'goto-address-mode' for url and email highlighting in + inferior buffers. + + * 'smart-underscore' and 'ess-smart-S-assign-key' have been removed. + Users who liked the previous behavior (i.e. underscore inserting + "<-") should bind 'ess-insert-assign' to the underscore in their + Emacs initialization file. For example, '(define-key + ess-r-mode-map "_" #'ess-insert-assign)' and '(define-key + inferior-ess-r-mode-map "_" #'ess-insert-assign)' will activate it + in all ESS R buffers. + + * ESS major modes are now defined using 'define-derived-mode'. This + makes ESS major modes respect modern conventions such as having + -mode-hook and -mode-map. Users are encouraged + to place customizations under the appropriate mode. + + * New option ess-auto-width controls setting the width option on + window changes. Users can change it to 'frame, 'window, or an + integer. See the documentation for details. + 'ess-auto-width-visible' controls visibility. + + * ESS now respects 'display-buffer-alist'. Users can now use + 'display-buffer-alist' to manage how and where windows appear. For + more information and examples, see *Note (ess)Controlling buffer + display::. + + * 'ess-roxy-mode' can now be enabled in non-R buffers. This is + primarily intended to support roxygen documentation for cpp + buffers. Preview functionality is not supported outside R buffers. + + * ESS[R]: DESCRIPTION files now open in 'conf-colon-mode'. + + * 'ess-style' now has effects when set as a file or directory local + variable. + + * 'ess-default-style' is now obsolete, use 'ess-style' instead. + + * Options for 'ess-gen-proc-buffer-name-function' have been renamed. + ess-gen-proc-buffer-name:projectile-or-simple was renamed to + ess-gen-proc-buffer-name:project-or-simple and + ess-gen-proc-buffer-name:projectile-or-directory was renamed to + ess-gen-proc-buffer-name:project-or-directory. As the name + suggests, these now rely on project.el (included with Emacs) rather + than projectile.el, which is a third-party package. + + * Eldoc fully honors 'eldoc-echo-area-use-multiline-p' + + * ESS[R]: 'ess-r-rhub-check-package' gained new 'RECOMMENDED'. + + * ESS[R]: devtools commands ask about saving modified buffers before + running. Users can disable the questioning with + 'ess-save-silently'. + + * ESS[R] help pages now provide links to other help topics. This is + similar with what you would see with, for example + 'options(help_type = ``html'')' but works with the plain-text + version as well. This only works with 'options(useFancyQuotes = + TRUE)' (the default). + + * 'ess-rdired' buffers now derive from tabulated-list-mode. They + should look better and be a bit faster overall. The size column + now displays object sizes in bytes. + + * 'ess-rdired' buffers now auto-update. The frequency is governed by + the new option 'ess-rdired-auto-update-interval'. + + * ESS[R]: 'electric-layout-mode' is now supported. This + automatically inserts a newline after an opening curly brace in R + buffers. To enable it, customize 'ess-r-mode-hook'. + + * ESS[R]: imenu now supports assignment with the equals sign. + + * ESS[Rd]: Rd no longer writes abbrevs to user's abbrev file. + + * ESS removed support for many unused languages. This includes old + versions of S+, ARC, OMG, VST, and XLS. + + * ess-r-runner-prefixes was modified to find R-4 and later. + + * ESS no longer activates eldoc if the user has disabled + global-eldoc-mode. + + The following have been made obsolete or removed, see their +documentation for more detail: + + * Libraries for literate data analysis are obsolete and not loaded by + default. This includes 'ess-noweb', 'ess-swv', and related + functionality like 'Rnw-mode'. Users are encouraged to switch to + one of several other packages that deal with these modes. For + example, polymode , + , or markdown-mode with edit-indirect + . + + * Support for 'auto-complete' is obsolete. The 'auto-complete' + package is unmaintained and so ESS support is now obsolete. Users + are encouraged to switch to 'company-mode' instead. + + * User options for controlling display of buffers. This includes + 'ess-show-buffer-action', 'inferior-ess-same-window', + 'inferior-ess-own-frame', and 'inferior-ess-frame-alist'. See + above about ESS respecting 'display-buffer-alist'. + + * Variables 'ess-tab-always-indent' and 'ess-tab-complete-in-script'. + Use the Emacs-wide setting of 'tab-always-indent' instead. + + * 'inferior-ess-*-start-file' variables. All modes except Stata did + not respect customization of this variable. In order to load a + file on startup, you should put a function on + 'ess-*-post-run-hook'. + + Bug Fixes in 18.10.3: + * More 'Makefile' fixes, notably installing '*.el's. + + Bug Fixes in 18.10.2: + * ESS[R] Fix namespace evaluation in non-installed packages. + Evaluation is directed into GlobalEnv as originally intended. + * 'Makefile' fixes, notably for 'make install' and including full + docs in the tarballs. + + Bug Fixes in 18.10-1: + * New functions 'ess-eval-line-visibly-and-step' ('C-c C-n' and + 'ess-eval-region-or-line-visibly-and-step' ('C-RET') which behave + as the old versions of 'ess-eval-line-and-step' and + 'ess-eval-region-or-line-and-step'. + + Changes and New Features in 18.10: + + * This is the last release to support Emacs older than 25.1. Going + forward, only GNU Emacs 25.1 and newer will be supported. Soon + after this release, support for older Emacs versions will be + dropped from the git master branch. Note that MELPA uses the git + master branch to produce ESS snapshots, so if you are using Emacs < + 25.1 from MELPA and are unable to upgrade, you should switch to + MELPA-stable. + + * ESS now displays the language dialect in the mode-line. So, for + example, R buffers will now show ESS[R] rather than ESS[S]. + + * The ESS manual has been updated and revised. + + * The ESS initialization process has been further streamlined. If + you update the autoloads (which installation from 'package-install' + does), you should not need to '(require 'ess-site)' at all, as + autoloads should automatically load ESS when it is needed (e.g. + the first time an R buffer is opened). In order to defer loading + your ESS config, you may want to do something like + '(with-require-after-load "ess" )' in your Emacs + init file. Users of the popular 'use-package' Emacs package can + now do '(use-package ess :defer t)' to take advantage of this + behavior. For more information on this feature, see *Note + (ess)Activating and Loading ESS::. + + * ESS now respects Emacs conventions for keybindings. This means + that The 'C-c [letter]' bindings have been removed. This affects + 'C-c h', which was bound to 'ess-eval-line-and-step-invisibly' in + 'sas-mode-local-map'; 'C-c f', which was bound to + 'ess-insert-function-outline' in 'ess-add-MM-keys'; and 'C-c h', + which was bound to 'ess-handy-commands' in 'Rd-mode-map', + 'ess-noweb-minor-mode-map', and 'ess-help-mode-map' + + * Functions 'ess-eval-line-and-step' and + 'ess-eval-region-or-line-and-step' now behave consistently with + other evaluation function inside a package. + + * ESS[R]: 'ess-r-package-use-dir' now works with any mode. This sets + the working directory to the root of the current package including + for example C or C++ files within '/src'). + + * ESS[R]: Long + + prompts in the inferior no longer offset output. + + * ESS[R]: New option 'strip' for 'inferior-ess-replace-long+'. This + strips the entire + + sequence. + + * ESS modes now inherit from 'prog-mode'. In the next release, ESS + modes will use 'define-derived-mode' so that each mode will have + (for example) its own hooks and keymaps. + + * ESS[R]: Supports flymake in R buffers for Emacs 26 and newer. + Users need to install the 'lintr' package to use it. Customizable + options include 'ess-use-flymake', 'ess-r-flymake-linters', and + 'ess-r-flymake-lintr-cache'. + + * ESS[R]: Gained support for xref in Emacs 25+ *Note (emacs)Xref::. + + * ESS[R]: The startup screen is cleaner. It also displays the + startup directory with an explicit 'setwd()'. + + * ESS[R]: Changing the working directory is now always reflected in + the process buffer. + + * ESS[R]: 'Makevars' files open with 'makefile-mode'. + + * New variable 'ess-write-to-dribble'. This allows users to disable + the dribble ('*ESS*') buffer if they wish. + + * All of the '*-program-name' variables have been renamed to + '*-program'. Users who previously customized e.g. + 'inferior-ess-R-program-name' will need to update their + customization to 'inferior-ess-R-program'. These variables are + treated as risky variables. + + * 'ess-smart-S-assign' was renamed to 'ess-insert-assign'. It + provides similar functionality but for any keybinding, not just + '_'. For instance if you bind it to ';', repeated invocations + cycle through between assignment and inserting ';'. + + * 'C-c C-=' is now bound to 'ess-cycle-assign' by default. See the + documentation for details. New user customization option + 'ess-assign-list' controls which assignment operators are cycled. + + * ESS[R] In remote sessions, the ESSR package is now fetched from + GitHub. + + * Commands that send the region to the inferior process now deal with + rectangular regions. See the documentation of 'ess-eval-region' + for details. This only works on Emacs 25.1 and newer. + + * ESS[R]: Improvements to interacting with iESS in non-R files. + Interaction with inferior process in non-R files within packages + (for instance C or C++ files) has been improved. This is a work in + progress. + + * ESS[R]: Changing the working directory is now always reflected in + the process buffer. + + * ESS[JAGS]: *.jog and *.jmd files no longer automatically open in + JAGS mode. + + Many improvements to fontification: + + * Improved customization for faces. ESS now provides custom faces + for (nearly) all faces used and places face customization options + into their own group. Users can customize these options using 'M-x + customize-group RET ess-faces'. + + * Many new keywords were added to 'ess-R-keywords' and + 'ess-R-modifiers'. See the documentation for details. + + * ESS[R]: 'in' is now only fontified when inside a 'for' construct. + This avoids spurious fontification, especially in the output buffer + where 'in' is a common English word. + + * ESS: Font-lock keywords are now generated lazily. That means you + can now add or remove keywords from variables like 'ess-R-keywords' + in your Emacs configuration file after loading ESS (i.e. in the + ':config' section for 'use-package' users). + + * ESS[R]: Fontification of roxygen '@param' keywords now supports + comma-separated parameters. + + * ESS[R]: Certain keywords are only fontified if followed by a + parenthesis. Function-like keywords such as 'if ()' or 'stop()' + are no longer fontified as keyword if not followed by an opening + parenthesis. The same holds for search path modifiers like + 'library()' or 'require()'. + + * ESS[R]: Fixed fontification toggling. Especially certain syntactic + elements such as '%op%' operators and backquoted function + definitions. + + * ESS[R]: 'ess-font-lock-toggle-keyword' can be called interactively. + This command asks with completion for a font-lock group to toggle. + This functionality is equivalent to the font-lock menu. + + Notable bug fixes: + + * 'prettify-symbols-mode' no longer breaks indentation. This is + accomplished by having the pretty symbols occupy the same number of + characters as their non-pretty cousins. You may customize the new + variable 'ess-r-prettify-symbols' to control this behavior. + + * ESS: Inferior process buffers are now always displayed on startup. + Additionally, they don't hang Emacs on failures. + + Obsolete libraries, functions, and variables: + + * The 'ess-r-args.el' library has been obsoleted and will be removed + in the next release. Use 'eldoc-mode' instead, which is on by + default. + + * Functions and options dealing with the smart assign key are + obsolete. The following functions have been made obsolete and will + be removed in the next release of ESS: 'ess-smart-S-assign', + 'ess-toggle-S-assign', 'ess-toggle-S-assign-key', + 'ess-disable-smart-S-assign'. + + The variable 'ess-smart-S-assign-key' is now deprecated and will be + removed in the next release. If you would like to continue using + '_' for inserting assign in future releases, please bind + 'ess-insert-assign' in 'ess-mode-map' the normal way. + + * ESS[S]: Variable 'ess-s-versions-list' is obsolete and ignored. + Use 'ess-s-versions' instead. You may pass arguments by starting + the inferior process with the universal argument. + + Changes and New Features in 17.11: + + * The ESS initialization process has been streamlined. You can now + load the R and Stata modes independently from the rest of ESS. Just + put '(require 'ess-r-mode)' or '(require 'ess-stata-mode)' in your + init file. This is for experienced Emacs users as this requires + setting up autoloads for '.R' files manually. We will keep + maintaining 'ess-site' for easy loading of all ESS features. + + * Reloading and quitting the process is now more robust. If no + process is attached, ESS now switches automatically to one + (prompting you for selection if there are several running). + Reloading and quitting will now work during a debug session or when + R is prompting for input (for instance after a crash). Finally, + the window configuration is saved and restored after reloading to + prevent the buffer of the new process from capturing the cursor. + + * ESS[R]: New command 'ess-r-package-use-dir'. It sets the working + directory of the current process to the current package directory. + + * ESS[R] Lookup for references in inferior buffers has been improved. + New variable 'ess-r-package-source-roots' contains package + sub-directories which are searched recursively during the file + lookup point. Directories in 'ess-tracebug-search-path' are now + also searched recursively. + + * ESS[R] Namespaced evaluation is now automatically enabled only in + the 'R/' directory. This way ESS will not attempt to update + function definitions from a package if you are working from e.g. a + test file. + + Changes and New Features in 16.10: + + * ESS[R]: Syntax highlighting is now more consistent. Backquoted + names are not fontified as strings (since they really are + identifiers). Furthermore they are now correctly recognized when + they are function definitions or function calls. + * ESS[R]: Backquoted names and '%op%' operators are recognized as + sexp. This is useful for code navigation, e.g. with 'C-M-f' and + 'C-M-b'. + * ESS[R]: Integration of outline mode with roxygen examples fields. + You can use outline mode's code folding commands to fold the + examples field. This is especially nice to use with well + documented packages with long examples set. Set + 'ess-roxy-fold-examples' to non-nil to automatically fold the + examples field when you open a buffer. + * ESS[R]: New experimental feature: syntax highlighting in roxygen + examples fields. This is turned off by default. Set + 'ess-roxy-fontify-examples' to non-nil to try it out. + * ESS[R]: New package development command 'ess-r-devtools-ask' bound + to 'C-c C-w C-a'. It asks with completion for any devtools command + that takes 'pkg' as argument. + * ESS[R]: New command 'C-c C-e C-r' to reload the inferior process. + Currently only implemented for R. The R method runs + 'inferior-ess-r-reload-hook' on reloading. + * ESS[R]: 'ess-r-package-mode' is now activated in non-file buffers + as well. + + Bug fixes in 16.10: + * ESS[R]: Fix broken (un)flagging for debugging inside packages + * ESS[R]: Fixes (and improvements) in Package development + * ESS[R]: Completion no longer produces '...=' inside 'list( )'. + * ESS[R]: Better debugging and tracing in packages. + * ESS[R]: Better detection of symbols at point. + * ESS[R]: No more spurious warnings on deletion of temporary files. + * ESS[julia]: help and completion work (better) + * ESS[julia]: available via 'ess-remote' + + Changes and New Features in 16.04: + + * ESS[R]: 'developer' functionality has been refactored. The new + user interface consists of a single command + 'ess-r-set-evaluation-env' bound by default to 'C-c C-t C-s'. Once + an evaluation environment has been set with, all subsequent ESS + evaluation will source the code into that environment. By default, + for file within R packages the evaluation environment is set to the + package environment. Set 'ess-r-package-auto-set-evaluation-env' + to 'nil' to disable this. + * ESS[R]: New 'ess-r-package-mode' This development mode provides + features to make package development easier. Currently, most of + the commands are based on the 'devtools' packages and are + accessible with 'C-c C-w' prefix. See the documentation of + 'ess-r-package-mode' function for all available commands. With + 'C-u' prefix each command asks for extra arguments to the + underlying devtools function. This mode is automatically enabled + in all files within R packages and is indicated with '[pkg:NAME]' + in the mode-line. + * ESS[R]: Help lookup has been improved. It is now possible to get + help for namespaced objects such as pkg::foobar. Furthermore, ESS + recognizes more reliably when you change 'options('html_type')'. + * ESS[R]: New specialized breakpoints for debugging magrittr pipes + * ESS: ESS now implements a simple message passing interface to + communicate between ESS and inferior process. + + Bug fixes in 16.04: + * ESS[R]: Roxygen blocks with backtics are now correctly filled + * ESS[R]: Don't skip breakpoints in magrittr's 'debug_pipe' + * ESS[R]: Error highlighting now understands 'testthat' type errors + * ESS[Julia]: Added getwd and setwd generic commands + + +File: ess.info, Node: Credits, Next: Manual, Prev: New features, Up: Introduction + +1.3 Authors of and contributors to ESS +====================================== + +The ESS environment is built on the open-source projects of many +contributors, dating back to 1989 where Doug Bates and Ed Kademan wrote +S-mode to edit S and Splus files in GNU Emacs. Frank Ritter and Mike +Meyer added features, creating version 2. Meyer and David Smith made +further contributions, creating version 3. For version 4, David Smith +provided significant enhancements to allow for powerful process +interaction. + + John Sall wrote GNU Emacs macros for SAS source code around 1990. +Tom Cook added functions to submit jobs, review listing and log files, +and produce basic views of a dataset, thus creating a SAS-mode which was +distributed in 1994. + + In 1994, A.J. Rossini extended S-mode to support XEmacs. Together +with extensions written by Martin Maechler, this became version 4.7 and +supported S, Splus, and R. In 1995, Rossini extended SAS-mode to work +with XEmacs. + + In 1997, Rossini merged S-mode and SAS-mode into a single Emacs +package for statistical programming; the product of this marriage was +called ESS version 5. Richard M. Heiberger designed the inferior mode +for interactive SAS and SAS-mode was further integrated into ESS. Thomas +Lumley's Stata mode, written around 1996, was also folded into ESS. More +changes were made to support additional statistical languages, +particularly XLispStat. + + ESS initially worked only with Unix statistics packages that used +standard-input and standard-output for both the command-line interface +and batch processing. ESS could not communicate with statistical +packages that did not use this protocol. This changed in 1998 when +Brian Ripley demonstrated use of the Windows Dynamic Data Exchange (DDE) +protocol with ESS. Heiberger then used DDE to provide interactive +interfaces for Windows versions of Splus. In 1999, Rodney A. Sparapani +and Heiberger implemented SAS batch for ESS relying on files, rather +than standard-input/standard-output, for Unix, Windows and Mac. In +2001, Sparapani added BUGS batch file processing to ESS for Unix and +Windows. + + * The multiple process code, and the idea for + 'ess-eval-line-and-next-line' are by Rod Ball. + + * Thanks to Doug Bates for many useful suggestions. + + * Thanks to Martin Maechler for reporting and fixing bugs, providing + many useful comments and suggestions, and for maintaining the ESS + mailing lists. + + * Thanks to Frank Ritter for updates, particularly the menu code, and + invaluable comments on the manual. + + * Thanks to Ken'ichi Shibayama for his excellent indenting code, and + many comments and suggestions. + + * Thanks to Aki Vehtari for adding interactive BUGS support. + + * Thanks to Brendan Halpin for bug-fixes and updates to Stata-mode. + + * Last, but definitely not least, thanks to the many ESS users and + contributors to the ESS mailing lists. + + _ESS_ is being developed and currently maintained by + + * A.J. Rossini (mailto:blindglobe@gmail.com) + * Richard M. Heiberger (mailto:rmh@temple.edu) + * Kurt Hornik (mailto:Kurt.Hornik@R-project.org) + * Martin Maechler (mailto:maechler@stat.math.ethz.ch) + * Rodney A. Sparapani (mailto:rsparapa@mcw.edu) + * Stephen Eglen (mailto:stephen@gnu.org) + * Sebastian P. Luque (mailto:spluque@gmail.com) + * Henning Redestig (mailto:henning.red@googlemail.com) + * Vitalie Spinu (mailto:spinuvit@gmail.com) + * Lionel Henry (mailto:lionel.hry@gmail.com) + * J. Alexander Branham (mailto:alex.branham@gmail.com) + + +File: ess.info, Node: Manual, Prev: Credits, Up: Introduction + +1.4 How to read this manual +=========================== + +If you need to install ESS, read *note Installation:: for details on +what needs to be done before proceeding to the next chapter. This +section describes some of the basics of using Emacs. If you are already +familiar with basic Emacs functionality, skip this section. You may +also want to use the Emacs tutorial, accessible via 'C-h t'. + + In this manual we use the standard notation used by Emacs for +describing the keystrokes used to invoke certain commands. 'C-' +means hold the CONTROL key while typing the character . 'M-' +means hold the META key (usually ALT) down while typing . If there +is no META, EDIT or ALT key, instead press and release the ESC key and +then type . + + All ESS commands can be invoked by typing 'M-x command'. Most of the +useful commands are bound to keystrokes for ease of use. Also, the most +popular commands are also available through the Emacs menubar, and a +small subset are provided on the toolbar. Where possible, keybindings +are similar to other modes in Emacs to strive for a consistent user +interface within Emacs, regardless of the details of which programming +language is being edited, or process being run. + + Some commands, such as 'M-x R' can accept an optional 'prefix' +argument. To specify the prefix argument, you would type 'C-u' before +giving the command. For example, if you type 'C-u M-x R', you will be +asked for command line options that you wish to invoke the R process +with. + + Emacs is a 'self-documenting' text editor. This applies to ESS in +two ways. First, some documentation about each ESS command can be +obtained by typing 'C-h f'. For example, if you type 'C-h f +ess-eval-region', documentation for that command will appear in a +separate *Help* buffer. Second, 'C-h m' pops up a complete list of +keybindings available in each ESS mode and brief description of that +mode. + + Emacs is a versatile editor written in both C and a dialect of Lisp +known as Elisp. ESS is written in Elisp and benefits from the flexible +nature of lisp. In particular, many aspects of ESS behaviour can be +changed by suitable customization of Lisp variables. This manual +mentions some of the most frequent variables. A full list of them +however is available by using the Custom facility within Emacs. Type +'M-x customize-group RET ess RET' to get started. *note Customization:: +provides details of common user variables you can change to customize +ESS to your taste, but it is recommended that you defer this section +until you are more familiar with ESS. + + +File: ess.info, Node: Installation, Next: Interactive ESS, Prev: Introduction, Up: Top + +2 Installing ESS on your system +******************************* + +ESS supports GNU Emacs versions 25.1 and newer. + + ESS is most likely to work with current/recent versions of the +following statistical packages: R/S-PLUS, SAS, Stata, OpenBUGS and JAGS. + + To build the PDF documentation, you will need a version of TeX Live +or texinfo that includes texi2dvi. + + There are two main methods used for installing ESS. You may install +from a third-party repository or from source code. Once you install it, +you must also activate or load ESS in each Emacs session, though +installation from a third-party repository likely takes care of that for +you. See *note Activating and Loading ESS:: for more details. + +* Menu: + +* Installing from a third-party repository:: +* Installing from source:: +* Activating and Loading ESS:: +* Check Installation:: + + +File: ess.info, Node: Installing from a third-party repository, Next: Installing from source + +2.1 Installing from a third-party repository +============================================ + +ESS is packaged by many third party repositories. Many GNU/Linux +distributions package it, usually with the name "emacs-ess" or similar. + + ESS is also available through Milkypostman’s Emacs Lisp Package +Archive (MELPA), a popular repository for Emacs packages. Instructions +on how to do so are found on MELPA's website (https://melpa.org/). +MELPA also hosts MELPA-stable with stable ESS builds. You may choose +between MELPA with the latest and greatest features (and bugs) or +MELPA-stable, which may lag a bit behind but should be more stable. + + After installing, users should make sure ESS is activated or loaded +in each Emacs session. See *note Activating and Loading ESS::. +Depending on install method, this may be taken care of automatically. + + +File: ess.info, Node: Installing from source, Next: Activating and Loading ESS, Prev: Installing from a third-party repository + +2.2 Installing from source +========================== + +Stable versions of ESS are available at the ESS web page +(https://ess.r-project.org) as a .tgz file or .zip file. ESS releases +are GPG-signed, you should check the signature by downloading the +accompanying '.sig' file and doing: + + gpg --verify ess-18.10.tgz.sig + + Alternatively, you may download the git repository. ESS is currently +hosted on GitHub: . 'git clone +https://github.com/emacs-ess/ESS.git' will download it to a new +directory 'ESS' in the current working directory. + + We will refer to the location of the ESS source files as +'/path/to/ESS/' hereafter. + + After installing, users should make sure they activate or load ESS in +each Emacs session, see *note Activating and Loading ESS:: + + Optionally, compile Elisp files, build the documentation, and the +autoloads: + cd /path/to/ESS/ + make + Without this step the documentation, reference card, and autoloads +will not be available. Uncompiled ESS will also run slower. + + Optionally, you may make ESS available to all users of a machine by +installing it site-wide. To do so, run 'make install'. You might need +administrative privileges: + + make install + + The files are installed into '/usr/share/emacs' directory. For this +step to run correctly on macOS, you will need to adjust the 'PREFIX' +path in 'Makeconf'. The necessary code and instructions are commented +in that file. + + +File: ess.info, Node: Activating and Loading ESS, Next: Check Installation, Prev: Installing from source + +2.3 Activating and Loading ESS +============================== + +After installing ESS, you must activate or load it each Emacs session. +ESS can be autoloaded, and if you used a third-party repository (such as +your Linux distribution or MELPA) to install, you can likely skip this +section and proceed directly to *note Check Installation:: + + Otherwise, you may need to add the path to ESS to 'load-path' with: + + (add-to-list 'load-path "/path/to/ESS/lisp") + + You then need to decide whether to take advantage of deferred loading +(which will result in a faster Emacs startup time) or require ESS when +Emacs is loaded. To autoload ESS when needed (note that if installed +from source, you must have run 'make'): + + (load "ess-autoloads") + + To require ESS on startup, you can either put + + (require 'ess-site) + + or + + (require 'ess-r-mode) + + In your configuration file, depending on whether you want all ESS +features or only R related features. + + +File: ess.info, Node: Check Installation, Prev: Activating and Loading ESS + +2.4 Check Installation +====================== + +Restart Emacs and check that ESS was loaded from a correct location with +'M-x ess-version'. + + +File: ess.info, Node: Interactive ESS, Next: Entering commands, Prev: Installation, Up: Top + +3 Interacting with statistical programs +*************************************** + +As well as using ESS to edit your source files for statistical programs, +you can use ESS to run these statistical programs. In this chapter, we +mostly will refer by example to running R from within Emacs. The Emacs +convention is to name such processes running under its control as +'inferior processes'. Some users find this terminology confusing; you +may prefer to think of these as 'interactive processes.' Either way, we +use the term 'iESS' to refer to the Emacs mode used to interact with +statistical programs. + +* Menu: + +* Starting up:: +* Multiple ESS processes:: +* ESS processes on Remote Computers:: +* Customizing startup:: +* Controlling buffer display:: + + +File: ess.info, Node: Starting up, Next: Multiple ESS processes, Up: Interactive ESS + +3.1 Starting an ESS process +=========================== + +To start an inferior R session on GNU/Linux, macOS, or Windows using the +Cygwin bash shell, simply type 'M-x R RET'. To start an R session on +Windows when you use the MSDOS/powershell shell, simply type 'M-x +S+6-msdos RET'. R will then (by default) ask the question + + R starting data directory? + +Enter the name of the directory you wish to have as the working +directory (that is, the directory you wish to have 'getwd()' return if +using R). + + You will then be popped into a buffer named '*R*' which will be used +for interacting with the ESS process, and you can start entering +commands. + + +File: ess.info, Node: Multiple ESS processes, Next: ESS processes on Remote Computers, Prev: Starting up, Up: Interactive ESS + +3.2 Running more than one ESS process +===================================== + +ESS allows you to run more than one iESS process simultaneously in the +same session. Each process has a name and a number; the initial process +(process 1) is simply named 'R'. If you call 'M-x R' again without +killing the first R process, ESS will start a second R process with the +name 'R:2'. To have the first buffer named 'R:1', customize the option +'ess-plain-first-buffername'. With a prefix argument, 'C-u M-x R' +allows for the specification of command line options. + + -- User Option: ess-plain-first-buffername + If non-'nil', name the first iESS process [R]. Otherwise, name it + [R:1]. + + You can switch to any active ESS process with the command 'M-x +ess-request-a-process'. Just enter the name of the process you require; +completion is provided over the names of all running processes. This is +a good command to consider binding to a global key. + + +File: ess.info, Node: ESS processes on Remote Computers, Next: Customizing startup, Prev: Multiple ESS processes, Up: Interactive ESS + +3.3 ESS processes on Remote Computers +===================================== + +3.3.1 ESS and TRAMP +------------------- + +ESS works with processes on remote computers as easily as with processes +on the local machine. The recommended way to access a statistical +program on remote computer is to start it with *Note (tramp)Top::. + + Start an ssh session using TRAMP with 'C-x C-f /ssh:user@host: RET'. +Tramp should open a dired buffer in your remote home directory. Now +call your favorite ESS process ('R', 'Julia', 'stata' etc) as you would +usually do on local machine: 'M-x R'. + + Alternatively you can start your process normally ('M-x R'). When +asked for starting directory, simply type '/ssh:user@host: RET'. The R +process will be started on the remote machine. + + To simplify the process even further create a "config" file in your +'.ssh/' folder and add an account. For example if you use amazon EC2, +it might look like following: + + Host amazon + Hostname ec2-54-215-203-181.us-west-1.compute.amazonaws.com + User ubuntu + IdentityFile ~/.ssh/my_amazon_key.pem + ForwardX11 yes + + With this configuration '/ssh:amazon:' is enough to start a +connection. The ForwardX11 is needed if you want to see the R graphic +device showing on the current machine + +3.3.2 ESS-remote +---------------- + +TRAMP is the recommended way of starting a remote session. The other +way to start a remote ESS connection is through 'ess-remote'. + + 1. Start a new shell, telnet or ssh buffer and connect to the remote + computer (e.g. use, 'M-x shell', 'M-x telnet' or 'M-x ssh'; ssh.el + is available at + ). + + 2. Start the ESS process on the remote machine, for example with one + of the commands 'R', 'Splus', or 'sas -stdio'. + + 3. Start 'M-x ess-remote'. You will be prompted for a program name + with completion. Choose one. Your process is now known to ESS. + All the usual ESS commands ('C-c C-n' and its relatives) now work + with the R language processes. For SAS you need to use a different + command 'C-c i' (that is a regular 'i', not a 'C-i') to send lines + from your 'myfile.sas' to the remote SAS process. 'C-c i' sends + lines over invisibly. With ess-remote you get teletype + behavior--the data input, the log, and the listing all appear in + the same buffer. To make this work, you need to end every PROC and + DATA step with a "RUN;" statement. The "RUN;" statement is what + tells SAS that it should process the preceding input statements. + + 4. Graphics (interactive) on the remote machine. If you run X11 + (*Note X11::, X Windows) on both the local and remote machines then + you should be able to display the graphs locally by setting the + 'DISPLAY' environment variable appropriately. Windows users can + download 'xfree86' from cygwin. + + 5. Graphics (static) on the remote machine. If you don't run the X + window system on the local machine, then you can write graphics to + a file on the remote machine, and display the file in a graphics + viewer on the local machine. Most statistical software can write + one or more of postscript, GIF, or JPEG files. Depending on the + versions of Emacs and the operating system that you are running, + Emacs itself may display '.gif' and '.jpg' files. Otherwise, a + graphics file viewer will be needed. Ghostscript/ghostview may be + downloaded to display '.ps' and '.eps' files. Viewers for GIF and + JPEG are usually included with operating systems. *Note + ESS(SAS)--Function keys for batch processing::, for more + information on using the F12 key for displaying graphics files with + SAS. + + Should you or a colleague inadvertently start a statistical process +in an ordinary '*shell*' buffer, the 'ess-remote' command can be used to +convert it to an ESS buffer and allow you to use the ESS commands with +it. + + +File: ess.info, Node: Customizing startup, Next: Controlling buffer display, Prev: ESS processes on Remote Computers, Up: Interactive ESS + +3.4 Changing the startup actions +================================ + +If you do not wish ESS to prompt for a starting directory when starting +a new process, set the variable 'ess-ask-for-ess-directory' to 'nil'. +In this case, the starting directory will be set using one of the +following methods: + + 1. If the variable 'ess-directory-function' stores the name of a + function, the value returned by this function is used. The default + for this variable is nil. + + 2. Otherwise, if the variable 'ess-directory' stores the name of a + directory (ending in a slash), this value is used. The default for + this variable is nil. + + 3. Otherwise, the working directory of the current buffer is used. + + If 'ess-ask-for-ess-directory' has a non-'nil' value (as it does by +default) then the value determined by the above rules provides the +default when prompting for the starting directory. Incidentally, +'ess-directory' is an ideal variable to set in 'ess-pre-run-hook'. + + You may also customize 'ess-post-run-hook' and the dialect-specific +'ess-*-post-run-hook' variables. For example, you may want to use +'ess-load-file' to load a file when ESS starts R: + + (add-hook 'ess-r-post-run-hook (lambda () (ess-load-file "foo.R"))) + + If you like to keep a record of your R actions, set the variable +'ess-ask-about-transfile' to 't', and you will be asked for a filename +for the transcript before the ESS process starts. + + -- User Option: ess-ask-about-transfile + If non-'nil', ask for a file name in which to save the session + transcript. + + Enter the name of a file in which to save the transcript at the +prompt. If the file doesn't exist it will be created (for R, you likely +want it to end in '.Rout'). If the file already exists the transcript +will be appended to the file. (Note: if you don't set this variable but +you still want to save the transcript, you can still do it later -- +*note Saving transcripts::.) + + Once these questions are answered (if they are asked at all) the +inferior process itself is started. If you need to pass any arguments +to this program, they may be specified in the variable +'inferior-S_PROGRAM_NAME-args'. For example, if 'inferior-ess-program' +is '"R"' then the variable to set is 'inferior-R-args'. It is not +normally necessary to pass arguments to the iESS program; in particular +do not pass the '-e' option to 'Splus', since ESS provides its own +command history mechanism. + + ESS can set the width option of inferior processes automatically when +the window configuration changes. To do so, set 'ess-auto-width' to a +non-nil value. By default, the change will not be shown in the inferior +buffer. If you want it to be shown, set 'ess-auto-width-visible' to a +non-nil value. + + +File: ess.info, Node: Controlling buffer display, Prev: Customizing startup, Up: Interactive ESS + +3.5 Controlling buffer display +============================== + +Users can control how buffers are displayed by customizing +'display-buffer-alist', *Note (emacs)Window Choice::. This section +provides examples of how to achieve certain setups. + + Users coming from RStudio may want the R process to appear at the +bottom left of the frame, help buffers to appear at the bottom right, +and ess-rdired buffers at the top right. To achieve that, you could +this. Note that the order matters; '*R Dired*' would match '*R' if it +came before in the alist. + + (setq display-buffer-alist + `(("^\\*R Dired" + (display-buffer-reuse-window display-buffer-in-side-window) + (side . right) + (slot . -1) + (window-width . 0.33) + (reusable-frames . nil)) + ("^\\*R" + (display-buffer-reuse-window display-buffer-at-bottom) + (window-width . 0.5) + (reusable-frames . nil)) + ("^\\*Help" + (display-buffer-reuse-window display-buffer-in-side-window) + (side . right) + (slot . 1) + (window-width . 0.33) + (reusable-frames . nil)))) + + Some users prefer working with multiple frames where one frame has +the source code and the other frame has the inferior process. To +achieve this, use this example. For a detailed description of +'reusable-frames', see *Note (elisp)Buffer Display Action Alists::. + + (setq display-buffer-alist + '(("^\\*R" + (display-buffer-reuse-window display-buffer-pop-up-frame) + (reusable-frames . 0)))) + + Some users may want the process window to be dedicated to the process +so that other buffers are not shown on top of that window. *Note +(elisp)Dedicated Windows::. For example, this prevents help buffers +from being displayed in the window showing the inferior R process. + + (setq display-buffer-alist + '(("^\\*R" + nil + (dedicated . t)))) + + By default, ESS usually prefers splitting the frame into multiple +windows so that you can work with both the R script and the R REPL +visible at once. If you want to override this behavior so that the +script buffer and the process buffer share the same window, you can do +so like this: + + (setq display-buffer-alist + '(("^\\*R" . ((display-buffer-same-window) (inhibit-same-window . nil))) + ("\\.R$" . ((display-buffer-same-window) (inhibit-same-window . nil))))) + + +File: ess.info, Node: Entering commands, Next: Evaluating code, Prev: Interactive ESS, Up: Top + +4 Interacting with the ESS process +********************************** + +The primary function of the ESS package is to provide an easy-to-use +front end to the R interpreter. This is achieved by running the R +process from within an Emacs buffer, called hereafter _inferior_ buffer, +which has an active 'inferior-ess-mode'. The features of inferior R +mode are similar to those provided by the standard Emacs shell mode +(*note (emacs)Shell Mode::). Command-line completion of R objects and a +number of 'hot keys' for commonly-used R commands are also provided for +ease of typing. + +* Menu: + +* Command-line editing:: Entering commands and fixing mistakes +* Transcript:: Manipulating the transcript +* Command History:: Command History +* History expansion:: References to historical commands +* Hot keys:: Hot keys for common commands +* Statistical Process running in ESS?:: +* Emacsclient:: Using emacsclient +* Other:: Other commands provided by inferior-ESS + + +File: ess.info, Node: Command-line editing, Next: Transcript, Up: Entering commands + +4.1 Entering commands and fixing mistakes +========================================= + +Sending a command to the ESS process is as simple as typing it in and +pressing the key: + + -- Command: inferior-ess-send-input + 'RET' Send the command on the current line to the ESS process. + + If you make a typing error before pressing 'RET' all the usual Emacs +editing commands are available to correct it (*note Basic: +(emacs)Basic.). Once the command has been corrected you can press + (even if the cursor is not at the end of the line) to send the +corrected command to the ESS process. + + Emacs provides some other commands which are useful for fixing +mistakes: + +'C-c C-w' + 'backward-kill-word' Deletes the previous word (such as an object + name) on the command line. + +'C-c C-u' + 'comint-kill-input' Deletes everything from the prompt to point. + Use this to abandon a command you have not yet sent to the ESS + process. + +'C-a' + 'comint-bol' Move to the beginning of the line, and then skip + forwards past the prompt, if any. + + *Note (emacs)Shell Mode::, for other commands relevant to entering +input. + + +File: ess.info, Node: Transcript, Next: Command History, Prev: Command-line editing, Up: Entering commands + +4.2 Manipulating the transcript +=============================== + +Most of the time, the cursor spends its time at the bottom of the ESS +process buffer, entering commands. However all the input and output +from the current (and previous) ESS sessions is stored in the process +buffer (we call this the transcript) and often we want to move back up +through the buffer, to look at the output from previous commands for +example. + + Within the process buffer, a paragraph is defined as the prompt, the +command after the prompt, and the output from the command. Thus 'M-{' +and 'M-}' move you backwards and forwards, respectively, through +commands in the transcript. A particularly useful command is 'M-h' +('mark-paragraph') which will allow you to mark a command and its entire +output (for deletion, perhaps). For more information about paragraph +commands, *note Paragraphs: (emacs)Paragraphs. + + If an ESS process finishes and you restart it in the same process +buffer, the output from the new ESS process appears after the output +from the first ESS process separated by a form-feed ('^L') character. +Thus pages in the ESS process buffer correspond to ESS sessions. Thus, +for example, you may use 'C-x [' and 'C-x ]' to move backward and +forwards through ESS sessions in a single ESS process buffer. For more +information about page commands, *note Pages: (emacs)Pages. + +* Menu: + +* Last command:: Manipulating the output from the last command +* Process buffer motion:: Viewing older commands +* Transcript resubmit:: Re-submitting commands from the transcript +* Saving transcripts:: Keeping a record of your R session + + +File: ess.info, Node: Last command, Next: Process buffer motion, Up: Transcript + +4.2.1 Manipulating the output from the last command +--------------------------------------------------- + +Viewing the output of the command you have just entered is a common +occurrence and ESS provides a number of facilities for doing this. +Whenever a command produces output, it is possible that the window will +scroll, leaving the next prompt near the middle of the window. The +first part of the command output may have scrolled off the top of the +window, even though the entire output would fit in the window if the +prompt were near the bottom of the window. If this happens, you can use +the following comint commands: + + 'comint-show-maximum-output' to move to the end of the buffer, and +place cursor on bottom line of window to make more of the last output +visible. To make this happen automatically for all inputs, set the +variable 'comint-scroll-to-bottom-on-input' to 't' or ''this'. If the +first part of the output is still not visible, use 'C-c C-r' +('comint-show-output'), which moves cursor to the previous command line +and places it at the top of the window. + + Finally, if you want to discard the last command output altogether, +use 'C-c C-o' ('comint-delete-output'), which deletes everything from +the last command to the current prompt. Use this command judiciously to +keep your transcript to a more manageable size. + + +File: ess.info, Node: Process buffer motion, Next: Transcript resubmit, Prev: Last command, Up: Transcript + +4.2.2 Viewing older commands +---------------------------- + +If you want to view the output from more historic commands than the +previous command, commands are also provided to move backwards and +forwards through previously entered commands in the process buffer: + +'C-c C-p' + 'comint-previous-prompt' Moves point to the preceding prompt in the + process buffer. + +'C-c C-n' + 'comint-next-prompt' Moves point to the next prompt in the process + buffer. + +Note that these two commands are analogous to 'C-p' and 'C-n' but apply +to command lines rather than text lines. And just like 'C-p' and 'C-n', +passing a prefix argument to these commands means to move to the ARG'th +next (or previous) command. (These commands are also discussed in *note +Shell History Copying: (emacs)Shell History Copying.) + + There are also two similar commands (not bound to any keys by +default) which move to preceding or succeeding commands, but which first +prompt for a regular expression (*note Syntax of Regular Expression: +(emacs)Regexps.), and then moves to the next (previous) command matching +the pattern. + +'comint-backward-matching-input regexp arg' +'comint-forward-matching-input regexp arg' + Search backward (forward) through the transcript buffer for the + ARG'th previous (next) command matching REGEXP. ARG is the prefix + argument; REGEXP is prompted for in the minibuffer. + + +File: ess.info, Node: Transcript resubmit, Next: Saving transcripts, Prev: Process buffer motion, Up: Transcript + +4.2.3 Re-submitting commands from the transcript +------------------------------------------------ + +When moving through the transcript, you may wish to re-execute some of +the commands you find there. ESS provides commands to do this; these +commands may be used whenever the cursor is within a command line in the +transcript (if the cursor is within some command _output_, an error is +signaled). Note all commands involve the key. + +'RET' + 'inferior-ess-send-input' *Note Command-line editing::. + +'C-c RET' + 'comint-copy-old-input' Copy the command under the cursor to the + current command line, but don't execute it. Leaves the cursor on + the command line so that the copied command may be edited. + + When the cursor is not after the current prompt, the key has +a slightly different behavior than usual. Pressing 'RET' on any line +containing a command that you entered (i.e. a line beginning with a +prompt) sends that command to the ESS process once again. If you wish +to edit the command before executing it, use 'C-c RET' instead; it +copies the command to the current prompt but does not execute it, +allowing you to edit it before (re)submitting it. + + These commands work even if the current line is a continuation line +(i.e. the prompt is '+' instead of '>') -- in this case all the lines +that form the multi-line command are concatenated together and the +resulting command is sent to the ESS process (currently this is the only +way to resubmit a multi-line command to the ESS process in one go). If +the current line does not begin with a prompt, an error is signalled. +This feature, coupled with the command-based motion commands described +above, could be used as a primitive history mechanism. ESS provides a +more sophisticated mechanism, however, which is described in *note +Command History::. + + +File: ess.info, Node: Saving transcripts, Prev: Transcript resubmit, Up: Transcript + +4.2.4 Keeping a record of your R session +---------------------------------------- + +To keep a record of your R session in a disk file, use the Emacs command +'C-x C-w' ('write-file') to attach a file to the ESS process buffer. +The name of the process buffer will (probably) change to the name of the +file, but this is not a problem. You can still use R as usual; just +remember to save the file before you quit Emacs with 'C-x C-s'. You can +make ESS prompt you for a filename in which to save the transcript every +time you start R by setting the variable 'ess-ask-about-transfile' to +'t'; *Note Customizing startup::. For R files, naming transcript files +'*.Rout' puts them in a special mode (ESS transcript mode -- *note +Transcript Mode::) for editing transcript files which is automatically +selected for files with this suffix. + + R transcripts can get very large, so some judicious editing is +appropriate if you are saving it in a file. Use 'C-c C-o' whenever a +command produces excessively long output (printing large arrays, for +example). Delete erroneous commands (and the resulting error messages +or other output) by moving to the command (or its output) and typing +'M-h C-w'. Also, remember that 'C-c C-x' (and other hot keys) may be +used for commands whose output you do not wish to appear in the +transcript. These suggestions are appropriate even if you are not +saving your transcript to disk, since the larger the transcript, the +more memory your Emacs process will use on the host machine. + + You can use 'ess-transcript-clean-region' to strip output from a +transcript, leaving only source code suitable for inclusion in files +'source()'-able from R. *note Transcript Mode: Clean. + + +File: ess.info, Node: Command History, Next: History expansion, Prev: Transcript, Up: Entering commands + +4.3 Command History +=================== + +ESS provides easy-to-use facilities for re-executing or editing previous +commands. An input history of the last few commands is maintained (by +default the last 500 commands are stored, although this can be changed +by setting the variable 'comint-input-ring-size' in +'inferior-ess-mode-hook'.) The simplest history commands simply select +the next and previous commands in the input history: + +'M-p' + 'comint-previous-input' Select the previous command in the input + history. + +'M-n' + 'comint-next-input' Select the next command in the input history. + +For example, pressing 'M-p' once will re-enter the last command into the +process buffer after the prompt but does not send it to the ESS process, +thus allowing editing or correction of the command before the ESS +process sees it. Once corrections have been made, press 'RET' to send +the edited command to the ESS process. + + If you want to select a particular command from the history by +matching it against a regular expression (*note Syntax of Regular +Expression: (emacs)Regexps.), to search for a particular variable name +for example, these commands are also available: + +'M-r' + 'comint-history-isearch-backward-regexp' Prompt for a regular + expression, and search backwards through the input history for a + command matching the expression. + +A common type of search is to find the last command that began with a +particular sequence of characters; the following two commands provide an +easy way to do this: + +'C-c M-r' + 'comint-previous-matching-input-from-input' Select the previous + command in the history which matches the string typed so far. + +'C-c M-s' + 'comint-next-matching-input-from-input' Select the next command in + the history which matches the string typed so far. + +Instead of prompting for a regular expression to match against, as they +instead select commands starting with those characters already entered. +For instance, if you wanted to re-execute the last 'attach()' command, +you may only need to type 'att' and then 'C-c M-r' and 'RET'. + + *Note Shell History Ring: (emacs)Shell Ring, for a more detailed +discussion of the history mechanism, and do experiment with the 'In/Out' +menu to explore the possibilities. + + Many ESS users like to have even easier access to these, and +recommend adding something like + (eval-after-load "comint" + '(progn + (define-key comint-mode-map [up] + 'comint-previous-matching-input-from-input) + (define-key comint-mode-map [down] + 'comint-next-matching-input-from-input) + + ;; also recommended for ESS use -- + (setq comint-move-point-for-output 'others) + ;; somewhat extreme, almost disabling writing in *R*, *shell* buffers above prompt: + (setq comint-scroll-to-bottom-on-input 'this) + )) + to your Emacs configuration file, where the last two settings are +typically desirable for the situation where you work with a script (for +example, 'code.R') and send code chunks to the process buffer (e.g. +'*R*'). Note however that these settings influence all 'comint'-using +Emacs modes, not just the ESS ones, and for that reason, these +customization cannot be part of 'ESS' itself. + +* Menu: + +* Saving History:: + + +File: ess.info, Node: Saving History, Up: Command History + +4.3.1 Saving the command history +-------------------------------- + +The 'ess-history-file' variable, which is 't' by default, together with +'ess-history-directory', governs if and where the command history is +saved and restored between sessions. By default, +'ess-history-directory' is 'nil', and the command history will be stored +(as a file) in the same directory as the iESS process. + + ESS users may work exclusively with script files rather than in a +iESS session, and may not want to save any history files. To do so: + + (setq ess-history-file nil) + +or if you prefer only one global command history file: + + (setq ess-history-directory "~/.R/") + +in your Emacs configuration file. + + +File: ess.info, Node: History expansion, Next: Hot keys, Prev: Command History, Up: Entering commands + +4.4 References to historical commands +===================================== + +Instead of searching through the command history using the command +described in the previous section, you can alternatively refer to a +historical command directly using a notation very similar to that used +in 'csh'. History references are introduced by a '!' or '^' character +and have meanings as follows: + +'!!' + The immediately previous command + +'!-N' + The Nth previous command + +'!text' + The last command beginning with the string 'text' + +'!?text' + The last command containing the string 'text' + + In addition, you may follow the reference with a "word designator" to +select particular "words" of the input. A word is defined as a sequence +of characters separated by whitespace. (You can modify this definition +by setting the value of 'comint-delimiter-argument-list' to a list of +characters that are allowed to separate words and themselves form +words.) Words are numbered beginning with zero. The word designator +usually begins with a ':' (colon) character; however it may be omitted +if the word reference begins with a '^', '$', '*' or '-'. If the word +is to be selected from the previous command, the second '!' character +can be omitted from the event specification. For instance, '!!:1' and +'!:1' both refer to the first word of the previous command, while '!!$' +and '!$' both refer to the last word in the previous command. The +format of word designators is as follows: + +'0' + The zeroth word (i.e. the first one on the command line) + +'N' + The Nth word, where N is a number + +'^' + The first word (i.e. the second one on the command line) + +'$' + The last word + +'X-Y' + A range of words; '-Y' abbreviates '0-Y' + +'*' + All the words except the zeroth word, or nothing if the command had + just one word (the zeroth) + +'X*' + Abbreviates X-$ + +'X-' + Like 'X*', but omitting the last word + + In addition, you may surround the entire reference except for the +first '!' by braces to allow it to be followed by other (non-whitespace) +characters (which will be appended to the expanded reference). + + Finally, ESS also provides quick substitution; a reference like +'^old^new^' means "the last command, but with the first occurrence of +the string 'old' replaced with the string 'new'" (the last '^' is +optional). Similarly, '^old^' means "the last command, with the first +occurrence of the string 'old' deleted" (again, the last '^' is +optional). + + To convert a history reference as described above to an input +suitable for R, you need to "expand" the history reference, using the + key. For this to work, the cursor must be preceded by a space +(otherwise it would try to complete an object name) and not be within a +string (otherwise it would try to complete a filename). So to expand +the history reference, type 'SPC TAB'. This will convert the history +reference into an R command from the history, which you can then edit or +press to execute. + + For example, to execute the last command that referenced the variable +'data', type '!?data SPC TAB RET'. + + +File: ess.info, Node: Hot keys, Next: Statistical Process running in ESS?, Prev: History expansion, Up: Entering commands + +4.5 Hot keys for common commands +================================ + +ESS provides a number of commands for executing the commonly used +functions. These commands below are basically information-gaining +commands (such as 'objects()' or 'search()') which tend to clutter up +your transcript and for this reason some of the hot keys display their +output in a temporary buffer instead of the process buffer by default. +This behavior is controlled by the following option: + + -- User Option: ess-execute-in-process-buffer + If non-'nil', means that these commands will produce their output + in the process buffer instead. + + In any case, passing a prefix argument to the commands (with 'C-u') +will reverse the meaning of 'ess-execute-in-process-buffer' for that +command. In other words, the output will be displayed in the process +buffer if it usually goes to a temporary buffer, and vice-versa. These +are the hot keys that behave in this way: + + -- Command: ess-execute-objects POSN + 'C-c C-x' Sends the 'objects()' command to the ESS process. A + prefix argument specifies the position on the search list (use a + negative argument to toggle 'ess-execute-in-process-buffer' as + well). This is a quick way to see what objects are in your working + directory. A prefix argument of 2 or more means get objects for + that position. A negative prefix argument POSN gets the objects + for that position, as well as toggling + 'ess-execute-in-process-buffer'. + + -- Command: ess-execute-search INVERT + 'C-c C-s' Sends the 'inferior-ess-search-list-command' command to + the 'ess-language' process; 'search()' in R. Prefix INVERT toggles + 'ess-execute-in-process-buffer'. + + 'ess-execute' may seem pointless when you could just type the command +in anyway, but it proves useful for 'spot' calculations which would +otherwise clutter your transcript, or for evaluating an expression while +partway through entering a command. You can also use this command to +generate new hot keys using the Emacs keyboard macro facilities; *note +Keyboard Macros: (emacs)Keyboard Macros. + + The following hot keys do not use 'ess-execute-in-process-buffer' to +decide where to display the output -- they either always display in the +process buffer or in a separate buffer, as indicated: + + -- Command: ess-load-file FILENAME + 'C-c M-l' Prompts for a file (FILENAME) to load into the ESS + process using 'source()'. If there is an error during loading, you + can jump to the error in the file with the following function. + + -- Command: ess-parse-errors ARG RESET + Visits next 'next-error' message and corresponding source code. If + all the error messages parsed so far have been processed already, + the message buffer is checked for new ones. A prefix ARG specifies + how many error messages to move; negative means move back to + previous error messages. Just 'C-u' as a prefix means reparse the + error message buffer and start at the first error. The RESET + argument specifies restarting from the beginning. + + *Note Error Checking::, for more details. + + -- Command: ess-display-help-on-object OBJECT COMMAND + 'C-c C-v' Pops up a help buffer for an R object or function. If + COMMAND is supplied, it is used instead of + 'inferior-ess-help-command'. See *note Help:: for more details. + + -- Command: ess-quit + 'C-c C-q' Issue an exiting command to the inferior process, + additionally also running 'ess-cleanup' for disposing of any + temporary buffers (such as help buffers and edit buffers) that may + have been created. Use this command when you have finished your R + session instead of simply quitting at the inferior process prompt, + otherwise you will need to issue the command 'ess-cleanup' + explicitly to make sure that all the files that need to be saved + have been saved, and that all the temporary buffers have been + killed. + + +File: ess.info, Node: Statistical Process running in ESS?, Next: Emacsclient, Prev: Hot keys, Up: Entering commands + +4.6 Is the Statistical Process running under ESS? +================================================= + +For the R languages (R, S, S-Plus) ESS sets an option in the current +process that programs in the language can check to determine the +environment in which they are currently running. + + ESS sets 'options(STERM="iESS")' for R language processes running in +an inferior 'iESS[S]' or 'iESS[R]' buffer. + + ESS sets 'options(STERM="ddeESS")' for independent S-Plus for Windows +processes running in the GUI and communicating with ESS via the DDE +(Microsoft Dynamic Data Exchange) protocol through a 'ddeESS[S]' buffer. + + Other values of 'options()$STERM' that we recommend are: + + * 'length': Fixed length xterm or telnet window. + * 'scrollable': Unlimited length xterm or telnet window. + * 'server': S-Plus Stat Server. + * 'BATCH': BATCH. + * 'Rgui': R GUI. + * 'Commands': S-Plus GUI without DDE interface to ESS. + + Additional values may be recommended in the future as new interaction +protocols are created. Unlike the values 'iESS' and 'ddeESS', ESS can't +set these other values since the R language program is not under the +control of ESS. + + +File: ess.info, Node: Emacsclient, Next: Other, Prev: Statistical Process running in ESS?, Up: Entering commands + +4.7 Using emacsclient +===================== + +When starting R or S under Unix, ESS sets +'options(editor="emacsclient")'. Under Microsoft Windows, it will use +gnuclient.exe rather than emacsclient, but the same principal applies. +Within your R session, if you have a function called 'iterator', typing +'fix(iterator)', will show that function in a temporary Emacs buffer. +You can then correct the function. When you kill the buffer, the +definition of the function is updated. Using 'edit()' rather than +'fix()' means that the function is not updated. Finally, the R function +'page(x)' will also show a text representation of the object 'x' in a +temporary Emacs buffer. + + +File: ess.info, Node: Other, Prev: Emacsclient, Up: Entering commands + +4.8 Other commands provided by inferior-ESS +=========================================== + +The following commands are also available in the process buffer: + + -- Command: comint-interrupt-subjob + 'C-c C-c' Sends a Control-C signal to the iESS process. This has + the effect of aborting the current command. + + -- Command: ess-switch-to-inferior-or-script-buffer TOGGLE-EOB + 'C-c C-z' When in process buffer, return to the most recent script + buffer. When in a script buffer pop to the associated process + buffer. Consecutive presses of 'C-z' switch between the script and + process buffers. + + If TOGGLE-EOB is given, the value of + 'ess-switch-to-end-of-proc-buffer' is toggled. + + -- User Option: ess-switch-to-end-of-proc-buffer + If non-'nil', 'ess-switch-to-inferior-or-script-buffer' goes to end + of process buffer. + + Other commands available in iESS modes are discussed in *note +(emacs)Shell Mode::. + + +File: ess.info, Node: Evaluating code, Next: Transcript Mode, Prev: Entering commands, Up: Top + +5 Sending code to the ESS process +********************************* + +Other commands are also available for evaluating portions of code in the +R process. These commands cause the selected code to be evaluated +directly by the ESS process as if you had typed them in at the command +line; the 'source()' function is not used. You may choose whether both +the commands and their output appear in the process buffer (as if you +had typed in the commands yourself) or if the output alone is echoed. +The behavior is controlled by the variable: + + -- User Option: ess-eval-visibly + Non-'nil' means 'ess-eval-*' commands display commands and output + in the process buffer. A value of 't' blocks Emacs while R is + busy. A value of 'nowait' does not block Emacs but printing may be + slightly off. + + Passing a prefix ('C-u') (in Elisp terms, the argument VIS) to any of +the following commands, however, reverses the meaning of +'ess-eval-visibly' for that command only -- for example 'C-u C-c C-j' +evaluates the current line without showing the input in the iESS buffer. +The default value of 'ess-eval-visibly' ('t') means that ESS calls block +Emacs until they finish. This may be undesirable, especially if +commands take long to finish. Users who want input to be displayed and +Emacs not to be blocked can set 'ess-eval-visibly' to ''nowait'. This +sends the input to the iESS buffer but does not wait for the process to +finish, ensuring Emacs is not blocked. + + Primary commands for evaluating code are: + + -- Command: ess-eval-region-or-line-and-step VIS + 'C-' Sends the highlighted region or current line and step to + next line of code. + + -- Command: ess-eval-region-or-function-or-paragraph VIS + 'C-M-x' Sends the current selected region or function or paragraph. + + -- Command: ess-eval-region-or-function-or-paragraph-and-step VIS + 'C-c C-c' Like 'ess-eval-region-or-function-or-paragraph' but steps + to next line of code. + + Other, not so often used, evaluation commands are: + + -- Command: ess-eval-line VIS + 'C-c C-j' Sends the current line to the ESS process. + + -- Command: ess-eval-line-and-go VIS + 'C-c M-j' Like 'ess-eval-line' but additionally switches point to + the ESS process. + + -- Command: ess-eval-function VIS NO-ERROR + 'C-c C-f' Sends the function containing point to the ESS process. + + -- Command: ess-eval-function-and-go VIS + 'C-c M-f' Like 'ess-eval-function' but additionally switches point + to the ESS process. + + -- Command: ess-eval-region START END TOGGLE MESSAGE + 'C-c C-r' Sends the current region to the ESS process. + + -- Command: ess-eval-region-and-go START END VIS + 'C-c M-r' Like 'ess-eval-region' but additionally switches point to + the ESS process. + + -- Command: ess-eval-buffer VIS + 'C-c C-b' Sends the current buffer to the ESS process. + + -- Command: ess-eval-buffer-and-go VIS + 'C-c M-b' Like 'ess-eval-buffer' but additionally switches point to + the ESS process. + + All the above 'ess-eval-*' commands are useful for evaluating small +amounts of code and observing the results in the process buffer for +debugging purposes, or for generating transcripts from source files. +When editing R functions, it is generally preferable to use 'C-c C-l' to +update the function's value. In particular, 'ess-eval-buffer' is now +largely obsolete. + + A useful way to work is to divide the frame into two windows; one +containing the source code and the other containing the process buffer. +If you wish to make the process buffer scroll automatically when the +output reaches the bottom of the window, you will need to set the +variable 'comint-move-point-for-output' to ''others' or 't'. + + +File: ess.info, Node: Transcript Mode, Next: Editing objects, Prev: Evaluating code, Up: Top + +6 Manipulating saved transcript files +************************************* + +Inferior R mode records the transcript (the list of all commands +executed, and their output) in the process buffer, which can be saved as +a "transcript file", which should normally have the suffix '.Rout'. The +most obvious use for a transcript file is as a static record of the +actions you have performed in a particular R session. Sometimes, +however, you may wish to re-execute commands recorded in the transcript +file by submitting them to a running ESS process. This is what +Transcript Mode is for. + + If you load file a with the suffix '.Rout' into Emacs, it is placed +in R Transcript Mode. Transcript Mode is similar to inferior R mode +(*note Entering commands::): paragraphs are defined as a command and its +output, and you can move though commands either with the paragraph +commands or with 'C-c C-p' and 'C-c C-n'. + +* Menu: + +* Resubmit:: Resubmitting commands from the transcript file +* Clean:: Cleaning transcript files + + +File: ess.info, Node: Resubmit, Next: Clean, Up: Transcript Mode + +6.1 Resubmitting commands from the transcript file +================================================== + +Three commands are provided to re-submit command lines from the +transcript file to a running ESS process. They are: + + -- Command: ess-transcript-send-command + 'M-RET' Sends the current command line to the ESS process, and + execute it. + + -- Command: ess-transcript-copy-command + 'C-c RET' Copy the current command to the ESS process, and switch + to it (ready to edit the copied command). + + -- Command: ess-transcript-send-command-and-move + 'RET' Sends the current command to the ESS process, and move to the + next command line. This command is useful for submitting a series + of commands. + +Note that the first two commands are similar to those on the same keys +in inferior R Mode. In all three cases, the commands should be executed +when the cursor is on a command line in the transcript; the prompt is +automatically removed before the command is submitted. + + +File: ess.info, Node: Clean, Prev: Resubmit, Up: Transcript Mode + +6.2 Cleaning transcript files +============================= + +Yet another use for transcript files is to extract the command lines for +inclusion in an R source file or function. Transcript mode provides one +command which does just this: + + -- Command: ess-transcript-clean-region BEG END EVEN-IF-READ-ONLY + 'C-c C-w' Strip the transcript in the region (given by BEG and + END), leaving only commands. Deletes any lines not beginning with + a prompt, and then removes the prompt from those lines that remain. + Prefix argument EVEN-IF-READ-ONLY means to clean even if the buffer + is read-only. Don't forget to remove any erroneous commands first! + +The remaining command lines may then be copied to a source file or edit +buffer for inclusion in a function definition, or may be evaluated +directly (*note Evaluating code::) using the code evaluation commands +from R mode, also available in R Transcript Mode. + + +File: ess.info, Node: Editing objects, Next: Help, Prev: Transcript Mode, Up: Top + +7 Editing objects and functions +******************************* + +ESS provides facilities for editing R objects within your Emacs session. +Most editing is performed on R functions, although in theory you may +edit datasets as well. Edit buffers are always associated with files, +although you may choose to make these files temporary if you wish. +Alternatively, you may make use of a simple yet powerful mechanism for +maintaining backups of text representations of R functions. +Error-checking is performed when R code is loaded into the ESS process. + +* Menu: + +* Edit buffer:: Edit objects in a specialized buffer +* Loading:: Loading source files into the ESS process +* Error Checking:: Detecting errors in source files +* Indenting:: Indenting and formatting S code +* Other edit buffer commands:: Commands for motion, completion and more +* Source Files:: Maintaining R source files +* Source Directories:: Names and locations of dump files + + +File: ess.info, Node: Edit buffer, Next: Loading, Up: Editing objects + +7.1 Creating or modifying R objects +=================================== + +To edit an object, type + + -- Command: ess-dump-object-into-edit-buffer OBJECT + 'C-c C-e C-d' Edit an object in its own edit buffer. + + from within the iESS process buffer ('*R*'). You will then be +prompted for an object to edit: you may either type in the name of an +existing object (for which completion is available using the 'TAB' key), +or you may enter the name of a new object. A buffer will be created +containing the text representation of the requested object or, if you +entered the name of a non-existent object at the prompt and the variable +'ess-function-template' is non-'nil', you will be presented with a +template defined by that variable, which defaults to a skeleton function +construct. + + You may then edit the function as required. The edit buffer +generated by 'ess-dump-object-into-edit-buffer' is placed in the 'ESS' +major mode which provides a number of commands to facilitate editing R +source code. Commands are provided to intelligently indent R code, +evaluate portions of R code and to move around R code constructs. + + Note: when you dump a file with 'C-c C-e C-d', ESS first checks to +see whether there already exists an edit buffer containing that object +and, if so, pops you directly to that buffer. If not, ESS next checks +whether there is a file in the appropriate place with the appropriate +name (*note Source Files::) and if so, reads in that file. You can use +this facility to return to an object you were editing in a previous +session (and which possibly was never loaded to the R session). +Finally, if both these tests fail, the ESS process is consulted and a +'dump()' command issued. If you want to force ESS to ask the ESS +process for the object's definition (say, to reformat an unmodified +buffer or to revert back to R's idea of the object's definition) pass a +prefix argument to 'ess-dump-object-into-edit-buffer' by typing 'C-u C-c +C-e C-d'. + + +File: ess.info, Node: Loading, Next: Error Checking, Prev: Edit buffer, Up: Editing objects + +7.2 Loading source files into the ESS process +============================================= + +The best way to get information -- particularly function definitions -- +into R is to load them in as source file, using R's 'source' function. +You have already seen how to create source files using 'C-c C-e C-d'; +ESS provides a complementary command for loading source files (even +files not created with ESS!) into the ESS process, namely +'ess-load-file' ('C-c M-l'). *note Hot keys::. + +After typing 'C-c M-l' you will prompt for the name of the file to load +into R; usually this is the current buffer's file which is the default +value (selected by simply pressing 'RET' at the prompt). You will be +asked to save the buffer first if it has been modified (this happens +automatically if the buffer was generated with 'C-c C-e C-d'). The file +will then be loaded, and if it loads successfully you will be returned +to the ESS process. + + +File: ess.info, Node: Error Checking, Next: Indenting, Prev: Loading, Up: Editing objects + +7.3 Detecting errors in source files +==================================== + +If any errors occur when loading a file with 'C-c C-l', ESS will inform +you of this fact. In this case, you can jump directly to the line in +the source file which caused the error by typing 'C-c `' +('ess-parse-errors'). You will be returned to the offending file +(loading it into a buffer if necessary) with point at the line S +reported as containing the error. You may then correct the error, and +reload the file. Note that none of the commands in an R source file +will take effect if any part of the file contains errors. + + Sometimes the error is not caused by a syntax error (loading a +non-existent file for example). In this case typing 'C-c `' will simply +display a buffer containing S's error message. You can force this +behavior (and avoid jumping to the file when there _is_ a syntax error) +by passing a prefix argument to 'ess-parse-errors' with 'C-u C-c `'. + + +File: ess.info, Node: Indenting, Next: Other edit buffer commands, Prev: Error Checking, Up: Editing objects + +7.4 Indenting and formatting R code +=================================== + +ESS provides a sophisticated mechanism for indenting R source code. +Compound statements (delimited by '{' and '}') are indented relative to +their enclosing block. In addition, the braces have been electrified to +automatically indent to the correct position when inserted, and +optionally insert a newline at the appropriate place as well. Lines +which continue an incomplete expression are indented relative to the +first line of the expression. Function definitions, 'if' statements, +calls to 'expression()' and loop constructs are all recognized and +indented appropriately. User variables are provided to control the +amount of indentation in each case, and there are also a number of +predefined indentation styles to choose from. + + Comments are also handled specially by ESS, using an idea borrowed +from the Emacs-Lisp indentation style. By default, comments beginning +with '###' are aligned to the beginning of the line. Comments beginning +with '##' are aligned to the current level of indentation for the block +containing the comment. Finally, comments beginning with '#' are +aligned to a column on the right (the 40th column by default, but this +value is controlled by the variable 'comment-column',) or just after the +expression on the line containing the comment if it extends beyond the +indentation column. You turn off the default behavior by adding the +line '(setq ess-indent-with-fancy-comments nil)' to your '.emacs' file. + + ESS also supports roxygen2 entries which is R documentation +maintained in the source code as comments *Note roxygen2::. + + The indentation commands provided by ESS are: + + -- Command: ess-indent-or-complete + 'TAB' Indents the current line as R code. + + Try to indent first, and if code is already properly indented, + complete instead. In ess-mode, only tries completion if + 'tab-always-indent' is ''complete'. See also + 'ess-first-tab-never-complete'. + + -- User Option: ess-first-tab-never-complete + If non-'nil', 'TAB' never tries to complete in ess-mode. The + default ''symbol' does not try to complete if the next char is a + valid symbol constituent. There are more options, see the help + ('C-h v'). + + -- Command: ess-indent-exp + 'TAB' Indents each line in the R (compound) expression which + follows point. Very useful for beautifying your R code. + + -- Command: ess-electric-brace + '{' '}' The braces automatically indent to the correct position + when typed. + + The following Emacs command are also helpful: + +'RET' +'LFD' + 'newline-and-indent' Insert a newline, and indent the next line. + (Note that most keyboards nowadays do not have a key, + but and 'C-j' are equivalent.) + +'M-;' + 'indent-dwim' Call the comment command you want (Do What I Mean). + +* Menu: + +* Styles:: Changing styles for indentation and alignment + + +File: ess.info, Node: Styles, Up: Indenting + +7.4.1 Changing styles for code indentation and alignment +-------------------------------------------------------- + +The combined value of twelve variables (4 of three groups +'ess-indent-*', 'ess-offset-*' and 'ess-align-*') that control +indentation are collectively termed a style. ESS provides several +styles covering the common styles of indentation: 'DEFAULT', 'OWN', +'GNU', 'BSD', 'K&R', 'C++', 'RRR', 'RRR+', 'Rstudio', 'Rstudio-', and +'CLB'. The variable 'ess-style-alist' lists the value of each +indentation variable per style (and its documentation contains more). + + -- Command: ess-set-style + 'C-c C-e C-s' (or 'C-c C-e s') sets the formatting style in this + buffer to be one of the predefined styles, see above. The + 'DEFAULT' style uses the default values for the indenting + variables; The 'OWN' style allows you to use your own private + values of the indentation variable, see below. + + -- User Option: ess-style + The style to use. See the variable 'ess-style-alist' for how these + groups (DEFAULT, OWN, GNU, RRR, ...) map onto different settings + for variables. You can set this in your Emacs configuration file: + + (setq ess-style 'C++) + + -- User Option: ess-style-alist + Predefined formatting styles for ESS code. Values for all groups, + except OWN, are fixed. To change the value of variables in the OWN + group, customize the variable 'ess-own-style-list'. The default + style in use is controlled by 'ess-style'. + + The styles 'DEFAULT' and 'OWN' are initially identical. If you wish +to edit some of the default values, set 'ess-style' to ''OWN' and change +'ess-own-style-list'. *Note Customization::, for convenient ways to set +both these variables. + + If you prefer not to use the customization facility, you can change +individual indentation variables within a hook, for example: + + (defun myindent-ess-hook () + (setq ess-indent-level 4)) + (add-hook 'ess-mode-hook 'myindent-ess-hook) + + In the rare case that you'd like to add an entire new indentation +style of your own, copy the definition of 'ess-own-style-list' to a new +variable and ensure that the last line of the ':set' declaration calls +'ess-add-style' with a unique name for your style (e.g. ''MINE'). +Finally, add '(setq ess-style 'MINE)' to use your new style. + + +File: ess.info, Node: Other edit buffer commands, Next: Source Files, Prev: Indenting, Up: Editing objects + +7.5 Commands for motion, completion and more +============================================ + +A number of commands are provided to move across function definitions in +the edit buffer: + + -- Command: ess-goto-beginning-of-function-or-para + 'ESC C-a' aka 'C-M-a' If inside a function go to the beginning of + it, otherwise go to the beginning of paragraph. + + -- Command: ess-goto-end-of-function-or-para + 'ESC C-e' aka 'C-M-e' Move point to the end of the function + containing point. + + -- Command: ess-mark-function + 'ESC C-h' aka 'C-M-h' Place point at the beginning of the R + function containing point, and mark at the end. + +Don't forget the usual Emacs commands for moving over balanced +expressions and parentheses: *Note Lists and Sexps: (Emacs)Lists. + + Completion is provided in the edit buffer in a similar fashion to the +process buffer: first indents, and if there is nothing to indent, +completes the object or file name; 'M-?' lists file completions. See +*Note Completion::, for more. + + Finally, 'C-c C-z' ('ess-switch-to-inferior-or-script-buffer') +returns you to the 'iESS' process buffer, if done from a script buffer, +placing point at the end of the buffer. If this is done from the 'iESS' +process buffer, point is taken to the script buffer. + + In addition many commands available in the process buffer are also +available in the script buffer. You can still read help files with 'C-c +C-v', edit another function with 'C-c C-e C-d' and of course 'C-c C-l' +can be used to load a source file into R. + + +File: ess.info, Node: Source Files, Next: Source Directories, Prev: Other edit buffer commands, Up: Editing objects + +7.6 Maintaining R source files +============================== + +Every edit buffer in ESS is associated with a "dump file" on disk. Dump +files are created whenever you type 'C-c C-e C-d' +('ess-dump-object-into-edit-buffer'), and may either be deleted after +use, or kept as a backup file or as a means of keeping several versions +of an R function. + + -- User Option: ess-delete-dump-files + If non-'nil', dump files created with C-c C-e C-d are deleted + immediately after they are created by the ess-process. + + Since immediately after R dumps an object's definition to a disk file +the source code on disk corresponds exactly to R's idea of the object's +definition, the disk file isn't needed; deleting it now has the +advantage that if you _don't_ modify the file (say, because you just +wanted to look at the definition of one of the standard R functions) the +source dump file won't be left around when you kill the buffer. Note +that this variable only applies to files generated with R's 'dump' +function; it doesn't apply to source files which already exist. The +default value is 't'. + + -- User Option: ess-keep-dump-files + Variable controlling whether to delete dump files after a + successful load. If 'nil': always delete. If 'ask', confirm to + delete. If 'check', confirm to delete, except for files created + with 'ess-dump-object-into-edit-buffer'. Anything else, never + delete. This variable only affects the behaviour of + 'ess-load-file'. Dump files are never deleted if an error occurs + during the load. + + After an object has been successfully (without error) loaded back +into R with 'C-c C-l', the disk file again corresponds exactly (well, +almost -- see below) to R's record of the object's definition, and so +some people prefer to delete the disk file rather than unnecessarily use +up space. This option allows you to do just that. + + If the value of 'ess-keep-dump-files' is 't', dump files are never +deleted after they are loaded. Thus you can maintain a complete text +record of the functions you have edited within ESS. Backup files are +kept as usual, and so by using the Emacs numbered backup facility -- +*note Single or Numbered Backups: (emacs)Backup Names, you can keep a +historic record of function definitions. Another possibility is to +maintain the files with a version-control system such as git *Note +Version Control: (emacs)Version Control. As long as a dump file exists +in the appropriate place for a particular object, editing that object +with 'C-c C-e C-d' finds that file for editing (unless a prefix argument +is given) -- the ESS process is not consulted. Thus you can keep +comments _outside_ the function definition as a means of documentation +that does not clutter the R object itself. Another useful feature is +that you may format the code in any fashion you please without R +re-indenting the code every time you edit it. These features are +particularly useful for project-based work. + + If the value of 'ess-keep-dump-files' is nil, the dump file is always +silently deleted after a successful load with 'C-c C-l'. While this is +useful for files that were created with 'C-c C-e C-d' it also applies to +any other file you load (say, a source file of function definitions), +and so can be dangerous to use unless you are careful. Note that since +'ess-keep-dump-files' is buffer-local, you can make sure particular +files are not deleted by setting it to 't' in the Local Variables +section of the file *Note Local Variables in Files: (emacs)File +Variables. + + A safer option is to set 'ess-keep-dump-files' to 'ask'; this means +that ESS will always ask for confirmation before deleting the file. +Since this can get annoying if you always want to delete dump files +created with 'C-c C-e C-d', but not any other files, setting +'ess-keep-dump-files' to 'check' (the default value) will silently +delete dump files created with 'C-c C-e C-d' in the current Emacs +session, but query for any other file. Note that in any case you will +only be asked for confirmation once per file, and your answer is +remembered for the rest of the Emacs session. + + Note that in all cases, if an error (such as a syntax error) is +detected while loading the file with 'C-c C-l', the dump file is _never_ +deleted. This is so that you can edit the file in a new Emacs session +if you happen to quit Emacs before correcting the error. + + Dump buffers are always autosaved, regardless of the value of +'ess-keep-dump-files'. + + +File: ess.info, Node: Source Directories, Prev: Source Files, Up: Editing objects + +7.7 Names and locations of dump files +===================================== + +Every dump file should be given a unique file name, usually the dumped +object name with some additions. + + -- User Option: ess-dump-filename-template + Template for filenames of dumped objects. '%s' is replaced by the + object name. + +By default, dump file names are the user name, followed by '.' and the +object and ending with '.R'. Thus if user 'joe' dumps the object +'myfun' the dump file will have name 'joe.myfun.R'. The username part +is included to avoid clashes when dumping into a publicly-writable +directory, such as '/tmp'; you may wish to remove this part if you are +dumping into a directory owned by you. + + You may also specify the directory in which dump files are written: + + -- User Option: ess-source-directory + Directory name (ending in a slash) where R dump files are to be + written. + + By default, dump files are always written to '/tmp', which is fine +when 'ess-keep-dump-files' is 'nil'. If you are keeping dump files, +then you will probably want to keep them somewhere in your home +directory, say '~/R-source'. This could be achieved by including the +following line in your Emacs configuration file: + (setq ess-source-directory (expand-file-name "~/R-source/")) + + If you would prefer to keep your dump files in separate directories +depending on the value of some variable, ESS provides a facility for +this also. By setting 'ess-source-directory' to a lambda expression +which evaluates to a directory name, you have a great deal of +flexibility in selecting the directory for a particular source file to +appear in. The lambda expression is evaluated with the process buffer +as the current buffer and so you can use the variables local to that +buffer to make your choice. For example, the following expression +causes source files to be saved in the subdirectory 'Src' of the +directory the ESS process was run in. + + (setq ess-source-directory + (lambda () + (concat ess-directory "Src/"))) + +('ess-directory' is a buffer-local variable in process buffers which +records the directory the ESS process was run from.) This is useful if +you keep your dump files and you often edit objects with the same name +in different ESS processes. Alternatively, if you often change your R +working directory during an R session, you may like to keep dump files +in some subdirectory of the directory pointed to by the first element of +the current search list. This way you can edit objects of the same name +in different directories during the one R session: + (setq ess-source-directory + (lambda () + (file-name-as-directory + (expand-file-name (concat + (car ess-search-list) + "/.Src"))))) + + If the directory generated by the lambda function does not exist but +can be created, you will be asked whether you wish to create the +directory. If you choose not to, or the directory cannot be created, +you will not be able to edit functions. + + +File: ess.info, Node: Help, Next: Completion, Prev: Editing objects, Up: Top + +8 Reading help files +******************** + +ESS provides an easy-to-use facility for reading R help files from +within Emacs. From within the ESS process buffer or any ESS edit +buffer, typing 'C-c C-v' ('ess-display-help-on-object') will prompt you +for the name of an object for which you would like documentation. +Completion is provided over all objects which have help files. + + If the requested object has documentation, you will be popped into a +buffer (named '*help(OBJ-NAME)*') containing the help file. This buffer +is placed in a special ESS help mode which disables the usual editing +commands but which provides a number of keys for paging through the help +file. + + Help commands: + +'?' + 'ess-describe-help-mode' Pops up a help buffer with a list of the + commands available in R help mode. + +'h' + 'ess-display-help-on-object' Pop up a help buffer for a different + object. + + Paging commands: + +'DEL' + 'scroll-down-command' Move one screen backwards through the help + file. + +'SPC' + 'scroll-up-command' Move one screen forwards through the help file. + +'>' +'<' + 'end/beginning-of-buffer' Move to the end or beginning of the help + file, respectively. + + Section-based motion commands: + +'n' +'p' + 'ess-skip-to-previous-section' and 'ess-skip-to-next-section' Move + to the next and previous section header in the help file, + respectively. A section header consists of a number of capitalized + words, followed by a colon. + + In addition, the 's' key followed by one of the following letters +will jump to a particular section in the help file. Note that the exact +headings available and capitalization scheme may vary across languages. + + You may use 's ?' to get the current list of active key bindings. + +'a' + Arguments: + +'b' + Background: + +'B' + Bugs: + +'d' + Description: + +'D' + Details: + +'e' + Examples: + +'n' + Note: + +'O' + Optional Arguments: + +'R' + Required Arguments: + +'r' + References: + +'s' + See Also: + +'S' + Side Effects: + +'u' + Usage: + +'v' + Value: + +'?' + Pops up a help buffer with a list of the defined section motion + keys. + + Evaluation: + +'l' + 'ess-eval-line-and-step' Evaluates the current line in the ESS + process, and moves to the next line. Useful for running examples + in help files. + +'r' + 'ess-eval-region' Send the contents of the current region to the + ESS process. Useful for running examples in help files. + + Quit commands: + +'q' + 'ess-help-quit' Return to previously selected buffer, and bury the + help buffer. + +'k' + 'kill-buffer' Return to previously selected buffer, and kills the + help buffer. + +'x' + 'ess-kill-buffer-and-go' Return to the ESS process, killing this + help buffer. + + Miscellaneous: + +'i' + 'ess-display-index' Prompt for a package and display it's help + index. + +'v' + 'ess-display-vignettes' Display all available vignettes. + +'w' + 'ess-display-help-in-browser' Display current help page with the + web browser. + +'/' + 'isearch-forward' Same as 'C-s'. + + In addition, all of the ESS commands available in the edit buffers +are also available in R help mode (*note Edit buffer::). Of course, the +usual (non-editing) Emacs commands are available, and for convenience +the digits and <-> act as prefix arguments. + + If a help buffer already exists for an object for which help is +requested, that buffer is popped to immediately; the ESS process is not +consulted at all. If the contents of the help file have changed, you +either need to kill the help buffer first, or pass a prefix argument +(with 'C-u') to 'ess-display-help-on-object'. + + Help buffers are marked as temporary buffers in ESS, and are deleted +when 'ess-quit' or 'ess-cleanup' are called. + + Help buffers normally appear in another window within the current +frame. If you wish help buffers to appear in their own frame (either +one per help buffer, or one for all help buffers), you can customize the +variable 'ess-help-own-frame'. + + Help buffers are displayed by calling the function +'ess-display-help'. You can customize where these buffers are displayed +by adding an entry in 'display-buffer-alist'; for examples, see *Note +(ess)Controlling buffer display::. Or by customizing the options +'ess-help-own-frame', 'ess-help-frame-alist', and +'ess-display-buffer-reuse-frame'. + + +File: ess.info, Node: Completion, Next: Developing with ESS, Prev: Help, Up: Top + +9 Completion +************ + +* Menu: + +* Object names:: +* Function arguments:: +* Minibuffer completion:: +* Company:: +* Icicles:: + + +File: ess.info, Node: Object names, Next: Function arguments, Up: Completion + +9.1 Completion of object names +============================== + +The key is for completion. The value of the variable +'ess-first-tab-never-complete' controls when completion is allowed to +occur. In 'ess-mode' first tries to indent, and if there is +nothing to indent, complete the object name instead. + +'TAB' + 'comint-dynamic-complete' Complete the R object name or filename + before point. + + When the cursor is just after a partially-completed object name, +pressing provides completion in a similar fashion to the rest of +Emacs. ESS maintains a list of all objects known to R at any given +time, which basically consists of all objects (functions and datasets) +in every attached directory listed by the 'search()' command along with +the component objects of attached data frames + + For example, consider three functions 'binomplot()', 'binom.test()' +and 'binomial()'. Typing 'bin TAB' will insert the characters 'om', +completing the longest prefix ('binom') which distinguishes these three +commands. Pressing 'TAB' once more provides a list of the three +commands which have this prefix, allowing you to add more characters +(say, '.') which specify the function you desire. After entering more +characters pressing 'TAB' yet again will complete the object name up to +uniqueness, etc. If you just wish to see what completions exist without +adding any extra characters, type 'M-?'. + + -- Command: ess-complete-object-name + 'M-?' List all possible completions of the object name at point. + + ESS also provides completion over the components of named lists and +environments (after '$'), S4 classes slots (after @), package and +namespace objects (after :: and :::). + + Completion is also provided over file names, which is particularly +useful when using R functions such as 'get()' or 'scan()' which require +fully expanded file names. + + In the iESS buffer, if the cursor is not in a string and does not +follow a (partial) object name, the key has a third use: it +expands history references. *Note History expansion::. + + Efficiency in completion is gained by maintaining a cache of objects +currently known to R; when a new object becomes available or is deleted, +only one component of the cache corresponding to the associated +directory needs to be refreshed. If ESS ever becomes confused about +what objects are available for completion (such as when if refuses to +complete an object you *know* is there), the command 'M-x ess-resynch' +forces the _entire_ cache to be refreshed, which should fix the problem. + + +File: ess.info, Node: Function arguments, Next: Minibuffer completion, Prev: Object names, Up: Completion + +9.2 Completion of function arguments +==================================== + +When inside a function call (i.e. following ''(''), 'TAB' completion +also provides function arguments. If function is a generic, completion +will provide all the arguments of 'S3' methods known to 'R'. + + In R versions newer than 2.14.1, ESS uses R's built-in completion +engine and will honor its settings. You may read about them by issuing +'?rc.options' at the prompt. For example, to have the equals sign for +function arguments contain spaces on both sides (e.g. 'lm(for)' +suggests 'formula = ' rather than 'formula='), you can adjust +'funarg.suffix': + + utils::rc.options(funarg.suffix = " = ") + + A related functionality is *Note ESS ElDoc::, which displays function +arguments in the echo area whenever the point is inside a function call. + + +File: ess.info, Node: Minibuffer completion, Next: Company, Prev: Function arguments, Up: Completion + +9.3 Minibuffer completion +========================= + +ESS uses 'IDO' mechanism (part of default Emacs) for minibuffer +completion if the 'ido' package is available and the value of +'ess-use-ido' it 't' (the default). The completion command +'ess-completing-read' falls back on classic 'completion-read' interface +if this feature is not available for whatever reason. + + +File: ess.info, Node: Company, Next: Icicles, Prev: Minibuffer completion, Up: Completion + +9.4 Company +=========== + +Another popular package for completion is company, short for complete +anything. ESS provides support for company out-of-the-box. To disable +company support, set 'ess-use-company' to 'nil'. You can set it to +''script-only' to only activate company in R scripts. + + +File: ess.info, Node: Icicles, Prev: Company, Up: Completion + +9.5 Icicles +=========== + +Another option for comprehensively handling completion in Emacs is via +Icicles (). It allows users to +have completions shown temporarily in the standard '*Completions*' +buffer, and interactively select completion candidates using several +methods. As of version 2013.04.04, Icicles provides support for +completion in ESS. Please consult Icicles documentation, which is easily +accessible via 'customize-group Icicles', for more details on +installation and customization options. + + Once installed, Icicles can be activated by evaluating): + + (require 'icicles) + (icy-mode 1) + + Icicles can be toggled by typing 'M-x icy'. + + When Icicles is on, 'TAB' offers completion, provided the conditions +determined by 'ess-first-tab-never-complete' allow it. Typing 'M-TAB' +will attempt completion regardless. Typing 'M-?' in 'ESS' or 'iESS' +modes brings up the relevant completion candidates from which to choose. +Minibuffer input filters the available candidates. Use 'TAB' for prefix +completion or 'S-TAB' for substring or regexp completion. Use 'S-SPC' +to match an additional pattern (repeatable). You can cycle among the +matching candidates, choosing with 'RET' or 'mouse-2'. + + +File: ess.info, Node: Developing with ESS, Next: Extras, Prev: Completion, Up: Top + +10 Developing with ESS +********************** + +ESS provides several tools to help you with the development of your R +packages: + +* Menu: + +* ESS tracebug:: Visual debugging, breakpoints, tracing, watch etc. +* Editing documentation:: Tools to edit R documentation +* Namespaced Evaluation:: Develop your packages on the fly + + +File: ess.info, Node: ESS tracebug, Next: Editing documentation, Up: Developing with ESS + +10.1 ESS tracebug +================= + +* Menu: + +* Getting started with tracebug:: Quick tutorial + +ESS 'tracebug' offers visual debugging, interactive error navigation, +interactive backtrace, breakpoint manipulation, control over R error +actions, watch window and interactive flagging/unflagging of functions +for debugging. + + 'ess-tracebug' is on by default. You can toggle it on and off with +'M-x' 'ess-tracebug'. To disable startup activation of 'ess-tracebug' +set 'ess-use-tracebug' to nil. + + Tracebug functionality can be found on 'ess-dev-map', bound to 'C-c +C-t'. Additionally, when subprocess is in a debugging state +'ess-debug-minor-mode' is active and the following additional shortcuts +are available: + +* Interactive Debugging (`ess-debug-minor-mode-map'): + + M-C . Continue . `ess-debug-command-continue' + M-C-C . Continue multi . `ess-debug-command-continue-multi' + M-N . Next step . `ess-debug-command-next' + M-C-N . Next step multi . `ess-debug-command-next-multi' + M-U . Up frame . `ess-debug-command-up' + M-Q . Quit debugging . `ess-debug-command-quit' + + + These are all the tracebug commands defined in 'ess-dev-map' ('C-c +C-t ?' to show this table): + + +* Breakpoints (`ess-dev-map'): + + b . Set BP (repeat to cycle BP type) . `ess-bp-set' + B . Set conditional BP . `ess-bp-set-conditional' + k . Kill BP . `ess-bp-kil' + K . Kill all BPs . `ess-bp-kill-all' + o . Toggle BP state . `ess-bp-toggle-state' + l . Set logger BP . `ess-bp-set-logger' + n . Goto next BP . `ess-bp-next' + p . Goto previous BP . `ess-bp-previous' + + (C- prefixed equivalents are also defined) + +* Debugging (`ess-dev-map'): + ` . Show traceback . `ess-show-traceback' (also on C-c `) + ~ . Show callstack . `ess-show-call-stack' (also on C-c ~) + e . Toggle error action (repeat to cycle). `ess-debug-toggle-error-action' + d . Flag for debugging . `ess-debug-flag-for-debugging' + u . Unflag for debugging . `ess-debug-unflag-for-debugging' + w . Watch window . `ess-watch' + + (C- prefixed equivalents are also defined) + +* Navigation to errors (general Emacs functionality): + + C-x `, M-g n . `next-error' + M-g p . `previous-error' + +* Misc: + +? . Show this help . `ess-tracebug-show-help' + + + To configure how electric watch window splits the display see +'ess-watch-width-threshold' and 'ess-watch-height-threshold' variables. + + _Note:_ Currently, ess-tracebug does not detect some of R's debug +related messages in non-English locales. To set your R messages to +English add the following line to your .Rprofile init file: + + Sys.setlocale("LC_MESSAGES", "C") + + +File: ess.info, Node: Getting started with tracebug, Up: ESS tracebug + +10.1.1 Getting started with tracebug +------------------------------------ + +Consider a buffer with the following function: + +test <- function(x){ + mean(x), +} + + Evaluating the function (e.g. 'C-c C-c') results in an error about +an unexpected comma. You can use 'next-error' (bound by default to 'C-x +`', 'M-g n', and 'M-g M-n') to jump to the place where the error +occurred. Alternatively, use the mouse to click on the error to jump to +where it occurred. + + Correct the error by deleting the comma. Now put point on 'mean' and +set the breakpoint using 'C-c C-t b' ('ess-bp-set') and reevaluate the +function. Jump to the inferior buffer (possibly using 'C-c C-z') and +evaluate 'test(1:10)'. An interactive debug process starts, stopping at +the breakpoint we just specified. Here you can debug your function +(what is 'x' at this point?). Use 'M-N' to continue. + + Let's replace our test function with one slightly more complicated: + +test <- function(x){ + x <- x + 1 + y <- mean(x) + x <- ifelse(x > 5, x, x - 100) + list(x, y) +} + + Try setting multiple breakpoints. You can unset a breakpoint by +killing it with 'C-c C-t k'. You can set conditional breakpoints too. +Try setting one by placing point on the line 'x <- x + 1' and doing 'C-c +C-t B'. ESS will ask for the condition. Let's set it to +'!is.numeric(x)'. After re-evaluating 'test', try calling 'test(1:100)' +and 'test('foo')'. + + You can remove all breakpoints with 'C-c C-t K'. + + You can flag a function for debugging (similar to calling +'debug(test)' at R's prompt) by doing 'C-c C-t d'. Try this yourself by +putting point over 'test' and doing 'C-c C-t d'. + + If an error occurs, you can get the complete call stack by doing 'C-c +`' or 'C-c C-t `' ('ess-show-traceback'). + + Tracebug also offers a watch window where you can watch values of +objects. Open it with 'C-c C-t w' ('ess-watch'). Initially you aren't +watching anything. Add something with 'a' (e.g. 'a test'). The watch +window displays what the object is at any given time and automatically +updates. Quit the watch window with 'q'. + + +File: ess.info, Node: Editing documentation, Next: Namespaced Evaluation, Prev: ESS tracebug, Up: Developing with ESS + +10.2 Editing documentation +========================== + +ESS provides two ways of writing documentation for R objects. Either +using the standard R documentation system or using in-source +documentation written as structured comment fields for use with the +roxygen2 package. + +* Menu: + +* R documentation files:: Edit objects in a specialized buffer +* roxygen2:: Loading source files into the ESS process + + +File: ess.info, Node: R documentation files, Next: roxygen2, Up: Editing documentation + +10.2.1 Editing R documentation (Rd) files +----------------------------------------- + +R objects are documented in files written in the "R documentation" +("Rd"), a simple markup language closely resembling (La)TeX, which can +be processed into a variety of formats, including LaTeX, HTML, and plain +text. Rd format is described in section "Rd format" of the "Writing R +Extensions" manual in the R distribution. ESS has several features that +facilitate editing Rd files. + + Visiting an Rd file as characterized by its extension 'Rd' will +activate Rd Mode, which provides several facilities for making editing R +documentation files more convenient, by helping with indentation, +insertions, even doing some of the typing for you (with Abbrev Mode), +and by showing Rd keywords, strings, etc. in different faces (with Font +Lock Mode). + + In Rd mode, the following special Emacs commands can be used in +addition to the standard Emacs commands. + +'C-h m' + Describe the features of Rd mode. + +'LFD' +'RET' + Reindent the current line, insert a newline and indent the new line + ('reindent-then-newline-and-indent'). An abbrev before point is + expanded if 'abbrev-mode' is non-'nil'. + +'TAB' + Indent current line based on its contents and on previous lines. + ('indent-according-to-mode'). + +'C-c C-e' + Insert a "skeleton" with Rd markup for at least all mandatory + entries in Rd files ('Rd-mode-insert-skeleton'). Note that many + users might prefer to use the R function 'prompt' on an existing R + object to generate a non-empty Rd "shell" documenting the object + (which already has all information filled in which can be obtained + from the object). + +'C-c C-f' + Insert "font" specifiers for some of the Rd markup commands markup + available for emphasizing or quoting text, including markup for + URLs and email addresses ('Rd-font'). 'C-c C-f' is only a prefix; + see e.g. 'C-c C-f TAB' for the available bindings. Note that + currently, not all of the Rd text markup as described in section + "Marking text" of "Writing R Extensions" can be accessed via 'C-c + C-f'. + +'C-c C-j' + Insert a suitably indented '\item{' on the next line + ('Rd-mode-insert-item'). + +'C-c C-p' + Preview a plain text version ("help file", *note Help::) generated + from the Rd file ('Rd-preview-help'). + + In addition, when editing Rd files one can interact with a running R +process in a similar way as when editing R language files. For example, +'C-c C-v' provides access to on-line help, and 'C-c C-n' sends the +current line to the R process for evaluation. This interaction is +particularly useful when editing the examples in the Rd file. See 'C-h +m' for all available commands. + + Rd mode also provides access to abbreviations for most of the Rd +markup commands. Type 'M-x list-abbrevs' with Abbrev mode turned on to +list all available abbrevs. Note that all Rd abbrevs start with a grave +accent. + + Rd mode can be customized via the following variables. + + -- User Option: Rd-mode-hook + Hook to be run when Rd mode is entered. + + -- User Option: Rd-indent-level + The indentation of Rd code with respect to containing blocks. + Default is 2. + + -- User Option: Rd-to-help-command + The shell command used for converting Rd source to help text. + Default is 'R CMD Rd2txt'. + + To automatically turn on the abbrev and font-lock features of Rd +mode, add the following lines to one of your Emacs startup files: + + (add-hook 'Rd-mode-hook + (lambda () + (abbrev-mode 1) + (font-lock-mode 1))) + + +File: ess.info, Node: roxygen2, Prev: R documentation files, Up: Editing documentation + +10.2.2 Editing roxygen2 documentation +------------------------------------- + +The roxygen2 R package makes it possible to keep the intended contents +for Rd files as structured comments in the R source files. roxygen2 can +then parse R files and generate appropriate Rd files from these +comments, fill the usage fields as well as updating 'NAMESPACE' files. +See the roxygen2 documentation found via +for more information on its usage. An example of an roxygen2 entry for +a simple R function can look like this: + + ##' Description of the function + ##' + ##' Further details about this function + ##' @title A title + ##' @param me all parameters must be listed and documented + ##' @return Description of the return value + ##' @author The author + myfun <- function(me) + cat("Hello", me, "\n") + The entry is immediately preceding the object to document and all +lines start with the roxygen2 prefix string, in this case '##''. ESS +provides support to edit these documentation entries by providing line +filling, navigation, template generation etc. Syntax highlighting is +provided. + + roxygen2 is customized by the variables in the customization group +"Ess Roxy". Customizations include the roxygen2 prefix, use of folding +to toggle visibility of roxygen2 entries and the roxygen2 template. + + All ESS roxygen2 support is defined in 'ess-roxy.el' which is loaded +by default in ESS. The following special Emacs commands are provided. + + -- Command: ess-roxy-update-entry + 'C-c C-o C-o' Generate a roxygen2 template or update the parameter + list in roxygen2 entry at point (or above the function at the + point). Documented parameters that are not in the function are + placed last in the list, parameters that are not documented and not + in the definition are dropped. Parameter descriptions are filled + if 'ess-roxy-fill-param-p' is non-nil. + + -- Command: ess-roxy-toggle-roxy-region BEG END + 'C-c C-o C-c' Toggle the presence of the leading roxygen2 string on + all lines in the marked region (between BEG and END. Convenient + for transferring text to roxygen2 entries and to evaluate example + fields. + + -- Command: ess-roxy-preview-Rd NAME-FILE + 'C-c C-o C-r' Use the attached R process to parse the entry at + point to obtain the Rd code. Convenient for previewing and + checking syntax. When used with the prefix argument NAME-FILE, + i.e. 'C-u C-c C-e C-r', place the content in a buffer associated + with a Rd file with the same name as the documentation. Requires + the roxygen2 package to be installed. + + -- Command: ess-roxy-preview-HTML VISIT-INSTEAD-OF-OPEN + 'C-c C-o C-t' Use the attached R process to parse the entry at to + generate HTML for the entry and open it in a browser. When used + with the prefix argument VISIT-INSTEAD-OF-OPEN, i.e. 'C-u C-c C-e + C-t', visit the generated HTML file instead. Requires the roxygen2 + and tools packages to be installed. + + -- Command: ess-roxy-previous-entry + 'C-c C-o p' Go to start of the roxygen2 entry above point. + + -- Command: ess-roxy-next-entry + 'C-c C-o n' Go to end of the roxygen2 entry above point. + + -- Command: ess-roxy-hide-all + 'C-c C-o C-h' Use the hideshow mode to fold away the visibility of + all roxygen2 entries. Hide-show support must be enabled for this + binding to get defined. + + ESS also advises the following standard editing functions in order to +make roxygen2 editing more intuitive: + +'TAB' + 'ess-R-complete-object-name' Complete roxygen2 tag at point. E.g. + doing 'TAB' when the point is at the end of '@par' completes to + '@param'. + +'M-h' + 'mark-paragraph' If the transient mark mode is active, place mark + and point at start end end of the field at point and activate the + mark. + +'TAB' + 'ess-indent-command' If hide-show support is enabled, fold away the + visibility of the roxygen2 entry at point. + +'M-q' + 'fill-paragraph' Fill the roxygen2 field at point. + +'C-a' + 'ess-roxy-move-beginning-of-line' Move to the point directly to the + right of the roxygen2 start string. If already there, move to the + beginning of the line. + +'RET' + 'newline-and-indent' Insert a new line and the roxygen2 prefix + string. + + +File: ess.info, Node: Namespaced Evaluation, Prev: Editing documentation, Up: Developing with ESS + +10.3 Namespaced Evaluation +========================== + +In non package files evaluation commands, *Note Evaluating code::, send +portions of the current buffer environment ('R_GlobalEnv'. When +developing packages, ESS sends code to the corresponding package +namespace and (for visible objects) into package environment (visible on +search path). All objects that are assigned are displayed in the +minibuffer alongside the environment in which they are assigned. + + Here is a short overview of how namespace and package environments +work in R. All objects defined in a package 'foo' are stored in an +environment called 'namespace:foo'. Parent environment of +'namespace:foo' is an environment 'imports:foo' which contains copies of +all objects from other packages which 'foo' imports. Parent environment +of 'imports:foo' is the 'namespace:base'. Parent environment of +'namespace:base' is .GlobalEnv. Thus functions and methods stored in +'namespace:foo' see all the objects in .GlobalEnv unless shadowed by +objects in 'imports:foo', 'namespace:base', or 'namespace:foo' itself. +There is another environment associated with 'foo' - 'package:foo'. +This environment stores *copies* of exported objects from +'namespace:foo' and is placed on the search() path, i.e. if 'foo' is +loaded and if you start with .GlobalEnv and iteratively call +parent.env() you will get eventually to 'package:foo'. Thus all methods +and functions defined in .GlobalEnv can "see" objects in 'package:foo' +environment. See also +. + + Occasionally you want to evaluate into a package from a non-package +file, or the other way around, evaluate into 'GlobalEnv' from inside a +package. In such cases 'C-c C-t C-s' is your friend. + + -- Command: ess-r-set-evaluation-env ARG + 'C-c C-t C-s' Set or unset the current evaluation environment (a + package). + + +File: ess.info, Node: Extras, Next: ESS for R, Prev: Developing with ESS, Up: Top + +11 Other ESS features and tools +******************************* + +ESS has a few extra features, which didn't fit anywhere else. +* Menu: + +* ESS ElDoc:: Display function arguments in minibuffer +* ESS Flymake:: On-the-fly syntax checking +* Handy commands:: Usefully commands at your fingertips +* Highlighting:: Syntactic highlighting of buffers +* Parens:: Parenthesis matching +* Graphics:: Using graphics with ESS +* Imenu:: Support for Imenu in ESS +* Toolbar:: Support for toolbar in ESS +* Xref:: Xref +* Rdired:: Directory editor for R objects +* Package listing:: R object/package management and help utilities +* Org:: Interaction with Org mode +* Sweave and AUCTeX:: Support for Sweave in ESS and AUCTeX + + +File: ess.info, Node: ESS ElDoc, Next: ESS Flymake, Up: Extras + +11.1 ElDoc +========== + +In 'ElDoc' mode, the echo area displays function's arguments at point. +ElDoc is active by default in 'ess-mode' and 'inferior-ess-mode' +buffers. To activate it only in 'ess-mode' buffers, place the following +into your init file: + + (setq ess-use-eldoc 'script-only) + + -- User Option: ess-use-eldoc + If 't', activate eldoc in ess-mode and inferior-ess-mode buffers. + If ''script-only' activate in ess-mode buffers only. Set + 'ess-use-eldoc' to 'nil' to stop using 'ElDoc' altogether. + + -- User Option: ess-eldoc-show-on-symbol + This variable controls whether the help is shown only inside + function calls. If set to 't', 'ElDoc' shows help string whenever + the point is on a symbol, otherwise (the default), shows only when + the point is in a function call, i.e. after ''(''. + + -- User Option: ess-eldoc-abbreviation-style + The variable determines how the doc string should be abbreviated to + fit into minibuffer. Posible values are 'nil', 'mild', 'normal', + 'strong' and 'aggressive'. Please see the documentation of the + variable for more details. The default filter is 'normal'. + + Ess-eldoc also honors the value of 'eldoc-echo-area-use-multiline-p', +which if set to 'nil', will cause the truncation of doc string +indifferent of the value of 'ess-eldoc-abbreviation-style'. This way +you can combine different filter levels with the truncation. + + +File: ess.info, Node: ESS Flymake, Next: Handy commands, Prev: ESS ElDoc, Up: Extras + +11.2 Flymake +============ + +The minor mode 'flymake-mode' provides on-the-fly syntax checking. ESS +provides support for flymake in R-mode in Emacs versions 26 and newer. +It is enabled by default, to disable it you may set 'ess-use-flymake' to +'nil'. In order to use it, you may need to install the 'lintr' R +package, available from CRAN. + + -- User Option: ess-use-flymake + When non-nil, use flymake. If ''process', only use flymake when + the buffer has an inferior process running. + + -- User Option: ess-r-flymake-linters + This variable describes the linters to use. It can either be a + string with an R expression to be used as-is or a list of strings + where each element is passed to 'lintr::with_defaults'. See the + help page for 'lintr::default_linters' for information on available + linters and their defaults. + + -- User Option: ess-r-flymake-lintr-cache + When 't' (the default), lintr uses a cache. Change to 'nil' to + disable lintr's caching mechanism. + + +File: ess.info, Node: Handy commands, Next: Highlighting, Prev: ESS Flymake, Up: Extras + +11.3 Handy commands +=================== + + -- Command: ess-handy-commands + Request and execute a command from 'ess-handy-commands' list. + + -- User Option: ess-handy-commands + An alist of custom ESS commands available for call by + 'ess-handy-commands' and 'ess-smart-comma' function. + + Currently contains: + + change-directory + 'ess-change-directory' + help-index + 'ess-display-index' + help-object + 'ess-display-help-on-object' + vignettes + 'ess-display-vignettes' + objects[ls] + 'ess-execute-objects' + search + 'ess-execute-search' + set-width + 'ess-execute-screen-options' + install.packages + 'ess-install.packages' + library + 'ess-library' + setRepos + 'ess-setRepositories' + sos + 'ess-sos' + + Handy commands: 'ess-library', 'ess-install.packages', etc - ask for +item with completion and execute the correspond command. 'ess-sos' is a +interface to 'findFn' function in package 'sos'. If package 'sos' is +not found, ask user for interactive install. + + +File: ess.info, Node: Highlighting, Next: Parens, Prev: Handy commands, Up: Extras + +11.4 Syntactic highlighting of buffers +====================================== + +ESS provides Font-Lock (*note Using Multiple Typefaces: (emacs)Faces.) +patterns for inferior R Mode, S Mode, and R Transcript Mode buffers. + + The font-lock patterns are defined by the following variables, which +you may modify if desired: + + -- User Option: inferior-R-font-lock-keywords + Font-lock patterns for inferior *R* processes. (There is a + corresponding 'inferior-S-font-lock-keywords' for *S* processes.) + The default value highlights prompts, inputs, assignments, output + messages, vector and matrix labels, and literals such as 'NA' and + 'TRUE'. + + -- User Option: ess-R-font-lock-keywords + Font-lock patterns for ESS R programming mode. (There is a + corresponding 'ess-S-font-lock-keywords' for S buffers.) The + default value highlights function names, literals, assignments, + source functions and reserved words. + + +File: ess.info, Node: Parens, Next: Graphics, Prev: Highlighting, Up: Extras + +11.5 Parenthesis matching +========================= + +Emacs has facilities for highlighting the parenthesis matching the +parenthesis at point. This feature is very useful when trying to +examine which parentheses match each other. This highlighting also +indicates when parentheses are not matching. You may activate it +putting this in your Emacs configuration file: + + (show-paren-mode) + + +File: ess.info, Node: Graphics, Next: Imenu, Prev: Parens, Up: Extras + +11.6 Using graphics with ESS +============================ + +One of the main features of R is its ability to generate high-resolution +graphics plots. When using R in a windowing environment, no additional +configuration is necessary; plots will be shown in a new (non-Emacs) +window. + + If not using a windowing environment or S, ESS provides a number of +features for dealing with such plots. + +* Menu: + +* printer:: The printer() graphics driver +* X11:: The X11() (and other X Windows based) driver +* winjava:: Java Graphics Device + + +File: ess.info, Node: printer, Next: X11, Up: Graphics + +11.6.1 Using ESS with the 'printer()' driver +-------------------------------------------- + +This is the simplest (and least desirable) method of using graphics +within ESS. S's 'printer()' device driver produces crude character based +plots which can be contained within the ESS process buffer itself. To +start using character graphics, issue the S command + printer(width=79) + (the 'width=79' argument prevents Emacs line-wrapping at column 80 on +an 80-column terminal. Use a different value for a terminal with a +different number of columns.) Plotting commands do not generate +graphics immediately, but are stored until the 'show()' command is +issued, which displays the current figure. + + +File: ess.info, Node: X11, Next: winjava, Prev: printer, Up: Graphics + +11.6.2 Using ESS with windowing devices +--------------------------------------- + +Of course, the ideal way to use graphics with ESS is to use a windowing +system. Under X Windows, or X11, this requires that the DISPLAY +environment variable be appropriately set. + + +File: ess.info, Node: winjava, Prev: X11, Up: Graphics + +11.6.3 Java Graphics Device +--------------------------- + +S+6.1 and newer on Windows contains a java library that supports +graphics. Send the commands: + + library(winjava) + java.graph() + +to start the graphics driver. This allows you to use ESS for both +interaction and graphics within S-PLUS. (Thanks to Tim Hesterberg for +this information.) + + +File: ess.info, Node: Imenu, Next: Toolbar, Prev: Graphics, Up: Extras + +11.7 Imenu +========== + +Imenu is an Emacs tool for providing mode-specific buffer indexes. In +some of the ESS editing modes (currently SAS and R), support for Imenu +is provided. For example, in R mode buffers, the menubar should display +an item called "Imenu-R". Within this menubar you will then be offered +bookmarks to particular parts of your source file (such as the starting +point of each function definition). + + Imenu works by searching your buffer for lines that match what ESS +thinks is the beginning of a suitable entry, for example the beginning +of a function definition. To examine the regular expression that ESS +uses, check the value of 'imenu-generic-expression'. This value is set +by various ESS variables such as 'ess-imenu-S-generic-expression'. + + +File: ess.info, Node: Toolbar, Next: Xref, Prev: Imenu, Up: Extras + +11.8 Toolbar +============ + +The R and S editing modes have support for a toolbar. This toolbar +provides icons to act as shortcuts for starting new S/R processes, or +for evaluating regions of your source buffers. The toolbar should be +present if your Emacs can display images. *Note Customization::, for +ways to change the toolbar. + + +File: ess.info, Node: Xref, Next: Rdired, Prev: Toolbar, Up: Extras + +11.9 Xref +========= + +Xref is an Emacs interface that supports finding "identifiers," usually +function definitions in ESS's view. ESS ships with support for Xref in +Emacs versions 25.1 and higher. For how to use this feature, see *Note +(emacs)Xref::. + + +File: ess.info, Node: Rdired, Next: Package listing, Prev: Xref, Up: Extras + +11.10 Rdired +============ + +Ess-rdired provides a dired-like buffer for viewing, editing and +plotting objects in your current R session. If you are used to using +the dired (directory editor) facility in Emacs, this mode gives you +similar functionality for R objects. + + Start an R session with 'M-x R' and then store a few variables, such +as: + + s <- sin(seq(from=0, to=8*pi, length=100)) + x <- c(1, 4, 9) + y <- rnorm(20) + z <- TRUE + + Then use 'M-x ess-rdired' to create a buffer listing the objects in +your current environment and display it in a new window: + mode length + s numeric 100 + x numeric 3 + y numeric 20 + z logical 1 + + Type 'C-h m' or '?' to get a list of the keybindings for this mode. +For example, with your point on the line of a variable, 'p' will plot +the object, 'v' will view it, and 'd' will mark the object for deletion +('x' will actually perform the deletion). + + +File: ess.info, Node: Package listing, Next: Org, Prev: Rdired, Up: Extras + +11.11 Package listing +===================== + +ESS[R] provides several commands to list and manage packages and objects +under the 'C-c C-.' keymap: + + -- Command: ess-r-package-list-local-packages + 'C-c C-. l' List all packages in all available libraries. + + -- Command: ess-r-package-list-available-packages + 'C-c C-. r' List available packages from repositories listed by + 'getOptions(``repos'')' in the current R session. + + -- Command: ess-r-package-update-packages LIB REPOS + 'C-c C-. u' Update packages in a particular library LIB and + repository REPOS. + + -- Command: ess-rutils-rm-all + 'C-c C-. m' Remove all R objects. + + -- Command: ess-rutils-load-workspace + 'C-c C-. w' Load a workspace file into R. + + -- Command: ess-rutils-save-workspace + 'C-c C-. s' Save a workspace file. + + -- Command: ess-change-directory + 'C-c C-. d' Change the working directory for the current R session. + + -- Command: ess-rutils-html-docs + 'C-c C-. H' Use 'browse-url' to navigate R html documentation. + + Functions for listing objects and packages ('ess-rutils-local-pkgs', +'ess-rutils-repos-pkgs', and 'ess-rutils-objs') show results in a +separate buffer and window, in 'ess-rutils-mode', providing useful key +bindings in this mode (type '?' in this buffer for a description). + + +File: ess.info, Node: Org, Next: Sweave and AUCTeX, Prev: Package listing, Up: Extras + +11.12 Interaction with Org mode +=============================== + +Org-mode () now supports reproducible research and +literate programming in many languages (including R) - see chapter 15 of +the Org manual +(). For ESS +users, this offers a document-based work environment within which to +embed ESS usage. R code lives in code blocks of an Org document, from +which it can be edited in ess-mode, evaluated, extracted ("tangled") to +pure code files. The code can also be exported ("woven") with the +surrounding text to several formats including HTML and LaTeX. Results of +evaluation including figures can be captured in the Org document, and +data can be passed from the Org document (e.g. from a table) to the ESS +R process. (This section contributed by Dan Davison and Eric Schulte.) + + +File: ess.info, Node: Sweave and AUCTeX, Prev: Org, Up: Extras + +11.13 Support for Sweave in ESS and AUCTeX +========================================== + +Libraries for literate data analysis are obsolete and not loaded by +default. This includes 'ess-noweb', 'ess-swv', and related +functionality like 'Rnw-mode'. Users are encouraged to switch to one of +several other packages that deal with these modes. For example, +polymode , +, or markdown-mode with edit-indirect +. + + ESS provides support for writing and processing Sweave +(), building up on Emacs' +ess-noweb-mode for literate programming. When working on an Sweave +document, the following key bindings are available: + + -- Command: ess-swv-weave CHOOSE + 'M-n s' Run Sweave on the current .Rnw file. If CHOOSE is + non-'nil', offer a menu of available weavers. + + -- Command: ess-swv-latex + 'M-n l' Run LaTeX after Sweave'ing. + + -- Command: ess-swv-PS + 'M-n p' Generate and display a postscript file after LaTeX'ing. + + -- Command: ess-swv-PDF PDFLATEX-CMD + 'M-n P' Generate and display a PDF file after LaTeX'ing. Optional + argument PDFLATEX-CMD is the command to use, which by default, is + the command used to generate the PDF file is the first element of + 'ess-swv-pdflatex-commands'. + + -- User Option: ess-swv-pdflatex-commands + Commands used by 'ess-swv-PDF' to run a version of pdflatex; the + first entry is the default command. + + Sweave'ing with 'ess-swv-weave' starts an inferior-ESS process, if +one is not available. Other commands are available from the 'Sweaving, +Tangling, ...' submenu of the Noweb menu. + + AUCTeX () users may prefer to +set the variable 'ess-swv-plug-into-AUCTeX-p' (available from the "ESS +Sweave" customization group) to t. Alternatively, the same can be +achieved by activating the entry "AUCTeX Interface" from the 'Sweaving, +Tangling, ...' submenu, which toggles this variable on or off. When the +interface is activated, new entries for Sweave'ing and LaTeX'ing +thereafter are available from AUCTeX's "Command" menu. Sweave'ing can, +thus, be done by 'C-c C-c Sweave RET' without an inferior-ESS process. +Similarly, LaTeX'ing can be done by 'C-c C-c LaTeXSweave RET'. In both +cases, the process can be monitored with 'C-c C-l' +('TeX-recenter-output-buffer'). Open the viewer with 'C-c C-v' +('TeX-view'), as usual in AUCTeX. + + +File: ess.info, Node: ESS for R, Next: ESS for SAS, Prev: Extras, Up: Top + +12 Overview of ESS features for the S family +******************************************** + +* Menu: + +* ESS(R)--Editing files:: +* iESS(R)--Inferior ESS processes:: +* Philosophies for using ESS(R):: +* Example ESS usage:: + + +File: ess.info, Node: ESS(R)--Editing files, Next: iESS(R)--Inferior ESS processes, Up: ESS for R + +12.1 ESS[R]-Editing files +========================= + +ESS[R] mode should be automatically turned on when visiting a file +ending with an R or S suffix (*.R, *.S, *.s, etc), which enables the +features discussed previously. Alternatively, type 'M-x R-mode' to put +the current buffer into R mode. However, one will have to start up an +inferior process to take advantage of the interactive features. + + +File: ess.info, Node: iESS(R)--Inferior ESS processes, Next: Philosophies for using ESS(R), Prev: ESS(R)--Editing files, Up: ESS for R + +12.2 iESS[R]-Inferior ESS processes +=================================== + +To start up iESS mode for R, use: + M-x R + M-x S+3 + M-x S4 + M-x S+5 + M-x S+6 + +(for R, S-PLUS 3.x, S4, S+5, S+6 or S+7, respectively. This assumes +that you have access to each). + + In the case that you wish to pass command line arguments to the +starting R process, call it with the universal prefix. To set command +line arguments that apply to all future iESS sessions, set the variable +'inferior-R-args'. + + Note that R has some extremely useful command line arguments. For +example, '--vanilla' will ensure R starts up without loading in any init +files. + + If you have other versions of R or S available on the system, ESS is +also able to start those versions. How this exactly works depend on +which OS you are using (details below). The general principle, +regardless of OS, is that ESS searches the paths listed in the variable +'exec-path' for R binaries. If ESS cannot find your R binaries, on Unix +you can change the Unix environment variable 'PATH', as this variable is +used to set 'exec-path'. + + R on GNU/Linux systems and other Unix-like systems (macOS): If you +have "R-3.6.3" on your 'exec-path', it can be started using 'M-x +R-3.6.3'. By default, ESS will find versions of R beginning "R-1", +"R-2", ..., "R-7", "R-devel", or "R-patched". If your versions of R are +called other names, consider renaming them with a symbolic link or +change the variable 'ess-r-runners-prefixes'. To see which functions +have been created for starting different versions of R, type 'M-x R-' +and then hit [Tab]. These other versions of R can also be started from +the "ESS->Start Process->Other" menu. + + R on Windows systems: If you have "rw1081" on your 'exec-path', it +can be started using 'M-x rw1081'. By default, ESS will find versions +of R located in directories parallel to the version of R in your 'PATH'. +If your versions of R are called other names, you will need to change +the variable 'ess-rterm-versions'. To see which functions have been +created for starting different versions of R, type 'M-x rw' and then hit +[Tab]. These other versions of R can also be started from the +"ESS->Start Process->Other" menu. + + Once ESS has found these extra versions of R, it will then create a +new function, called 'M-x run-ess-r-newest', which will call the newest +version of R that it found. (ESS examines the date in the first line of +information from 'R --version' to determine which is newest.) + + +File: ess.info, Node: Philosophies for using ESS(R), Next: Example ESS usage, Prev: iESS(R)--Inferior ESS processes, Up: ESS for R + +12.3 Philosophies for using ESS[R] +================================== + +There are two philosophies for using ESS. Most modern best practices +prefer the first. ESS is configured for the first, and this is what the +manual focuses on. + + 1: The source code is real. Objects are realizations of the source +code. Source for EVERY user modified object is placed in a particular +directory or directories, for later editing and retrieval. + + 2: R objects are real. Source code is a temporary realization of the +objects. Dumped buffers should not be saved. +_We_strongly_discourage_this_approach_. However, if you insist, add the +following lines to your Emacs configuration file: + (setq ess-keep-dump-files nil) + (setq ess-delete-dump-files t) + (setq ess-mode-silently-save nil) + + +File: ess.info, Node: Example ESS usage, Prev: Philosophies for using ESS(R), Up: ESS for R + +12.4 Example ESS usage +====================== + +Comments as to what should be happening are prefixed by "##". + + ### Data Analysis Example + + ## Open the file you want with + C-x C-f myfile.R + + ## Edit as appropriate, then start and switch to an *R* + process buffer with + C-c C-z + + ## A new buffer *R* will appear. R will have been started + ## in this buffer. The buffer is in iESS [R] mode. + + ## Return to the script + C-z (or C-c C-z if you have pressed other keys in between) + + ## Send current region (if active), or function, or paragraph at + point with + C-M-x + + ## Send current region or function or paragraph and step with + C-c C-c + + ## Send current line with + C-RET + + ## or load the entire buffer with + C-c C-l + + ## Save the revised myfile.R with + C-x C-s. + + ## Save the entire *R* interaction buffer with + C-x C-s. + + ## Search for documentation with + C-c C-d + + ## Investigate available ESS commands with + C-c C-h + + ## You will be prompted for a file name. The recommended name is + ## myfile.Rout. With this suffix, the file will be opened in + ## ess-transcript. + + + +File: ess.info, Node: ESS for SAS, Next: ESS for BUGS, Prev: ESS for R, Up: Top + +13 ESS for SAS +************** + +* Menu: + +* ESS(SAS)--Design philosophy:: +* ESS(SAS)--Editing files:: +* ESS(SAS)--TAB key:: +* ESS(SAS)--Batch SAS processes:: +* ESS(SAS)--Function keys for batch processing:: +* iESS(SAS)--Interactive SAS processes:: +* iESS(SAS)--Common problems:: +* ESS(SAS)--Graphics:: +* ESS(SAS)--Windows:: +ESS[SAS] was designed for use with SAS. It is descended from emacs +macros developed by John Sall for editing SAS programs and 'SAS-mode' by +Tom Cook. Those editing features and new advanced features are part of +ESS[SAS]. The user interface of ESS[SAS] has similarities with ESS[S] +and the SAS Display Manager. + + +File: ess.info, Node: ESS(SAS)--Design philosophy, Next: ESS(SAS)--Editing files, Up: ESS for SAS + +13.1 ESS[SAS]-Design philosophy +=============================== + +ESS[SAS] was designed to aid the user in writing and maintaining SAS +programs, such as 'FOO.sas'. Both interactive and batch submission of +SAS programs is supported. + + ESS[SAS] was written with two primary goals. + 1. The emacs text editor provides a powerful and flexible development + environment for programming languages. These features are a boon + to all programmers and, with the help of ESS[SAS], to SAS users as + well. + 2. Although a departure from SAS Display Manager, ESS[SAS] provides + similar key definitions to give novice ESS[SAS] users a head start. + Also, inconvenient SAS Display Manager features, like remote + submission and syntax highlighting, are provided transparently; + appealing to advanced ESS[SAS] users. + + +File: ess.info, Node: ESS(SAS)--Editing files, Next: ESS(SAS)--TAB key, Prev: ESS(SAS)--Design philosophy, Up: ESS for SAS + +13.2 ESS[SAS]-Editing files +=========================== + +ESS[SAS] is the mode for editing SAS language files. This mode handles: + + * proper indenting, generated by both and . + * color and font choices based on syntax. + * ability to save and submit the file you are working on as a batch + SAS process with a single keypress and to continue editing while it + is runs in the background. + * capability of killing the batch SAS process through the '*shell*' + buffer or allow the SAS process to keep on running after you exit + emacs. + * single keypress navigation of '.sas', '.log' and '.lst' files + ('.log' and '.lst' files are refreshed with each keypress). + * ability to send the contents of an entire buffer, a highlighted + region, or a single line to an interactive SAS process. + * ability to switch between processes which would be the target of + the buffer (for the above). + + ESS[SAS] is automatically turned on when editing a file with a '.sas' +suffix (or other extension, if specified via 'auto-mode-alist'). The +function keys can be enabled to use the same function keys that the SAS +Display Manager does. The interactive capabilities of ESS require you +to start an inferior SAS process with 'M-x SAS' (*Note +iESS(SAS)--Interactive SAS processes::.) + + At this writing, the indenting and syntax highlighting are generally +correct. Known issues: for multiple line '*' or '%*' comments, only the +first line is highlighted; for '.log' files, only the first line of a +'NOTE:', 'WARNING:' or 'ERROR:' message is highlighted; unmatched +single/double quotes in 'CARDS' data lines are *NOT* ignored; in an +iterative 'DO' statement, 'TO' and 'BY' are not highlighted. + + +File: ess.info, Node: ESS(SAS)--TAB key, Next: ESS(SAS)--Batch SAS processes, Prev: ESS(SAS)--Editing files, Up: ESS for SAS + +13.3 ESS[SAS]- key +======================= + +Two options. The key is bound by default to 'sas-indent-line'. +This function is used to syntactically indent SAS code so 'PROC' and +'RUN' are in the left margin, other statements are indented +'sas-indent-width' spaces from the margin, continuation lines are +indented 'sas-indent-width' spaces in from the beginning column of that +statement. This is the type of functionality that emacs provides in +most programming language modes. This functionality is activated by +placing the following line in your initialization file prior to a +'require'/'load': + (setq ess-sas-edit-keys-toggle nil) + + ESS provides an alternate behavior for that makes it behave as +it does in SAS Display Manager, i.e. move the cursor to the next stop. +The alternate behavior also provides a "TAB" backwards, 'C-', that +moves the cursor to the stop to the left and deletes any characters +between them. This functionality is obtained by placing the following +line in your initialization file prior to a 'require'/'load': + (setq ess-sas-edit-keys-toggle t) + Under the alternate behavior, is bound to 'M-x tab-to-tab-stop' +and the stops are defined by 'ess-sas-tab-stop-list'. + + +File: ess.info, Node: ESS(SAS)--Batch SAS processes, Next: ESS(SAS)--Function keys for batch processing, Prev: ESS(SAS)--TAB key, Up: ESS for SAS + +13.4 ESS[SAS]-Batch SAS processes +================================= + +Submission of a SAS batch job is dependent on your environment. +'ess-sas-submit-method' is determined by your operating system and your +shell. It defaults to ''sh' unless you are running Windows or Mac +Classic. Under Windows, it will default to ''sh' if you are using a +UNIX-imitating shell; otherwise ''ms-dos' for an MS-DOS shell. On +macOS, it will default to ''sh', but under Mac Classic, it defaults to +''apple-script'. You will also set this to ''sh' if the SAS batch job +needs to run on a remote machine rather than your local machine. This +works transparently if you are editing the remote file via ange-ftp/EFS +or tramp. Note that 'ess-sas-shell-buffer-remote-init' is a Local +Variable that defaults to '"ssh"' which will be used to open the buffer +on the remote host and it is assumed that no password is necessary, i.e. +you are using 'ssh-agent'/'ssh-add' or the equivalent (see the +discussion about Local Variables below if you need to change the +default). + + However, if you are editing the file locally and transferring it back +and forth with Kermit, you need some additional steps. First, start +Kermit locally before remotely logging in. Open a local copy of the +file with the 'ess-kermit-prefix' character prepended (the default is +'"#"'). Execute the command 'M-x ess-kermit-get' which automatically +brings the contents of the remote file into your local copy. If you +transfer files with Kermit manually in a '*shell*' buffer, then note +that the Kermit escape sequence is 'C-q C-\ c' rather than 'C-\ c' which +it would be in an ordinary terminal application, i.e. not in an emacs +buffer. Lastly, note that the remote Kermit command is specified by +'ess-kermit-command'. + + The command used by the 'SUBMIT' function key ( or ) to +submit a batch SAS job, whether local or remote, is +'ess-sas-submit-command' which defaults to 'sas-program'. 'sas-program' +is '"invoke SAS using program file"' for Mac Classic and '"sas"' +otherwise. However, you may have to alter 'ess-sas-submit-command' for +a particular program, so it is defined as buffer-local. Conveniently, +it can be set at the end of the program: + endsas; + Local variables: + ess-sas-submit-command: "sas8" + End: + + The command line is also made of 'ess-sas-submit-pre-command', +'ess-sas-submit-post-command' and 'ess-sas-submit-command-options' (the +last of which is also buffer-local). Here are some examples for your +'~/.emacs' or '~/.emacs.d/init.el' file (you may also use +'M-x customize-variable'): + ;'sh default + (setq ess-sas-submit-pre-command "nohup") + ;'sh default + (setq ess-sas-submit-post-command "-rsasuser &") + ;'sh example + (setq-default ess-sas-submit-command "/usr/local/sas/sas") + ;'ms-dos default + (setq ess-sas-submit-pre-command "start") + ;'ms-dos default + (setq ess-sas-submit-post-command "-rsasuser -icon") + ;Windows example + (setq-default ess-sas-submit-command "c:/progra~1/sas/sas.exe") + ;Windows example + (setq-default ess-sas-submit-command "c:\\progra~1\\sas\\sas.exe") + + There is a built-in delay before a batch SAS job is submitted when +using a UNIX-imitating shell under Windows. This is necessary in many +cases since the shell might not be ready to receive a command. This +delay is currently set high enough so as not to be a problem. But, +there may be cases when it needs to be set higher, or could be set much +lower to speed things up. You can over-ride the default in your +'~/.emacs' or '~/.emacs.d/init.el' file by: + (setq ess-sleep-for 0.2) + + For example, '(setq ess-sas-global-unix-keys t)' keys shown, '(setq +ess-sas-global-pc-keys t)' in parentheses; ESS[SAS] function keys are +presented in the next section. Open the file you want to work with +'C-x C-f foo.sas'. 'FOO.sas' will be in ESS[SAS] mode. Edit as +appropriate, then save and submit the batch SAS job. + () + The job runs in the '*shell*' buffer while you continue to edit +'FOO.sas'. If 'ess-sas-submit-method' is ''sh', then the message buffer +will display the shell notification when the job is complete. The ''sh' +setting also allows you to terminate the SAS batch job before it is +finished. + () + Terminating a SAS batch in the '*shell*' buffer. + kill PID + You may want to visit the '.log' (whether the job is still running or +it is finished) and check for error messages. The '.log' will be +refreshed and you will be placed in it's buffer. You will be taken to +the first error message, if any. + () + Goto the next error message, if any. + () + Now, 'refresh' the '.lst' and go to it's buffer. + () + If you wish to make changes, go to the '.sas' file with. + () + Make your editing changes and submit again. + () + + +File: ess.info, Node: ESS(SAS)--Function keys for batch processing, Next: iESS(SAS)--Interactive SAS processes, Prev: ESS(SAS)--Batch SAS processes, Up: ESS for SAS + +13.5 ESS[SAS]-Function keys for batch processing +================================================ + +The setup of function keys for SAS batch processing is unavoidably +complex, but the usage of function keys is simple. There are five +distinct options: + + Option 1 (default). Function keys in ESS[SAS] are not bound to Elisp +commands. This is in accordance with the GNU Elisp Coding Standards +(GECS) which do not allow function keys to be bound so that they are +available to the user. + + Options 2-5. Since GECS does not allow function keys to be bound by +modes, these keys are often unused. So, ESS[SAS] provides users with +the option of binding Elisp commands to these keys. Users who are +familiar with SAS will, most likely, want to duplicate the function key +capabilities of the SAS Display Manager. There are four options (noted +in parentheses). + + a. SAS Display Manager has different function key definitions for UNIX + (2, 4) and Windows (3, 5); ESS[SAS] can use either. + b. The ESS[SAS] function key definitions can be active in all buffers + (global: 4, 5) or limited (local: 2, 3) only to buffers with files + that are associated with ESS[SAS] as specified in your + 'auto-mode-alist'. + + The distinction between local and global is subtle. If you want the +ESS[SAS] definitions to work when you are in the '*shell*' buffer or +when editing files other than the file extensions that ESS[SAS] +recognizes, you will most likely want to use the global definitions. If +you want your function keys to understand SAS batch commands when you +are editing SAS files, and to behave normally when editing other files, +then you will choose the local definitions. The option can be chosen by +the person installing ESS for a site or by an individual. + + a. For a site installation or an individual, place *ONLY ONE* of the + following lines in your initialization file prior to a + 'require'/'load'. ESS[SAS] function keys are available in ESS[SAS] + if you choose either 2 or 3 and in all modes if you choose 4 or 5: + ;;2; (setq ess-sas-local-unix-keys t) + ;;3; (setq ess-sas-local-pc-keys t) + ;;4; (setq ess-sas-global-unix-keys t) + ;;5; (setq ess-sas-global-pc-keys t) + + The names '-unix-' and '-pc-' have nothing to do with the operating + system that you are running. Rather, they mimic the definitions + that the SAS Display Manager uses by default on those platforms. + + b. If your site installation has configured the keys contrary to your + liking, then you must call the appropriate function. + (load "ess-site") ;; local-unix-keys + (ess-sas-global-pc-keys) + + Finally, we get to what the function keys actually do. You may +recognize some of the nicknames as SAS Display Manager commands (they +are in all capitals). + +UNIX PC Nickname + 'refresh' + revert the current buffer with the file of the same name if the file is + newer than the buffer + 'SUBMIT' + save the current '.sas' file (which is either the '.sas' file in the + current buffer or the '.sas' file associated with the '.lst' or '.log' + file in the current buffer) and submit the file as a batch SAS job + 'PROGRAM' + switch buffer to '.sas' file + 'LOG' + switch buffer to '.log' file, 'refresh' and goto next error message, if + any + 'OUTPUT' + switch buffer to '.lst' file and 'refresh' + 'filetype-1' + switch buffer to 'filetype-1' (defaults to '.txt') file and 'refresh' + 'shell' + switch buffer to '*shell*' + 'VIEWTABLE' + open an interactive 'PROC FSEDIT' session on the SAS dataset near point + toggle-log + toggle ESS[SAS] for '.log' files; useful for certain debugging situations + 'filetype-2' + switch buffer to 'filetype-2' (defaults to '.dat') file and 'refresh' + viewgraph + open a 'GSASFILE' near point for viewing either in emacs or with an + external viewer +'C-' 'C-' rtf-portrait + create an MS RTF portrait file from the current buffer with a file + extension of '.rtf' +'C-' 'C-' rtf-landscape + create an MS RTF landscape file from the current buffer with a file + extension of '.rtf' +'C-' 'C-' submit-region + write region to 'ess-temp.sas' and submit +'C-' 'C-' append-to-log + append 'ess-temp.log' to the current '.log' file +'C-' 'C-' append-to-output + append 'ess-temp.lst' to the current '.lst' file +'C-' 'C-' 'INSIGHT' + open an interactive 'PROC INSIGHT' session on the SAS dataset near point +'C-''C-'toggle-listing + toggle ESS[SAS] for '.lst' files; useful for toggling read-only + + 'SUBMIT', 'PROGRAM', 'LOG' and 'OUTPUT' need no further explanation +since they mimic the SAS Display Manager commands and related function +key definitions. However, six other keys have been provided for +convenience and are described below. + + 'shell' switches you to the '*shell*' buffer where you can interact +with your operating system. This is especially helpful if you would +like to kill a SAS batch job. You can specify a different buffer name +to associate with a SAS batch job (besides '*shell*') with the +buffer-local variable 'ess-sas-shell-buffer'. This allows you to have +multiple buffers running SAS batch jobs on multiple local/remote +computers that may rely on different methods specified by the +buffer-local variable 'ess-sas-submit-method'. + + performs the 'refresh' operation on the current buffer. +'refresh' compares the buffer's last modified date/time with the file's +last modified date/time and replaces the buffer with the file if the +file is newer. This is the same operation that is automatically +performed when 'LOG', 'OUTPUT', 'filetype-1' or are pressed. + + 'filetype-1' switches you to a file with the same file name as your +'.sas' file, but with a different extension ('.txt' by default) and +performs 'refresh'. You can over-ride the default extension; for +example in your '~/.emacs' or '~/.emacs.d/init.el' file: + (setq ess-sas-suffix-1 "csv") ; for example + + will prompt you for the name of a permanent SAS dataset near +point to be opened for viewing by 'PROC FSEDIT'. You can control the +SAS batch command-line with 'ess-sas-data-view-submit-options'. For +controlling the SAS batch commands, you have the global variables +'ess-sas-data-view-libname' and 'ess-sas-data-view-fsview-command' as +well as the buffer-local variable 'ess-sas-data-view-fsview-statement'. +If you have your SAS 'LIBNAME' defined in '~/autoexec.sas', then the +defaults for these variables should be sufficient. + + Similarly, 'C-' will prompt you for the name of a permanent SAS +dataset near point to be opened for viewing by 'PROC INSIGHT'. You can +control the SAS batch command-line with +'ess-sas-data-view-submit-options'. For controlling the SAS batch +commands, you have the global variables 'ess-sas-data-view-libname' and +'ess-sas-data-view-insight-command' as well as the buffer-local variable +'ess-sas-data-view-insight-statement'. + + toggles ESS[SAS] mode for '.log' files which is off by default +(technically, it is 'SAS-log-mode', but it looks the same). The syntax +highlighting can be helpful in certain debugging situations, but large +'.log' files may take a long time to highlight. + + is the same as 'filetype-1' except it is '.dat' by default. + + will prompt you for the name of a 'GSASFILE' near the point in +'.log' to be opened for viewing either with emacs or with an external +viewer. Depending on your version of emacs and the operating system you +are using, emacs may support '.gif' and '.jpg' files internally. You +may need to change the following variables for your own situation. +'ess-sas-graph-view-suffix-regexp' is a regular expression of supported +file types defined via file name extensions. +'ess-sas-graph-view-viewer-default' is the default external viewer for +your platform. 'ess-sas-graph-view-viewer-alist' is an alist of +exceptions to the default; i.e. file types and their associated viewers +which will be used rather than the default viewer. + (setq ess-sas-graph-view-suffix-regexp (concat "[.]\\([eE]?[pP][sS]\\|" + "[pP][dD][fF]\\|[gG][iI][fF]\\|[jJ][pP][eE]?[gG]\\|" + "[tT][iI][fF][fF]?\\)")) ;; default + (setq ess-sas-graph-view-viewer-default "kodakimg") ;; Windows default + (setq ess-sas-graph-view-viewer-default "sdtimage") ;; Solaris default + (setq ess-sas-graph-view-viewer-alist + '(("[eE]?[pP][sS]" . "gv") ("[pP][dD][fF]" . "gv")) ;; default w/ gv + + 'C-' produces US landscape by default, however, it can produce A4 +landscape (first line for "global" key mapping, second for "local"): + (global-set-key [(control f2)] 'ess-sas-rtf-a4-landscape) + (define-key sas-mode-local-map [(control f2)] 'ess-sas-rtf-a4-landscape) + + +File: ess.info, Node: iESS(SAS)--Interactive SAS processes, Next: iESS(SAS)--Common problems, Prev: ESS(SAS)--Function keys for batch processing, Up: ESS for SAS + +13.6 iESS[SAS]-Interactive SAS processes +======================================== + +Inferior ESS (iESS) is the method for interfacing with interactive +statistical processes (programs). iESS[SAS] is what is needed for +interactive SAS programming. iESS[SAS] works best with the SAS +command-line option settings '"-stdio -linesize 80 -noovp +-nosyntaxcheck"' (the default of 'inferior-SAS-args'). + + '-stdio' + required to make the redirection of stdio work + '-linesize 80' + keeps output lines from folding on standard terminals + '-noovp' + prevents error messages from printing 3 times + '-nosyntaxcheck' + permits recovery after syntax errors + + To start up iESS[SAS] mode, use: + M-x SAS + + The '*SAS:1.log*' buffer in 'ESStr' mode corresponds to the file +'FOO.log' in SAS batch usage and to the 'SAS: LOG' window in the SAS +Display Manager. All commands submitted to SAS, informative messages, +warnings, and errors appear here. + + The '*SAS:1.lst*' buffer in 'ESSlst' mode corresponds to the file +'FOO.lst' in SAS batch usage and to the 'SAS: OUTPUT' window in the SAS +Display Manager. All printed output appears in this window. + + The '*SAS:1*' buffer exists solely as a communications buffer. The +user should never use this buffer directly. Files are edited in the +'FOO.sas' buffer. The 'C-c C-r' key in ESS[SAS] is the functional +equivalent of bringing a file into the 'SAS: PROGRAM EDITOR' window +followed by 'SUBMIT'. + + For example, open the file you want to work with. + C-x C-f foo.sas + 'FOO.sas' will be in ESS[SAS] mode. Edit as appropriate, and then +start up SAS with the cursor in the 'FOO.sas' buffer. + M-x SAS + Four buffers will appear on screen: +Buffer Mode Description +'FOO.sas' 'ESS[SAS]' your source file +'*SAS:1*' 'iESS[SAS:1]' iESS communication buffer +'*SAS:1.log*' 'Shell ESStr SAS log information + []' +'*SAS:1.lst*' 'Shell ESSlst SAS listing information + []' + If you would prefer each of the four buffers to appear in its own +individual frame, you can arrange for that. Place the cursor in the +buffer displaying 'FOO.sas'. Enter the sequence 'C-c C-w'. The cursor +will normally be in buffer 'FOO.sas'. If not, put it there and +'C-x b FOO.sas'. + + Send regions, lines, or the entire file contents to SAS (regions are +most useful: a highlighted region will normally begin with the keywords +'DATA' or 'PROC' and end with 'RUN;'), 'C-c C-r'. + + Information appears in the log buffer, analysis results in the +listing buffer. In case of errors, make the corrections in the +'FOO.sas' buffer and resubmit with another 'C-c C-r'. + + At the end of the session you may save the log and listing buffers +with the usual 'C-x C-s' commands. You will be prompted for a file +name. Typically, the names 'FOO.log' and 'FOO.lst' will be used. You +will almost certainly want to edit the saved files before including them +in a report. The files are read-only by default. You can make them +writable by the emacs command 'C-x C-q'. + + At the end of the session, the input file 'FOO.sas' will typically +have been revised. You can save it. It can be used later as the +beginning of another iESS[SAS] session. It can also be used as a batch +input file to SAS. + + The '*SAS:1*' buffer is strictly for ESS use. The user should never +need to read it or write to it. Refer to the '.lst' and '.log' buffers +for monitoring output! + + Troubleshooting: *Note iESS(SAS)--Common problems::. + + +File: ess.info, Node: iESS(SAS)--Common problems, Next: ESS(SAS)--Graphics, Prev: iESS(SAS)--Interactive SAS processes, Up: ESS for SAS + +13.7 iESS[SAS]-Common problems +============================== + + 1. iESS[SAS] does not work on Windows. In order to run SAS inside an + emacs buffer, it is necessary to start SAS with the '-stdio' + option. SAS does not support the '-stdio' option on Windows. + 2. If 'M-x SAS' gives errors upon startup, check the following: + * you are running Windows: see 1. + * 'ess-sas-sh-command' (from the ESS 'etc' directory) needs to + be executable; too check, type 'M-x dired'; if not, fix it as + follows, type 'M-:', then at the minibuffer prompt 'Eval:', + type '(set-file-modes "ess-sas-sh-command" 493)'. + * 'sas' isn't in your executable path; to verify, type 'M-:' and + at the minibuffer prompt 'Eval:', type '(executable-find + "sas")' + 3. 'M-x SAS' starts SAS Display Manager. Probably, the command 'sas' + on your system calls a shell script. In that case you will need to + locate the real 'sas' executable and link to it. You can execute + the UNIX command: + find / -name sas -print + Now place a soft link to the real 'sas' executable in your '~/bin' + directory, with for example + cd ~/bin + ln -s /usr/local/sas9/sas sas + Check your 'PATH' environment variable to confirm that '~/bin' +appears before the directory in which the 'sas' shell script appears. + + +File: ess.info, Node: ESS(SAS)--Graphics, Next: ESS(SAS)--Windows, Prev: iESS(SAS)--Common problems, Up: ESS for SAS + +13.8 ESS[SAS]-Graphics +====================== + +Output from a SAS/GRAPH 'PROC' can be displayed in a SAS/GRAPH window +for SAS batch on Windows or for both SAS batch and interactive with +XWindows on UNIX. If you need to create graphics files and view them +with , then include the following (either in 'FOO.sas' or in +'~/autoexec.sas'): + filename gsasfile 'graphics.ps'; + goptions device=ps gsfname=gsasfile gsfmode=append; + 'PROC PLOT' graphs can be viewed in the listing buffer. You may wish +to control the vertical spacing to allow the entire plot to be visible +on screen, for example: + proc plot; + plot a*b / vpos=25; + run; + + +File: ess.info, Node: ESS(SAS)--Windows, Prev: ESS(SAS)--Graphics, Up: ESS for SAS + +13.9 ESS[SAS]-Windows +===================== + + * iESS[SAS] does not work on Windows. *Note iESS(SAS)--Common + problems::. + + * ESS[SAS] mode for editing SAS language files works very well. + *Note ESS(SAS)--Editing files::. + + * There are two execution options for SAS on Windows. You can use + batch. *Note ESS(SAS)--Batch SAS processes::. + + Or you can mark regions with the mouse and submit the code with + 'submit-region' or paste them into SAS Display Manager. + + +File: ess.info, Node: ESS for BUGS, Next: ESS for JAGS, Prev: ESS for SAS, Up: Top + +14 ESS for BUGS +*************** + +ESS[BUGS] provides 5 features. First, BUGS syntax is described to allow +for proper fontification of statements, distributions, functions, +commands and comments in BUGS model files, command files and log files. +Second, ESS creates templates for the command file from the model file +so that a BUGS batch process can be defined by a single file. Third, +ESS provides a BUGS batch script that allows ESS to set BUGS batch +parameters. Fourth, key sequences are defined to create a command file +and submit a BUGS batch process. Lastly, interactive submission of BUGS +commands is also supported. + +14.1 ESS[BUGS]-Model files +========================== + +Model files with the '.bug' extension are edited in ESS[BUGS] mode. +Three keys are bound for your use in ESS[BUGS], 'F2', 'C-c C-c' and '='. +'F2' performs the same action as it does in ESS[SAS], *Note +ESS(SAS)--Function keys for batch processing::. 'C-c C-c' performs the +function 'ess-bugs-next-action' which you will use a lot. Pressing it +in an empty buffer for a model file will produce a template for you. +'=' inserts the set operator, '<-'. + +14.2 ESS[BUGS]-Command files +============================ + +Files ending in '.bmd' are used for BUGS command files. When you have +finished editing your model file and press 'C-c C-c', a command file is +created if one does not already exist. When you are finished editing +your command file, pressing 'C-c C-c' again will submit your command +file as a batch job. + +14.3 ESS[BUGS]-Log files +======================== + +The '.bog' extension is used for BUGS log files. The command line +generated by ESS creates the '.bog' transcript file. + + +File: ess.info, Node: ESS for JAGS, Next: Mailing lists/bug reports, Prev: ESS for BUGS, Up: Top + +15 ESS for JAGS +*************** + +ESS[JAGS] provides 4 features. First, JAGS syntax is described to allow +for proper fontification of statements, distributions, functions, +commands and comments in JAGS model files, command files and log files. +Second, ESS creates templates for the command file from the model file +so that a JAGS batch process can be defined by a single file. Third, +ESS provides a JAGS batch script that allows ESS to set JAGS batch +parameters. Fourth, key sequences are defined to create a command file +and submit a JAGS batch process. + +15.1 ESS[JAGS]-Model files +========================== + +Files with the '.jag' extension are edited in ESS[JAGS] mode. Three +keys are bound for your use in ESS[JAGS], 'F2', 'C-c C-c' and '='. 'F2' +performs the same action as it does in ESS[SAS], *Note +ESS(SAS)--Function keys for batch processing::. 'C-c C-c' performs the +function 'ess-bugs-next-action' which you will use a lot. Pressing it +in an empty buffer for a model file will produce a template for you. +'=' inserts the set operator, '<-'. + + The first press of 'C-c C-c' will set up a template, including some +necessary file-local variables in an empty buffer. These variables are +'ess-jags-chains', 'ess-jags-monitor', 'ess-jags-thin', +'ess-jags-burnin' and 'ess-jags-update'; they appear in the 'Local +Variables' section. When you are finished editing your model file, +pressing 'C-c C-c' will perform the necessary actions to build your +command file for you. + + The 'ess-jags-chains' variable is the number of chains that you want +to initialize and sample from; defaults to 1. The 'ess-jags-monitor' +variable is a list of variables that you want monitored: encase each +variable in double quotes. When you press 'C-c C-c', the appropriate +statements are created in the command file to monitor the list of +variables. By default, no variables are explicitly monitored which +means JAGS will implicitly monitor all "default" variables. The +'ess-jags-thin' variable is the thinning parameter. By default, the +thinning parameter is set to 1, i.e. no thinning. The +'ess-jags-burnin' variable is the number of initial samples to discard. +By default, the burnin parameter is set to 10000. The 'ess-jags-update' +variable is the number of post-burnin samples to keep. By default, the +update parameter is set to 10000. Both 'ess-jags-burnin' and +'ess-jags-update' are multiplied by 'ess-jags-thin' since JAGS does not +do it automatically. + +15.2 ESS[JAGS]-Command files +============================ + +Files ending in '.jmd' are for JAGS command files. For your '.jmd' +file, there is only one variable, 'ess-jags-command', in the 'Local +Variables' section. When you have finished editing your model file and +press 'C-c C-c', a command file is created if one does not already +exist. When you are finished editing your command file, pressing 'C-c +C-c' again will submit your command file as a batch job. The +'ess-jags-command' variable allows you to specify a different JAGS +program to use to run your model; defaults to "jags". + +15.3 ESS[JAGS]-Log files +======================== + +The '.jog' extension is used for JAGS log files. You may find 'F2' +useful to refresh the '.jog' if the batch process over-writes or appends +it. + + +File: ess.info, Node: Mailing lists/bug reports, Next: Customization, Prev: ESS for JAGS, Up: Top + +16 Bugs and Bug Reporting, Mailing Lists +**************************************** + +* Menu: + +* Bugs:: +* Reporting Bugs:: +* Mailing Lists:: +* Help with Emacs:: + + +File: ess.info, Node: Bugs, Next: Reporting Bugs, Up: Mailing lists/bug reports + +16.1 Bugs +========= + + * Commands like 'ess-display-help-on-object' and list completion + cannot be used while the user is entering a multi-line command. + The only real fix in this situation is to use another ESS process. + + * The 'ess-eval-' commands can leave point in the ESS process buffer + in the wrong place when point is at the same position as the last + process output. This proves difficult to fix, in general, as we + need to consider all _windows_ with 'window-point' at the right + place. + + * It's possible to clear the modification flag (say, by saving the + buffer) with the edit buffer not having been loaded into S. + + * Backup files can sometimes be left behind, even when + 'ess-keep-dump-files' is 'nil'. + + * Passing an incomplete S expression to 'ess-execute' causes ESS to + hang. + + * The function-based commands don't always work as expected on + functions whose body is not a parenthesized or compound expression, + and don't even recognize anonymous functions (i.e. functions not + assigned to any variable). + + * Multi-line commands could be handled better by the command history + mechanism. + + * Changes to the continuation prompt in R (e.g. 'options(continue = + " ")') are not automatically detected by ESS. Hence, for now, the + best thing is not to change the continuation prompt. If you do + change the continuation prompt, you will need to change accordingly + the value of 'inferior-ess-secondary-prompt' in + 'R-customize-alist'. + + +File: ess.info, Node: Reporting Bugs, Next: Mailing Lists, Prev: Bugs, Up: Mailing lists/bug reports + +16.2 Reporting Bugs +=================== + +Please send bug reports, suggestions etc. to , +or post them on our github issue tracker +(https://github.com/emacs-ess/ESS/issues) + + The easiest way to do this is within Emacs by typing + + 'M-x ess-submit-bug-report' + + This also gives the maintainers valuable information about your +installation which may help us to identify or even fix the bug. + + If Emacs reports an error, backtraces can help us debug the problem. +Type "M-x set-variable RET debug-on-error RET t RET". Then run the +command that causes the error and you should see a *Backtrace* buffer +containing debug information; send us that buffer. + + Note that comments, suggestions, words of praise and large cash +donations are also more than welcome. + + +File: ess.info, Node: Mailing Lists, Next: Help with Emacs, Prev: Reporting Bugs, Up: Mailing lists/bug reports + +16.3 Mailing Lists +================== + +There is a mailing list for discussions and announcements relating to +ESS. Join the list by sending an e-mail with "subscribe ess-help" (or +"help") in the body to ; contributions +to the list may be mailed to . Rest assured, +this is a fairly low-volume mailing list. + + The purposes of the mailing list include + + * helping users of ESS to get along with it. + * discussing aspects of using ESS. + * suggestions for improvements. + * announcements of new releases of ESS. + * posting small patches to ESS. + + +File: ess.info, Node: Help with Emacs, Prev: Mailing Lists, Up: Mailing lists/bug reports + +16.4 Help with Emacs +==================== + +Emacs is a complex editor with many abilities that we do not have space +to describe here. If you have problems with other features of Emacs +(e.g. printing), there are several sources to consult, including the +Emacs FAQs (try 'M-x view-emacs-faq') and EmacsWiki +(). Please consult them before asking on the +mailing list about issues that are not specific to ESS. + + +File: ess.info, Node: Customization, Next: Indices, Prev: Mailing lists/bug reports, Up: Top + +Appendix A Customizing ESS +************************** + +ESS can be easily customized to your taste simply by including the +appropriate lines in your Emacs configuration file. There are numerous +variables which affect the behavior of ESS in certain situations which +can be modified to your liking. Keybindings may be set or changed to +your preferences, and for per-buffer customizations hooks are also +available. + + Most of these variables can be viewed and set using the Custom +facility within Emacs. Type 'M-x customize-group RET ess RET' to see +all the ESS variables that can be customized. Variables are grouped by +subject to make it easy to find related variables. + + +File: ess.info, Node: Indices, Prev: Customization, Up: Top + +Indices +******* + +* Menu: + +* Key index:: +* Function and program index:: +* Variable index:: +* Concept index:: + + +File: ess.info, Node: Key index, Next: Function and program index, Up: Indices + +Key index +========= + +[index] +* Menu: + +* ,: Handy commands. (line 6) +* {: Indenting. (line 53) +* }: Indenting. (line 53) +* C-c C-. d: Package listing. (line 30) +* C-c C-. H: Package listing. (line 33) +* C-c C-. l: Package listing. (line 10) +* C-c C-. m: Package listing. (line 21) +* C-c C-. r: Package listing. (line 13) +* C-c C-. s: Package listing. (line 27) +* C-c C-. u: Package listing. (line 17) +* C-c C-. w: Package listing. (line 24) +* C-c C-b: Evaluating code. (line 68) +* C-c C-c: Other. (line 9) +* C-c C-c <1>: Evaluating code. (line 41) +* C-c C-e C-d: Edit buffer. (line 9) +* C-c C-e C-s: Styles. (line 15) +* C-c C-e s: Styles. (line 15) +* C-c C-f: Evaluating code. (line 54) +* C-c C-j: Evaluating code. (line 47) +* C-c C-o C-c: roxygen2. (line 45) +* C-c C-o C-h: roxygen2. (line 72) +* C-c C-o C-o: roxygen2. (line 37) +* C-c C-o C-r: roxygen2. (line 51) +* C-c C-o C-t: roxygen2. (line 59) +* C-c C-o n: roxygen2. (line 69) +* C-c C-o p: roxygen2. (line 66) +* C-c C-q: Hot keys. (line 71) +* C-C C-r: Evaluating code. (line 61) +* C-c C-s: Hot keys. (line 34) +* C-c C-t C-s: Namespaced Evaluation. + (line 36) +* C-c C-v: Hot keys. (line 66) +* C-c C-w: Clean. (line 11) +* C-c C-x: Hot keys. (line 24) +* C-c C-z: Other. (line 13) +* C-c M-b: Evaluating code. (line 71) +* C-c M-f: Evaluating code. (line 57) +* C-c M-j: Evaluating code. (line 50) +* C-c M-l: Hot keys. (line 50) +* C-c M-r: Evaluating code. (line 64) +* C-c RET: Resubmit. (line 14) +* C-c `: Error Checking. (line 9) +* C-j: Indenting. (line 60) +* C-M-a: Other edit buffer commands. + (line 10) +* C-M-e: Other edit buffer commands. + (line 14) +* C-M-h: Other edit buffer commands. + (line 18) +* C-M-q: Indenting. (line 49) +* C-M-x: Evaluating code. (line 38) +* C-RET: Evaluating code. (line 34) +* ESC C-a: Other edit buffer commands. + (line 10) +* ESC C-e: Other edit buffer commands. + (line 14) +* ESC C-h: Other edit buffer commands. + (line 18) +* ESC C-q: Indenting. (line 49) +* M-;: Indenting. (line 65) +* M-?: Object names. (line 33) +* M-C-q: Indenting. (line 49) +* M-n l: Sweave and AUCTeX. (line 24) +* M-n P: Sweave and AUCTeX. (line 30) +* M-n s: Sweave and AUCTeX. (line 20) +* M-RET: Resubmit. (line 10) +* RET: Command-line editing. (line 10) +* RET <1>: Resubmit. (line 18) +* TAB: Indenting. (line 35) + + +File: ess.info, Node: Function and program index, Next: Variable index, Prev: Key index, Up: Indices + +Function and program index +========================== + +[index] +* Menu: + +* backward-kill-word: Command-line editing. + (line 22) +* comint-backward-matching-input: Process buffer motion. + (line 31) +* comint-bol: Command-line editing. + (line 31) +* comint-copy-old-input: Transcript resubmit. (line 16) +* comint-delete-output: Last command. (line 24) +* comint-dynamic-complete: Object names. (line 12) +* comint-forward-matching-input: Process buffer motion. + (line 32) +* comint-history-isearch-backward-regexp: Command History. (line 32) +* comint-interrupt-subjob: Other. (line 8) +* comint-kill-input: Command-line editing. + (line 26) +* comint-next-input: Command History. (line 18) +* comint-next-matching-input-from-input: Command History. (line 45) +* comint-next-prompt: Process buffer motion. + (line 15) +* comint-previous-input: Command History. (line 14) +* comint-previous-matching-input-from-input: Command History. (line 41) +* comint-previous-prompt: Process buffer motion. + (line 11) +* comint-show-output: Last command. (line 20) +* dump(): Edit buffer. (line 35) +* ess-change-directory: Package listing. (line 29) +* ess-cleanup: Hot keys. (line 71) +* ess-cleanup <1>: Help. (line 170) +* ess-complete-object-name: Object names. (line 32) +* ess-describe-help-mode: Help. (line 21) +* ess-display-help-on-object: Hot keys. (line 65) +* ess-display-help-on-object <1>: Help. (line 8) +* ess-display-help-on-object <2>: Help. (line 25) +* ess-dump-object-into-edit-buffer: Edit buffer. (line 8) +* ess-electric-brace: Indenting. (line 52) +* ess-eval-buffer: Evaluating code. (line 67) +* ess-eval-buffer-and-go: Evaluating code. (line 70) +* ess-eval-function: Evaluating code. (line 53) +* ess-eval-function-and-go: Evaluating code. (line 56) +* ess-eval-line: Evaluating code. (line 46) +* ess-eval-line-and-go: Evaluating code. (line 49) +* ess-eval-line-and-step: Help. (line 106) +* ess-eval-region: Evaluating code. (line 60) +* ess-eval-region <1>: Help. (line 111) +* ess-eval-region-and-go: Evaluating code. (line 63) +* ess-eval-region-or-function-or-paragraph: Evaluating code. (line 37) +* ess-eval-region-or-function-or-paragraph-and-step: Evaluating code. + (line 40) +* ess-eval-region-or-line-and-step: Evaluating code. (line 33) +* ess-execute-objects: Hot keys. (line 23) +* ess-execute-search: Hot keys. (line 33) +* ess-goto-beginning-of-function-or-para: Other edit buffer commands. + (line 9) +* ess-goto-end-of-function-or-para: Other edit buffer commands. + (line 13) +* ess-handy-commands: Handy commands. (line 6) +* ess-handy-commands <1>: Handy commands. (line 6) +* ess-indent-command: roxygen2. (line 90) +* ess-indent-exp: Indenting. (line 48) +* ess-indent-or-complete: Indenting. (line 34) +* ess-load-file: Hot keys. (line 49) +* ess-load-file <1>: Loading. (line 11) +* ess-mark-function: Other edit buffer commands. + (line 17) +* ess-parse-errors: Hot keys. (line 54) +* ess-parse-errors <1>: Error Checking. (line 9) +* ess-quit: Hot keys. (line 70) +* ess-quit <1>: Help. (line 170) +* ess-R-complete-object-name: roxygen2. (line 80) +* ess-r-package-list-available-packages: Package listing. (line 12) +* ess-r-package-list-local-packages: Package listing. (line 9) +* ess-r-package-update-packages: Package listing. (line 16) +* ess-r-set-evaluation-env: Namespaced Evaluation. + (line 35) +* ess-remote: ESS processes on Remote Computers. + (line 9) +* ess-request-a-process: Multiple ESS processes. + (line 18) +* ess-resynch: Object names. (line 52) +* ess-roxy-hide-all: roxygen2. (line 71) +* ess-roxy-move-beginning-of-line: roxygen2. (line 97) +* ess-roxy-next-entry: roxygen2. (line 68) +* ess-roxy-preview-HTML: roxygen2. (line 58) +* ess-roxy-preview-Rd: roxygen2. (line 50) +* ess-roxy-previous-entry: roxygen2. (line 65) +* ess-roxy-toggle-roxy-region: roxygen2. (line 44) +* ess-roxy-update-entry: roxygen2. (line 36) +* ess-rutils-html-docs: Package listing. (line 32) +* ess-rutils-load-workspace: Package listing. (line 23) +* ess-rutils-rm-all: Package listing. (line 20) +* ess-rutils-save-workspace: Package listing. (line 26) +* ess-set-style: Styles. (line 14) +* ess-skip-to-help-section: Help. (line 55) +* ess-skip-to-next-section: Help. (line 46) +* ess-skip-to-previous-section: Help. (line 46) +* ess-smart-comma: Handy commands. (line 6) +* ess-submit-bug-report: Reporting Bugs. (line 6) +* ess-switch-to-end-of-ESS: Help. (line 117) +* ess-switch-to-inferior-or-script-buffer: Other. (line 12) +* ess-swv-latex: Sweave and AUCTeX. (line 23) +* ess-swv-PDF: Sweave and AUCTeX. (line 29) +* ess-swv-PS: Sweave and AUCTeX. (line 26) +* ess-swv-weave: Sweave and AUCTeX. (line 19) +* ess-tracebug: ESS tracebug. (line 6) +* ess-transcript-clean-region: Clean. (line 10) +* ess-transcript-copy-command: Resubmit. (line 13) +* ess-transcript-send-command: Resubmit. (line 9) +* ess-transcript-send-command-and-move: Resubmit. (line 17) +* ess-use-ido, ess-completing-read: Minibuffer completion. + (line 6) +* fill-paragraph: roxygen2. (line 94) +* getting started with tracebug: Getting started with tracebug. + (line 6) +* inferior-ess-send-input: Command-line editing. + (line 9) +* mark-paragraph: roxygen2. (line 85) +* newline-and-indent: roxygen2. (line 102) +* objects(): Hot keys. (line 24) +* printer(): printer. (line 11) +* q(): Hot keys. (line 71) +* R: Starting up. (line 11) +* S: Starting up. (line 11) +* search(): Hot keys. (line 34) +* search() <1>: Object names. (line 19) +* source(): Evaluating code. (line 20) +* source() <1>: Loading. (line 11) +* STERM: Statistical Process running in ESS?. + (line 6) + + +File: ess.info, Node: Variable index, Next: Concept index, Prev: Function and program index, Up: Indices + +Variable index +============== + +[index] +* Menu: + +* comint-delimiter-argument-list: History expansion. (line 28) +* comint-input-ring-size: Command History. (line 9) +* comment-column: Indenting. (line 24) +* ess-ask-about-transfile: Customizing startup. (line 36) +* ess-ask-about-transfile <1>: Saving transcripts. (line 12) +* ess-ask-for-ess-directory: Customizing startup. (line 7) +* ess-ask-for-ess-directory <1>: Customizing startup. (line 21) +* ess-auto-width: Customizing startup. (line 56) +* ess-auto-width-visible: Customizing startup. (line 56) +* ess-delete-dump-files: Source Files. (line 12) +* ess-directory: Source Directories. (line 48) +* ess-dump-filename-template: Source Directories. (line 9) +* ess-eldoc-abbreviation-style: ESS ElDoc. (line 24) +* ess-eldoc-show-on-symbol: ESS ElDoc. (line 18) +* ess-eval-visibly: Evaluating code. (line 14) +* ess-execute-in-process-buffer: Hot keys. (line 13) +* ess-first-tab-never-complete: Indenting. (line 42) +* ess-first-tab-never-complete <1>: Object names. (line 6) +* ess-function-template: Edit buffer. (line 17) +* ess-handy-commands: Handy commands. (line 6) +* ess-handy-commands <1>: Handy commands. (line 9) +* ess-indent-with-fancy-comments: Indenting. (line 27) +* ess-keep-dump-files: Source Files. (line 26) +* ess-plain-first-buffername: Multiple ESS processes. + (line 14) +* ess-post-run-hook: Customizing startup. (line 26) +* ess-pre-run-hook: Customizing startup. (line 21) +* ess-r-flymake-linters: ESS Flymake. (line 16) +* ess-r-flymake-lintr-cache: ESS Flymake. (line 23) +* ess-R-font-lock-keywords: Highlighting. (line 19) +* ess-search-list: Source Directories. (line 62) +* ess-source-directory: Source Directories. (line 22) +* ess-style: Styles. (line 21) +* ess-style-alist: Styles. (line 28) +* ess-switch-to-end-of-proc-buffer: Other. (line 21) +* ess-swv-pdflatex-commands: Sweave and AUCTeX. (line 35) +* ess-use-eldoc: ESS ElDoc. (line 13) +* ess-use-flymake: ESS Flymake. (line 12) +* iESS program arguments: Customizing startup. (line 48) +* inferior-ess-program: Customizing startup. (line 48) +* inferior-R-font-lock-keywords: Highlighting. (line 12) +* Rd-indent-level: R documentation files. + (line 78) +* Rd-mode-hook: R documentation files. + (line 75) +* Rd-to-help-command: R documentation files. + (line 82) + + +File: ess.info, Node: Concept index, Prev: Variable index, Up: Indices + +Concept Index +============= + +[index] +* Menu: + +* aborting R commands: Other. (line 9) +* aborting S commands: Other. (line 9) +* arguments to R program: Customizing startup. (line 51) +* arguments to S program: Customizing startup. (line 51) +* authors: Credits. (line 6) +* autosaving: Source Files. (line 83) +* bug reports: Reporting Bugs. (line 6) +* bugs: Bugs. (line 6) +* changing ESS processes: Multiple ESS processes. + (line 6) +* cleaning up: Hot keys. (line 71) +* comint: Credits. (line 6) +* command history: Command History. (line 6) +* command line arguments: iESS(R)--Inferior ESS processes. + (line 16) +* command-line completion: Object names. (line 6) +* command-line editing: Command-line editing. + (line 6) +* commands: Entering commands. (line 6) +* comments: Source Files. (line 41) +* comments in R: Indenting. (line 18) +* company: Company. (line 6) +* completion in edit buffer: Other edit buffer commands. + (line 24) +* completion of object names: Object names. (line 6) +* completion on file names: Object names. (line 39) +* completion on lists: Object names. (line 37) +* completion, when prompted for object names: Edit buffer. (line 14) +* creating new objects: Edit buffer. (line 14) +* credits: Credits. (line 6) +* customization: Customization. (line 6) +* data frames: Object names. (line 20) +* deleting output: Last command. (line 24) +* directories: Starting up. (line 11) +* dump file directories: Source Directories. (line 20) +* dump file names: Source Directories. (line 6) +* dump files: Edit buffer. (line 27) +* dump files <1>: Source Files. (line 10) +* echoing commands when evaluating: Evaluating code. (line 20) +* edit buffer: Edit buffer. (line 6) +* editing commands: Command History. (line 6) +* editing functions: Editing objects. (line 6) +* editing transcripts: Saving transcripts. (line 18) +* ElDoc: ESS ElDoc. (line 6) +* emacsclient: Emacsclient. (line 6) +* entering commands: Entering commands. (line 6) +* errors: Error Checking. (line 6) +* ESS commands blocking Emacs: Evaluating code. (line 20) +* ess developer: Namespaced Evaluation. + (line 6) +* ESS process buffer: Starting up. (line 17) +* ESS process directory: Starting up. (line 11) +* ESS tracebug: ESS tracebug. (line 6) +* ESS-elsewhere: ESS processes on Remote Computers. + (line 9) +* ess-roxy: roxygen2. (line 6) +* evaluating code with echoed commands: Evaluating code. (line 20) +* evaluating R expressions: Evaluating code. (line 31) +* evaluating S expressions: Evaluating code. (line 31) +* finding function definitions: Xref. (line 6) +* flymake: ESS Flymake. (line 6) +* font-lock mode: Highlighting. (line 7) +* formatting source code: Indenting. (line 32) +* graphics: Graphics. (line 6) +* Handy commands: Handy commands. (line 6) +* help files: Help. (line 6) +* highlighting: Highlighting. (line 7) +* historic backups: Source Files. (line 41) +* hot keys: Hot keys. (line 43) +* icicles: Icicles. (line 6) +* IDO completions: Minibuffer completion. + (line 6) +* indenting: Indenting. (line 32) +* installation: Installation. (line 6) +* interactive use of R: Introduction. (line 31) +* interactive use of S: Introduction. (line 31) +* interrupting R commands: Other. (line 9) +* interrupting S commands: Other. (line 9) +* introduction: Introduction. (line 6) +* keyboard short cuts: Hot keys. (line 43) +* killing temporary buffers: Hot keys. (line 71) +* killing the ESS process: Hot keys. (line 71) +* lists, completion on: Object names. (line 37) +* motion in transcript mode: Transcript Mode. (line 17) +* multi-line commands, resubmitting: Transcript resubmit. (line 33) +* multiple ESS processes: Multiple ESS processes. + (line 6) +* multiple inferior processes: Multiple ESS processes. + (line 6) +* multiple interactive processes: Multiple ESS processes. + (line 6) +* new objects, creating: Edit buffer. (line 14) +* objects: Hot keys. (line 24) +* pages in the process buffer: Transcript. (line 24) +* paging commands in help buffers: Help. (line 28) +* paragraphs in the process buffer: Transcript. (line 13) +* parsing errors: Error Checking. (line 6) +* process buffer: Starting up. (line 17) +* process names: Multiple ESS processes. + (line 8) +* programming in R: Introduction. (line 43) +* programming in S: Introduction. (line 43) +* project work in R: Source Files. (line 41) +* project work in S: Source Files. (line 41) +* quitting from ESS: Hot keys. (line 71) +* re-executing commands: Command History. (line 6) +* reading long command outputs: Last command. (line 19) +* remote Computers: ESS processes on Remote Computers. + (line 9) +* reverting function definitions: Edit buffer. (line 27) +* roxy: roxygen2. (line 6) +* roxygen2: roxygen2. (line 6) +* running R: Starting up. (line 6) +* running S: Starting up. (line 6) +* S+elsewhere: ESS processes on Remote Computers. + (line 9) +* search list: Hot keys. (line 34) +* search list <1>: Source Directories. (line 55) +* sending input: Entering commands. (line 6) +* Space in function argument completion: Function arguments. (line 10) +* starting directory: Starting up. (line 11) +* starting ESS: Starting up. (line 6) +* STERM: Statistical Process running in ESS?. + (line 6) +* temporary buffers: Help. (line 169) +* temporary buffers, killing: Hot keys. (line 71) +* tracebug tutorial: Getting started with tracebug. + (line 6) +* tramp support: ESS processes on Remote Computers. + (line 9) +* transcript: Transcript. (line 9) +* transcript file: Customizing startup. (line 40) +* transcript file names: Saving transcripts. (line 13) +* transcript mode motion: Transcript Mode. (line 17) +* transcripts of R sessions: Introduction. (line 38) +* transcripts of S sessions: Introduction. (line 38) +* using ESS interactively: Introduction. (line 31) +* using R interactively: Introduction. (line 31) +* using S interactively: Introduction. (line 31) +* winjava: winjava. (line 6) +* working directory: Starting up. (line 11) +* working directory <1>: Source Directories. (line 55) +* X Windows: X11. (line 6) +* xref: Xref. (line 6) + + + +Tag Table: +Node: Top268 +Node: Introduction2914 +Node: Features5668 +Node: Current Features6494 +Node: New features9945 +Node: Credits35243 +Node: Manual38860 +Node: Installation41526 +Node: Installing from a third-party repository42463 +Node: Installing from source43410 +Node: Activating and Loading ESS45002 +Node: Check Installation46076 +Node: Interactive ESS46296 +Node: Starting up47141 +Node: Multiple ESS processes47885 +Node: ESS processes on Remote Computers48966 +Node: Customizing startup53069 +Node: Controlling buffer display55959 +Node: Entering commands58580 +Node: Command-line editing59738 +Node: Transcript60971 +Node: Last command62740 +Node: Process buffer motion64166 +Node: Transcript resubmit65669 +Node: Saving transcripts67634 +Node: Command History69424 +Node: Saving History72833 +Node: History expansion73594 +Node: Hot keys76805 +Node: Statistical Process running in ESS?80875 +Node: Emacsclient82154 +Node: Other82946 +Node: Evaluating code83965 +Node: Transcript Mode87761 +Node: Resubmit88914 +Node: Clean89977 +Node: Editing objects90973 +Node: Edit buffer92091 +Node: Loading94137 +Node: Error Checking95164 +Node: Indenting96213 +Node: Styles99257 +Node: Other edit buffer commands101631 +Node: Source Files103287 +Node: Source Directories107891 +Node: Help111044 +Node: Completion115490 +Node: Object names115705 +Node: Function arguments118339 +Node: Minibuffer completion119282 +Node: Company119756 +Node: Icicles120143 +Node: Developing with ESS121463 +Node: ESS tracebug121909 +Node: Getting started with tracebug124916 +Node: Editing documentation127074 +Node: R documentation files127626 +Node: roxygen2131329 +Node: Namespaced Evaluation135740 +Node: Extras137738 +Node: ESS ElDoc138762 +Node: ESS Flymake140258 +Node: Handy commands141352 +Node: Highlighting142549 +Node: Parens143584 +Node: Graphics144060 +Node: printer144731 +Node: X11145487 +Node: winjava145826 +Node: Imenu146238 +Node: Toolbar147085 +Node: Xref147493 +Node: Rdired147821 +Node: Package listing148884 +Node: Org150268 +Node: Sweave and AUCTeX151222 +Node: ESS for R153774 +Node: ESS(R)--Editing files154074 +Node: iESS(R)--Inferior ESS processes154575 +Node: Philosophies for using ESS(R)157230 +Node: Example ESS usage158157 +Node: ESS for SAS159562 +Node: ESS(SAS)--Design philosophy160285 +Node: ESS(SAS)--Editing files161218 +Node: ESS(SAS)--TAB key163072 +Node: ESS(SAS)--Batch SAS processes164438 +Node: ESS(SAS)--Function keys for batch processing169466 +Node: iESS(SAS)--Interactive SAS processes178953 +Node: iESS(SAS)--Common problems182707 +Node: ESS(SAS)--Graphics184230 +Node: ESS(SAS)--Windows185013 +Node: ESS for BUGS185591 +Node: ESS for JAGS187347 +Node: Mailing lists/bug reports190699 +Node: Bugs190963 +Node: Reporting Bugs192587 +Node: Mailing Lists193480 +Node: Help with Emacs194207 +Node: Customization194739 +Node: Indices195513 +Node: Key index195688 +Node: Function and program index200820 +Node: Variable index210240 +Node: Concept index213801 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/ess-20230419.1527/essd-els.el b/elpa/ess-20230419.1527/essd-els.el new file mode 100644 index 00000000..f1612cd6 --- /dev/null +++ b/elpa/ess-20230419.1527/essd-els.el @@ -0,0 +1,183 @@ +;;; essd-els.el --- S-PLUS 3.x at another location customization -*- lexical-binding: t; -*- + +;; Copyright (C) 1998-2022 Free Software Foundation, Inc. + +;; Author: Richard M. Heiberger +;; Created: December 1998 +;; Maintainer: ESS-core + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This file defines all the S-PLUS 3.x customizations for ess-mode. + +;;; Code: + +(require 'ess-r-mode) +(require 'ess-sp6-d) +(require 'ess-sas-d) +(require 'ess-trns) +(require 'ess-utils) +(defvar ess-julia-customize-alist) + +;; Easily changeable in a user's .emacs +(defvar S+elsewhere-dialect-name "S+6" + "Name of `dialect' for S-PLUS at another location.") + +(defvar S+elsewhere-start-args "-i" + "Arguments for `S+elsewhere-dialect-name'.") + +(defcustom inferior-ess-remote-pager nil + "Remote pager to use for reporting help files and similar things. +The default value is nil." + :group 'ess-proc + :type '(choice (const nil) string)) + + +(defvar S+elsewhere-customize-alist + (append + '((ess-local-customize-alist . S+elsewhere-customize-alist) + (ess-dialect . S+elsewhere-dialect-name) + (ess-object-name-db-file . "ess-spelsewhere-namedb.el" ) + (inferior-ess-program . inferior-S-elsewhere-program) + (inferior-ess-help-command . "help(\"%s\", pager=\"cat\", window=F)\n") + (ess-STERM . "iESS") + ) + S+common-cust-alist) + "Variables to customize for S+elsewhere.") + +(defun S+elsewhere (&optional _proc-name) + "Call 'S-PLUS 3.x', the 'Real Thing' from StatSci." + ;; git commit 104c4d7c56bc239ea245562763caa317bc3a1a84 + (declare (obsolete ess-remote "2000")) + (ess-write-to-dribble-buffer + (format "\n(S+elsewhere): ess-dialect=%s, buf=%s\n" ess-dialect + (current-buffer))) + (let ((inf-buf (inferior-ess nil S+elsewhere-customize-alist))) + (when inferior-ess-language-start + (ess-eval-linewise inferior-ess-language-start)) + inf-buf)) + +(defun S+elsewhere-mode (&optional _proc-name) + "Major mode for editing S+3 source. See `ess-mode' for more help." + (declare (obsolete ess-remote "2000")) + (setq-local ess-local-customize-alist S+elsewhere-customize-alist) + (ess-mode)) + +;; This REALLY shouldn't need an editing mode. Just a transcript and +;; an inferior process handler. + +(defun ess-select-alist-dialect (&optional dialect) + "Query user for an ESS DIALECT and return the matching customize-alist." + (interactive) + (let* ((dialects '("R" "S+" "julia" "s3" "s4" + "sp3" "sp4" "sqpe4" "sp5" "sqpe" "SAS")) + (dialect (or dialect + (ess-completing-read "Dialect" dialects nil t)))) + (cond + ((string= dialect "julia") (progn (require 'julia-mode) + ess-julia-customize-alist)) + ((string= dialect "R") ess-r-customize-alist) + ((string= dialect "SAS") SAS-customize-alist) + (t S+elsewhere-customize-alist)))) + +(defun ess-add-ess-process () + "Execute this command from within a buffer running a process to add +the process to `ess-process-name-alist' and to make it the +`ess-current-process-name'. This command will normally be run in a +telnet buffer connected to another computer or in a shell or comint +buffer on the local computer." + (interactive) + (let ((proc (get-buffer-process (buffer-name)))) + (if (not proc) + (error "No process is associated with this buffer") + (set-process-filter proc #'inferior-ess-output-filter) + (setq ess-current-process-name (process-name proc)) + (add-to-list 'ess-process-name-list + (list ess-current-process-name))))) + +(defvar ess-remote nil + "Indicator, t in remote buffers.") + +;;;###autoload +(defun ess-remote (&optional proc-name dialect) + "Execute this command from within a buffer running a process. +It runs `ess-add-ess-process' to add the PROC-NAME to +`ess-process-name-alist' and to make it the +`ess-current-process-name'. It then prompts the user for an ESS +language and sets the editing characteristics appropriately. + +To use this command, first start a process on a remote computer by +manual use of telnet, rlogin, ssh, or some other protocol. Start the +relevant program (\"S\" or \"R\" or \"sas -stdio\") in that buffer. Once +you are talking to S or R or SAS, then do \\[ess-remote] to make +the current buffer an inferior-ess buffer with the right behavior for +the language you are currently working with. With S and R, use C-c +C-n to send lines over. With SAS, use C-c i +`ess-eval-line-and-step-invisibly' to send lines over invisibly. + +DIALECT is the desired ess-dialect. If nil, ask for dialect" + + (interactive) + (ess-add-ess-process) + ;; Need to select a remote-customize-alist + (let ((customize-alist (ess-select-alist-dialect dialect))) + (ess-write-to-dribble-buffer + (format "\n(ESS-remote): ess-dialect=%s, buf=%s\n" ess-dialect + (current-buffer))) + (ess-setq-vars-local customize-alist) + (inferior-ess--set-major-mode ess-dialect) + (setq-local ess-remote t) + (setq ess-local-process-name (or proc-name ess-current-process-name)) + + (goto-char (point-max)) + + (when (equal ess-dialect "R") + ;; ugly fix for evn variable. What can we do :( + (ess-eval-linewise (format "options(pager='%s')\n" + (or inferior-ess-remote-pager inferior-ess-pager)) + nil nil nil 'wait) + (ess-r-load-ESSR)) + + (when (equal ess-dialect "S+") + (ess-command ess-S+--injected-code)) + + (when (equal ess-language "SAS") + (font-lock-mode 0) + (SAS-log-mode) + (shell-mode) + (setq buffer-read-only nil) + (font-lock-mode 1)) + + (ess-process-put 'funargs-cache (make-hash-table :test 'equal)) + (ess-process-put 'funargs-pre-cache nil) + ;; auto-complete + (ess--setup-auto-complete ess-r-ac-sources t) + ;; company + (ess--setup-company ess-r-company-backends t) + + (when inferior-ess-language-start + (ess-eval-linewise inferior-ess-language-start + nil nil nil 'wait-prompt)))) + + + ; Provide package + +(provide 'essd-els) + +;;; essd-els.el ends here diff --git a/elpa/ess-20230419.1527/etc/ESSR.rds b/elpa/ess-20230419.1527/etc/ESSR.rds new file mode 100644 index 00000000..5203244f Binary files /dev/null and b/elpa/ess-20230419.1527/etc/ESSR.rds differ diff --git a/elpa/ess-20230419.1527/etc/ESSR/BUILDESSR b/elpa/ess-20230419.1527/etc/ESSR/BUILDESSR new file mode 100755 index 00000000..248d660e --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/BUILDESSR @@ -0,0 +1,10 @@ +#!/usr/bin/env Rscript +## -*- mode: R -*- +## code to build ESSR environment. +## Assume that current directory is etc/ESSR +## run "./BUILDESSR" to create ../ESSR.rda + +## exactly as in inferior-ess-r-load-ESSR in ess-r-d.el +source('./R/.load.R', local=TRUE) +ESSR <- .ess.ESSR.load('./R/') +saveRDS(ESSR, file = "../ESSR.rds") diff --git a/elpa/ess-20230419.1527/etc/ESSR/LOADREMOTE b/elpa/ess-20230419.1527/etc/ESSR/LOADREMOTE new file mode 100644 index 00000000..919ec33f --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/LOADREMOTE @@ -0,0 +1,24 @@ +## -*- mode: R -*- +## loading code which is first sent to R on remote sessions +local({ + ver <- '%s' ## <- passed from elisp + root <- '~/.config/ESSR' + if(!file.exists(root)) + dir.create(root, recursive = TRUE) + ## cannot use sprintf here + essr_file <- file.path(root, paste('ESSRv', ver, '.rds', sep = '')) + tryCatch({ + if(!file.exists(essr_file)) { + url <- paste('https://github.com/emacs-ess/ESS/raw/ESSRv', ver, '/etc/ESSR.rds', sep = '') + utils::download.file(url, essr_file) + } + ESSR <- readRDS(essr_file) + ESSR[[".ess.Rversion"]] <- ESSR[[".ess.getRversion"]]() + attach(ESSR) + print(TRUE) + }, + error = function(e) { + print(e) + print(FALSE) + }) +}) diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/.basic.R b/elpa/ess-20230419.1527/etc/ESSR/R/.basic.R new file mode 100644 index 00000000..b7a41a57 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/.basic.R @@ -0,0 +1,265 @@ +#### Essential functionality needed by ESS + +## Should work on *all* versions of R. +## Do not use _ in names, nor :: , nor 1L etc, as they +## cannot be parsed in old R versions + +.ess.getRversion <- function() { + if(exists("getRversion", mode="function")) getRversion() + else paste(R.version$major, R.version$minor, sep=".") +} + +## loading ESSR.rda might fail, so re-assign here: +.ess.Rversion <- .ess.getRversion() + +.ess.R.has.utils <- (.ess.Rversion >= "1.9.0") +.ess.utils.name <- paste("package", + if(.ess.Rversion >= "1.9.0") "utils" else "base", + sep = ":") + +## Instead of modern utils::help use one that works in R 1.0.0: +.ess.findFUN <- get("find", .ess.utils.name) + + +### HELP +.ess.help <- function(..., help.type = getOption("help_type")) { + if (is.null(help.type)) { + help.type <- "text" + } + + ## - get("help", ..) searching in global env works with devtools redefines + ## - Redefining to .ess.help this way is necessary because + ## utils:::print.help_files_with_topic (used internally when there's + ## more than one a package) uses the quoted call + ## MM: don't understand; more specifically? + ..help <- function(...) { + do.call(get("help", envir = .GlobalEnv), list(...)) + } + + if (.ess.Rversion > "2.10") { + ## Abbreviating help_type to avoid underscore + if(!is.null(getOption("warnPartialMatchArgs"))) { + op <- options(warnPartialMatchArgs = FALSE); on.exit(options(op)) + } + ..help(..., help = help.type) + } else { + ..help(..., htmlhelp = help.type == "html") + } +} + +.ess.getHelpAliases <- local({ + readrds <- if (.ess.Rversion >= '2.13.0') readRDS else .readRDS + aliasesCache <- new.env() + + getAliases <- function(file) { + cached <- aliasesCache[[file]] + if (!is.null(cached)) + return(cached) + + aliases <- tryCatch( + error = function(...) NULL, + if (file.exists(file)) + names(readrds(file)) + else + NULL + ) + + aliasesCache[[file]] <- aliases + aliases + } + + function(reset = FALSE) { + if (reset) + aliasesCache <<- new.env() + + rdsFiles <- paste(searchpaths(), "/help/aliases.rds", sep = "") + unlist(lapply(rdsFiles, getAliases), use.names = FALSE) + } +}) + +.ess.helpLinks <- function(topic, package) { + tryCatch( + warning = function(...) NULL, + error = function(...) NULL, + { + ast <- .ess.fetchParsedRd(topic, package) + .ess.findLinks(ast) + } + ) +} + +.ess.fetchParsedRd <- function(topic, package) { + path <- utils:::index.search(topic, find.package(package)) + utils:::.getHelpFile(path) +} + +.ess.findLinks <- function(x) { + links <- NULL + findLinksRec <- function(x) { + if (.ess.isRdLink(x)) { + ## Ignore `pkg` for now + links <<- c(links, .ess.getRdLink(x)[[2]]) + } else if (is.list(x)) { + for (elt in x) + findLinksRec(elt) + } + } + + findLinksRec(x) + links +} + +.ess.isRdLink <- function(x) { + identical(attr(x, "Rd_tag"), "\\link") +} + +## From `tools:::get_link()` +.ess.getRdLink <- function(x) { + pkg <- "" + dest <- paste(unlist(x), collapse = "") + + opt <- attr(x, "Rd_option") + if (!is.null(opt)) { + if (grepl("^=", opt, perl = TRUE, useBytes = TRUE)) { + dest <- sub("^=", "", opt) + } else if (grepl(":", opt, perl = TRUE, useBytes = TRUE)) { + dest <- sub("^[^:]*:", "", opt) + pkg <- sub(":.*", "", opt) + } else { + pkg <- as.character(opt) + } + } + + c(pkg, dest) +} + +### SOURCING +.ess.eval <- function(string, visibly = TRUE, output = FALSE, + max.deparse.length = 300, + file = tempfile("ESS"), local = NULL) +{ + if (is.null(local)) { + local <- if (.ess.Rversion > '2.13') parent.frame() else FALSE + } + + ## create FILE, put string into it. Then source. + ## arguments are like in source and .ess.source + cat(string, file = file) + ## The following on.exit infloops in R 3.3.0 + ## https://github.com/emacs-ess/ESS/issues/334 + ## https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16971 + ## So we are cleaning it in .ess.source instead. + ## on.exit(file.remove(file)) + .ess.source(file, visibly = visibly, output = output, + max.deparse.length = max.deparse.length, + local = local, fake.source = TRUE) +} + +.ess.strip.error <- function(msg, srcfile) { + pattern <- paste0(srcfile, ":[0-9]+:[0-9]+: ") + sub(pattern, "", msg) +} + +.ess.file.remove <- function(file){ + if (base::file.exists(file)) base::file.remove(file) + else FALSE +} + +.ess.source <- function(file, visibly = TRUE, output = FALSE, + max.deparse.length = 300, local = NULL, + fake.source = FALSE, keep.source = TRUE, + message.prefix = "") { + if (is.null(local)) { + local <- if (.ess.Rversion > "2.13") + parent.frame() + else FALSE + } + + ss <- + if (.ess.Rversion >= "3.4") + base::source + else if (.ess.Rversion >= "2.8") + function(..., spaced) base::source(...) + else function(..., spaced, keep.source) base::source(...) + + on.exit({ + if (fake.source) + .ess.file.remove(file) + }) + + out <- ss(file, echo = visibly, local = local, print.eval = output, spaced = FALSE, + max.deparse.length = max.deparse.length, keep.source = keep.source) + + if(!fake.source) + cat(sprintf("%sSourced file %s\n", message.prefix, file)) + + ## Return value for org-babel + invisible(out$value) +} + +if(.ess.Rversion < "1.8") + ## (works for "1.7.2"): bquote() was new in 1.8.0 + bquote <- function(expr, where=parent.frame()){ + unquote <- function(e) + if (is.pairlist(e)) as.pairlist(lapply(e, unquote)) + else if (length(e) <= 1) e + else if (e[[1]] == as.name(".")) eval(e[[2]], where) + else as.call(lapply(e, unquote)) + + unquote(substitute(expr)) + } + +.ess.command <- function(expr, sentinel) { + ## It is possible that the REPL is marked as non-busy when the + ## output is sinked because prompts are not sinked. In that case, + ## redirect the sinked output temporarily to ESS. + sinked <- !identical(stdout(), getConnection(1)) + if (sinked) + sink(getConnection(1)) + + on.exit({ + writeLines(paste0(sentinel, "-END")) + if (sinked) + sink(NULL) + }) + + writeLines(paste0(sentinel, "-START")) + + .ess.environment.state$env <- parent.frame() + on.exit(.ess.environment.state$env <- NULL, add = TRUE) + + + ## Don't interrupt `browser()` sessions (#1081) + restart <- function(...) { + if (!is.null(findRestart("browser"))) + invokeRestart("browser") + } + + ## Should be an exiting handler to be able to catch + ## stack overflow errors + rethrow <- function(cnd) { + stop('ESSR::ERROR \"', conditionMessage(cnd), '\"') + } + + out <- tryCatch( + error = rethrow, + withCallingHandlers( + interrupt = restart, + withVisible(expr) + ) + ) + + ## Print result manually because we can't rely on auto-print + ## without changing the last value + if (out$visible) + print(out$value) + + ## Keep `.Last.value` stable + invisible(.Last.value) +} + +.ess.environment.state <- new.env(parent = emptyenv()) + +.ess.environment <- function() { + .ess.environment.state$env +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/.load.R b/elpa/ess-20230419.1527/etc/ESSR/R/.load.R new file mode 100644 index 00000000..9b38af2b --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/.load.R @@ -0,0 +1,96 @@ +## This file is sourced when R starts and `load.ESSR` is called. See +## inferior-ess-r-load-ESSR--local. +## Do not use _ in names, nor :: as they cannot be parsed in old R versions + +## obtain the R version number as a string +.ess.ESSR.get.rver <- function() { + if(exists("getRversion", mode="function")) getRversion() + else paste(R.version$major, R.version$minor, sep=".") +} + +## load .base.R and all other files into ESSR environment; then attach ESSR +.ess.ESSR.load <- function(dir) { + + if (nzchar(Sys.getenv("ESSR_TEST_LOAD_ERROR"))) + stop('Loading failed with a nice message.') + + Rver <- .ess.ESSR.get.rver() + ESSR <- .ess.ESSR.create.env(Rver) + .ess.ESSR.source.files(ESSR, dir, Rver) + .ess.ESSR.attach.env(ESSR, Rver) + + ## BUILDESSR needs this: + invisible(ESSR) +} + +.ess.ESSR.create.env <- function(Rver) { + + ESSR <- + if (Rver <= "1.3.0") ## really old library() revert order a bit + attach(NULL, name = "ESSR") + else if(length(nn <- names(formals(new.env))) && any(nn == "parent")) + new.env(parent = + if (Rver >= "1.9.0") getNamespace("utils") + else .BaseNamespaceEnv) + else + new.env() + + assign(".ess.Rversion", Rver, envir = ESSR) + + ## updated by make !! + VERSION <- "1.8" + assign(".ess.ESSRversion", VERSION, envir = ESSR) + + ESSR +} + +## attempt to source the files in the ESSR directory and place the resulting R +## objects into ESSR environment; the updated version of the environment is +## returned +.ess.ESSR.source.files <- function(ESSR, dir, Rver) { + + .source <- + if(any("keep.source" == names(formals(sys.source)))) + sys.source + else + function(..., keep.source) sys.source(...) + + ## .basic.R: + try(.source(paste(dir,'/.basic.R', sep = ""), envir = ESSR, keep.source = FALSE)) + + ## all others try(*) as it will fail in old R + if (Rver > "1.3.0") { # no sense if very old R + for (f in dir(dir, pattern='\\.R$', full.names=TRUE)) + try(.source(f, envir = ESSR, keep.source = FALSE)) + } + + ESSR +} + + +## attach the ESSR environment to the search path +.ess.ESSR.attach.env <- function(ESSR, Rver) { + if (Rver >= "2.4.0") + attach(ESSR) + else if (Rver > "1.3.0") { # borrow from older library() + e <- attach(NULL, name = "ESSR") + .Internal(lib.fixup(ESSR, e)) + } else { # if old R, use as in that old library(): + .Internal(lib.fixup(ESSR, .GlobalEnv)) + } +} + + +## copy any ESSR R objects in the global environment into a newly created ESSR +## environment; then remove the original objects and attach ESSR +.ess.collect.ESSR.objects <- function() { + + Rver <- .ess.ESSR.get.rver() + ESSR <- .ess.ESSR.create.env(Rver) + essr.nms <- grep('\\.(ess|ESS)', ls(.GlobalEnv, all.names = TRUE), value = TRUE) + for (nm in essr.nms) { + assign(nm, get(nm, pos = .GlobalEnv), envir = ESSR) + } + .ess.ESSR.attach.env(ESSR, Rver) + rm(list = essr.nms, pos = .GlobalEnv) +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/completion.R b/elpa/ess-20230419.1527/etc/ESSR/R/completion.R new file mode 100644 index 00000000..50017df0 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/completion.R @@ -0,0 +1,171 @@ +## Do *NOT* use 1L -- it gives parse errors in historical versions of R + +## Try a setup working in as old R as possible. +## ===> +## 1) do not use "_" in names! --- seems impossible for the Millenials .. +## 2) use our own simplified definition of '::' and ':::' ? +## +if(!exists("local")) + local <- function(expr, envir = environment()) { invisible(eval(expr, envir=envir)) } + +##' Robust version of +##' utils:::.addFunctionInfo(c = c("recursive", "use.names")) # needed only for R <= 3.y.z +local({ + U <- asNamespace("utils"); fn <- ".addFunctionInfo" + EX <- exists(fn, envir=U) + if(EX && is.function(FN <- get(fn, envir=U))) { + FN(c = c("recursive", "use.names")); ##dbg: cat("Calling utils:::",fn,"(c = ...)\n") + } +}) + + +.ess_eval <- function(str, env = globalenv()) { + ## don't remove; really need eval(parse( here!! + tryCatch(eval(parse(text=str), envir = env), + error=function(e) NULL) ## also works for special objects containing @:$ etc +} + +.ess_nonull <- function(x, default = "") { + if (is.null(x)) default + else x +} + +## not needed for completion; called from (ess-r-xref--srcref *) in ../../../lisp/ess-r-xref.el +.ess_srcref <- function(name, pkg) { + if (!is.null(pkg) && requireNamespace(pkg)) { + env <- asNamespace(pkg) + } else { + env <- globalenv() + } + fn <- .ess_eval(name, env) + if (is.null(fn)) { + objs <- utils::getAnywhere(name)$objs + for (fn in objs) { + if(is.function(fn)) + break + } + } + out <- "()\n" + if (is.function(fn) && !is.null(utils::getSrcref(fn))) { + file <- utils::getSrcFilename(fn, full.names = TRUE) + if (file != "") { + line <- .ess_nonull(utils::getSrcLocation(fn, "line" ), 1) + col <- .ess_nonull(utils::getSrcLocation(fn, "column"), 1) + out <- sprintf("(\"%s\" %d %d)\n", file, line, col - 1) + } + } + cat(out) +} + + +.ess_fn_pkg <- function(fn_name) { + objs <- utils::getAnywhere(fn_name) + print(sub("(package|namespace):", "", objs$where)) +} + +.ess_funargs <- function(funname) { + if(.ess.Rversion > '2.14.1') { + ## temporarily disable JIT compilation and errors + comp <- compiler::enableJIT(0) + op <- options(error=NULL) + on.exit({ options(op); compiler::enableJIT(comp) }) + } + fun <- .ess_eval(funname) + if(is.function(fun)) { + special <- grepl('[:$@[]', funname) + args <- if(!special){ + fundef <- paste(funname, '.default',sep='') + do.call('argsAnywhere', list(fundef)) + } + + if(is.null(args)) + args <- args(fun) + if(is.null(args)) + args <- do.call('argsAnywhere', list(funname)) + + fmls <- formals(args) + fmls_names <- names(fmls) + fmls <- gsub('\"', '\\\"', + gsub("\\", "\\\\", as.character(fmls), fixed = TRUE), + fixed=TRUE) + args_alist <- + sprintf("'(%s)", + paste("(\"", fmls_names, "\" . \"", fmls, "\")", + sep = '', collapse = ' ')) + allargs <- + if (special) fmls_names + else tryCatch(gsub(' ?= ?', '', utils:::functionArgs(funname, ''), fixed = FALSE), + error=function(e) NULL) + allargs <- sprintf("'(\"%s\")", + paste(allargs, collapse = '\" "')) + envname <- + if (is.primitive(fun)) "base" + else environmentName(environment(fun)) + if (envname == "R_GlobalEnv") envname <- "" + cat(sprintf('(list \"%s\" %s %s)\n', + envname, args_alist, allargs)) + } +} + + +.ess_get_completions <- function(string, end, suffix = " = ") { + oldopts <- utils::rc.options(funarg.suffix = suffix) + on.exit(utils::rc.options(oldopts)) + sett <- utils::rc.settings + oldDots <- sett()[["dots"]] + on.exit(sett(dots=oldDots), add=TRUE) + sett(dots = FALSE) + if(.ess.Rversion > '2.14.1') { + comp <- compiler::enableJIT(0) + op <- options(error=NULL) + on.exit({ options(op); compiler::enableJIT(comp)}, add = TRUE) + } + utils:::.assignLinebuffer(string) + utils:::.assignEnd(end) + utils:::.guessTokenFromLine() + utils:::.completeToken() + c(get('token', envir=utils:::.CompletionEnv), + utils:::.retrieveCompletions()) +} + +.ess_arg_help <- function(arg, func) { + op <- options(error=NULL) + on.exit(options(op)) + fguess <- + if(is.null(func)) get('fguess', envir=utils:::.CompletionEnv) + else func + findArgHelp <- function(fun, arg){ + file <- help(fun, try.all.packages=FALSE)[[1]] + hlp <- utils:::.getHelpFile(file) + id <- grep('arguments', tools:::RdTags(hlp), fixed=TRUE) + if(length(id)){ + arg_section <- hlp[[id[[1]]]] + items <- grep('item', tools:::RdTags(arg_section), fixed=TRUE) + ## cat('items:', items, fill=TRUE) + if(length(items)){ + arg_section <- arg_section[items] + args <- unlist(lapply(arg_section, + function(el) paste(unlist(el[[1]][[1]], TRUE, FALSE), collapse=''))) + fits <- grep(arg, args, fixed=TRUE) + ## cat('args', args, 'fits', fill=TRUE) + if(length(fits)) + paste(unlist(arg_section[[fits[1]]][[2]], TRUE, FALSE), collapse='') + } + } + } + funcs <- c(fguess, tryCatch(methods(fguess), + warning= function(w) NULL, + error = function(e) NULL)) + if(length(funcs) > 1 && length(pos <- grep('default', funcs))) { + funcs <- c(funcs[[pos[[1]]]], funcs[-pos[[1]]]) + } + i <- 1; found <- FALSE + out <- 'No help found' + while(i <= length(funcs) && is.null(out <- + tryCatch(findArgHelp(funcs[[i]], arg), + warning=function(w) {NULL}, + error=function(e) {NULL}) + )) + i <- i + 1 + cat('\n\n', as.character(out), '\n') +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/debug.R b/elpa/ess-20230419.1527/etc/ESSR/R/debug.R new file mode 100644 index 00000000..cb2580bc --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/debug.R @@ -0,0 +1,230 @@ +### BREAKPOINTS +.ESSBP. <- new.env() + +### DEBUG/UNDEBUG +.ess_find_funcs <- function(env) { + objs <- ls(envir = env, all.names = TRUE) + if (length(objs) > 0) + objs <- objs[sapply(objs, exists, envir = env, + mode = 'function', inherits = FALSE)] + objs +} + +.ess_all_functions <- function(packages = c(), env = NULL) { + if(is.null(env)) + env <- parent.frame() + empty <- emptyenv() + coll <- list() + for(p in packages){ + ## package might not be attached + try( + { + objNS <- .ess_find_funcs(asNamespace(p)) + objPKG <- .ess_find_funcs(as.environment(paste0('package:', p))) + objNS <- setdiff(objNS, objPKG) + if(length(objPKG)) + coll[[length(coll) + 1]] <- paste0(p, ':::', objNS) + }, silent = TRUE) + } + while(!identical(empty, env)){ + coll[[length(coll) + 1]] <- .ess_find_funcs(env) + env <- parent.env(env) + } + grep('^\\.ess', unlist(coll, use.names = FALSE), + invert = TRUE, value = TRUE) +} + + +.ess_dbg_flag_for_debuging <- function(fname){ + all <- utils::getAnywhere(fname) + if(length(all$obj) == 0){ + msg <- sprintf("No functions names '%s' found", fname) + } else { + msg <- sprintf("Flagged '%s' for debugging", fname) + tryCatch(lapply(all$obj, debug), + error = function(e){ + msg <- paste0("Error: ", e$message) + }) + } + cat(msg) + .ess_mpi_message(msg) +} + +.ess_dbg_getTracedAndDebugged <- function() +{ + packages <- base::.packages() + tr_state <- tracingState(FALSE) + on.exit(tracingState(tr_state)) + generics <- methods::getGenerics() + all_traced <- c() + for(i in seq_along(generics)){ + genf <- methods::getGeneric(generics[[i]], + package=generics@package[[i]]) + if(!is.null(genf)){ ## might happen !! v.2.13 + menv <- methods::getMethodsForDispatch(genf) + traced <- unlist(eapply(menv, is, 'traceable', all.names=TRUE)) + if(length(traced) && any(traced)) + all_traced <- c(paste(generics[[i]],':', + names(traced)[traced],sep=''), all_traced) + tfn <- getFunction(generics[[i]], mustFind=FALSE, where = .GlobalEnv) + if(!is.null(tfn ) && is(tfn, 'traceable')) # if the default is traced, it does not appear in the menv :() + all_traced <- c(generics[[i]], all_traced) + } + } + debugged_pkg <- unlist(lapply(packages, function(pkgname){ + ns <- asNamespace(pkgname) + funcs <- .ess_find_funcs(ns) + dbged <- funcs[unlist(lapply(funcs, + function(f){ + isdebugged(get(f, envir = ns, inherits = FALSE)) + }))] + if(length(dbged)) + paste0(pkgname, ':::`', dbged, '`') + })) + env <- parent.frame() + ## traced function don't appear here. Not really needed and would affect performance. + all <- .ess_all_functions(packages = packages, env = env) + which_deb <- lapply(all, function(nm){ + ## if isdebugged is called with string it doess find + tryCatch(isdebugged(get(nm, envir = env)), + error = function(e) FALSE) + ## try(eval(substitute(isdebugged(nm), list(nm = as.name(nm)))), silent = T) + }) + debugged <- all[which(unlist(which_deb, recursive=FALSE, use.names=FALSE))] + unique(c(debugged_pkg, debugged, all_traced)) +} + + +.ess_dbg_UntraceOrUndebug <- function(name, env = parent.frame()) { + tr_state <- tracingState(FALSE) + on.exit(tracingState(tr_state)) + if( grepl('::', name) ){ + ## foo:::bar name + eval(parse(text = sprintf('undebug(%s)', name))) + }else{ + ## name is a name of a function to be undebugged or has a form + ## name:Class1#Class2#Class3 for traced methods + name <- strsplit(name, ':', fixed = TRUE)[[1]] + if( length(name)>1 ){ + ## a method + fun <- name[[1]] + sig <- strsplit(paste(name[-1], collapse=''), '#', fixed=TRUE)[[1]] + untrace(fun, signature = sig) + }else{ + ## function + if( is(getFunction(name, where = parent.frame()), 'traceable') ) + untrace(name) + else if(grepl(":", name)) + undebug(name) + else + undebug(get(name, envir = env)) + }} +} + +.ess_dbg_UndebugALL <- function(funcs) +{ + tr_state <- tracingState(FALSE) + on.exit(tracingState(tr_state)) + env <- parent.frame() + invisible(lapply(funcs, function( nm ) { + ## ugly tryCatch, but there might be several names pointing to the + ## same function, like foo:::bar and bar. An alternative would be + ## to call .ess_dbg_getTracedAndDebugged each time but that might + ## be ery slow + try(.ess_dbg_UntraceOrUndebug(nm, env = env), TRUE) + })) +} + + +### WATCH +.ess_watch_expressions <- list() + +.ess_watch_eval <- function() +{ + env <- as.environment("ESSR") + exps <- get('.ess_watch_expressions', envir = env) + if(length(exps) == 0) { + ## using old style so this can be parsed by R 1.9.1 (e.g): + cat('\n# Watch list is empty!\n', + '# a append new expression', + '# i insert new expression', + '# k kill', + '# e edit the expression', + '# r rename', + '# n/p navigate', + '# u/d,U move the expression up/down', + '# q kill the buffer', + sep="\n") + } else { + .parent_frame <- parent.frame() + .essWEnames <- allNames(exps) + len0p <- !nzchar(.essWEnames) + .essWEnames[len0p] <- seq_along(len0p)[len0p] + oo <- options(width = 10000) + on.exit(options(oo)) + for(i in seq_along(exps)) { + cat('\n@---- ', .essWEnames[[i]], ' ', + rep.int('-', max(0, 35 - nchar(.essWEnames[[i]]))), '-@\n', sep = '') + expr <- gsub(" +", " ", paste(deparse(exps[[i]][[1]]), collapse = " ")) + cat(paste('@---:', expr), ' \n', sep = '') + tryCatch(print(eval(exps[[i]], + envir = .parent_frame)), + error = function(e) cat('Error:', e$message, '\n' ), + warning = function(w) cat('warning: ', w$message, '\n' )) + } + } +} + + +.ess_watch_assign_expressions <- function(elist) { + assign(".ess_watch_expressions", elist, envir = as.environment("ESSR")) +} + +.ess_log_eval <- function(log_name) { + env <- as.environment("ESSR") + if(!exists(log_name, envir = env, inherits = FALSE)) + assign(log_name, list(), envir = env) + log <- get(log_name, envir = env, inherits = FALSE) + .essWEnames <- allNames(.ess_watch_expressions) + cur_log <- list() + .parent_frame <- parent.frame() + for(i in seq_along(.ess_watch_expressions)) { + capture.output( { + cur_log[[i]] <- + tryCatch(eval(.ess_watch_expressions[[i]]), + envir = .parent_frame, + error = function(e) paste('Error:', e$message, '\n'), + warning = function(w) paste('warning: ', w$message, '\n')) + if(is.null(cur_log[i][[1]])) + cur_log[i] <- list(NULL) + }) + } + names(cur_log) <- .essWEnames + assign(log_name, c(log, list(cur_log)), envir = env) + invisible(NULL) +} + + +.ess_package_attached <- function(pack_name){ + as.logical(match(paste0("package:", pack_name), search())) +} + +## magrittr debug_pipe +.ess_pipe_browser <- function(x){ + if(is.list(x)) + evalq({ + browser(skipCalls = 2) + x + }, envir = x) + else if(is.environment(x)) + ## enclos argumentn has no effect for unclear reason, need to hack + eval(bquote({ + x <- .(environment()) + browser(skipCalls = 2) + x + }), envir = x) + else { + browser(skipCalls = 0) + x + } +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/misc.R b/elpa/ess-20230419.1527/etc/ESSR/R/misc.R new file mode 100644 index 00000000..000cf5b7 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/misc.R @@ -0,0 +1,174 @@ +.ess_weave <- function(command, file, encoding = NULL){ + cmd_symb <- substitute(command) + if (grepl('knit|purl', deparse(cmd_symb))) require(knitr) + od <- getwd() + on.exit(setwd(od)) + setwd(dirname(file)) + frame <- parent.frame() + if (is.null(encoding)) + eval(bquote(.(cmd_symb)(.(file))), envir = frame) + else + eval(bquote(.(cmd_symb)(.(file), encoding = .(encoding))), envir = frame) +} + +.ess_knit <- function(file, output = NULL){ + library(knitr) + frame <- parent.frame() + od <- getwd() + on.exit(setwd(od)) + setwd(dirname(file)) + ## this bquote is really needed for data.table := operator to work correctly + eval(bquote(knit(.(file), output = .(output))), envir = frame) +} + + +.ess_sweave <- function(file, output = NULL){ + od <- getwd() + frame <- parent.frame() + on.exit(setwd(od)) + setwd(dirname(file)) + eval(bquote(Sweave(.(file), output = .(output))), envir = frame) +} + +## Users might find it useful. So don't prefix with .ess. +.ess_htsummary <- function(x, hlength = 4, tlength = 4, digits = 3) { + ## fixme: simplify and generalize + snames <- c("mean", "sd", "min", "max", "nlev", "NAs") + d <- " " + num_sumr <- function(x){ + c(f(mean(x, na.rm = TRUE)), + f(sd(x, na.rm = TRUE)), + f(min(x, na.rm = TRUE)), + f(max(x, na.rm = TRUE)), + d, + f(sum(is.na(x), na.rm = TRUE))) + } + f <- function(x) format(x, digits = digits) + + if (is.data.frame(x) | is.matrix(x)) { + if (nrow(x) <= tlength + hlength){ + print(x) + } else { + if (is.matrix(x)) + x <- data.frame(unclass(x)) + ## conversion needed, to avoid problems with derived classes such + ## as data.table + h <- as.data.frame(head(x, hlength)) + t <- as.data.frame(tail(x, tlength)) + for (i in 1:ncol(x)) { + h[[i]] <- f(h[[i]]) + t[[i]] <- f(t[[i]]) + } + ## summaries + sumr <- sapply(x, function(c){ + if (is.logical(c)) + ## treat logical as numeric; it's harmless + c <- as.integer(c) + if (is.numeric(c)) + num_sumr(c) + else if (is.factor(c)) c(d, d, d, d, nlevels(c), sum(is.na(c))) + else rep.int(d, length(snames)) + }) + sumr <- as.data.frame(sumr) + row.names(sumr) <- snames + dots <- rep("...", ncol(x)) + empty <- rep.int(" ", ncol(x)) + lines <- rep.int(" ", ncol(x)) + df <- rbind(h, ... = dots, t, `_____` = lines, sumr, ` ` = empty) + print(df) + } + } else { + cat("head(", hlength, "):\n", sep = "") + print(head(x, hlength)) + if (length(x) > tlength + hlength){ + cat("\ntail(", tlength, "):\n", sep = "") + print(tail(x, tlength)) + } + cat("_____\n") + if (is.numeric(x) || is.logical(x)) + print(structure(num_sumr(x), names = snames), quote = FALSE) + else if (is.factor(x)){ + cat("NAs: ", sum(is.na(x), na.rm = TRUE), "\n") + cat("levels: \n") + print(levels(x)) + } + } + invisible(NULL) +} + + +.ess_vignettes <- function(all=FALSE) { + vs <- unclass(browseVignettes(all = all)) + vs <- vs[sapply(vs, length) > 0] + + mat2elist <- function(mat) { + if (!is.null(dim(mat))){ + apply(mat, 1, function(r) + sprintf("(list \"%s\")", + paste0(gsub("\"", "\\\\\"", + as.vector(r[c("Title", "Dir", "PDF", + "File", "R")])), + collapse = "\" \""))) + } + } + cat("(list \n", + paste0(mapply(function(el, name) { + sprintf("(list \"%s\" %s)", + name, paste0(mat2elist(el), collapse = "\n")) + }, + vs, names(vs)), collapse = "\n"), ")\n") +} + +.ess_Rd2txt <- function(rd) { + fun <- tools::Rd2txt + if (length(formals(fun)["stages"]))# newer R version + fun(rd, stages = c("build", "install", "render")) + else + fun(rd) +} + +## Hacked help.start() to use with ess-rutils.el +.ess_help_start <- function(update=FALSE, remote=NULL) { + home <- if (is.null(remote)) { + port <- tools::startDynamicHelp(NA) + if (port > 0L) { + if (update) + make.packages.html(temp=TRUE) + paste0("http://127.0.0.1:", port) + } + else stop(".ess_help_start() requires the HTTP server to be running", + call.=FALSE) + } else remote + paste0(home, "/doc/html/index.html") +} + + +.ess.rdired <- function() { + cat('\n') + + objs <- ls(envir = .GlobalEnv) + if (length(objs)==0) { + cat("No objects to view!\n") + return(invisible(NULL)) + } + + names(objs) <- objs + objs <- lapply(objs, get, envir = .GlobalEnv) + + mode <- sapply(objs, data.class) + length <- sapply(objs, length) + size <- sapply(objs, function(obj) format(object.size(obj))) + d <- data.frame(mode, length, size) + + var.names <- row.names(d) + + ## If any names contain spaces, we need to quote around them. + quotes <- rep('', length(var.names)) + spaces <- grep(' ', var.names) + if (any(spaces)) + quotes[spaces] <- '\"' + var.names <- paste(quotes, var.names, quotes, sep = '') + row.names(d) <- paste(' ', var.names, sep = '') + + print(d) +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/mpi.R b/elpa/ess-20230419.1527/etc/ESSR/R/mpi.R new file mode 100644 index 00000000..0ad5cfcb --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/mpi.R @@ -0,0 +1,28 @@ +## simple Message Parsing Interface + +.ess_mpi_send <- function(head, ...){ + dots <- lapply(list(...), function(el) { + if (is.null(el)) "nil" + else if (is.logical(el)) {if (el) "t" else "nil"} + else as.character(el) + }) + payload <- paste(dots, collapse = "") + cat(sprintf("_%s%s\\", head, payload)) +} + +.ess_mpi_message <- function(msg){ + .ess_mpi_send("message", msg) +} + +.ess_mpi_y_or_n <- function(prompt, callback = NULL){ + .ess_mpi_send("y-or-n", prompt, callback) +} + +.ess_mpi_eval <- function(expr, callback = NULL){ + .ess_mpi_send("eval", expr, callback) +} + +.ess_mpi_error <- function(msg) { + .ess_mpi_send("error", msg) +} + diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/ns-eval.R b/elpa/ess-20230419.1527/etc/ESSR/R/ns-eval.R new file mode 100644 index 00000000..8dc4da88 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/ns-eval.R @@ -0,0 +1,421 @@ +## NOTE ON S3 METHODS: New S3 methods are not automatically registered. You can +## register them manually after you have inserted method_name.my_class into your +## package environment using ess-developer, like follows: +## +## registerS3method("method_name", "my_class", my_package:::method_name.my_class) +## +## If an S3 methods already exists in a package, ESS-developer will do the right +## thing. + +## evaluate the STRING by saving into a file and calling .ess.ns_source +.ess.ns_eval <- function(string, visibly, output, package, + file = tempfile("ESSDev"), verbose = FALSE, + fallback_env = NULL, local_env = parent.frame()) { + cat(string, file = file) + on.exit(.ess.file.remove(file)) + .ess.ns_source(file, visibly, output, package = package, + verbose = verbose, fake.source = TRUE, + fallback_env = fallback_env, local_env = local_env) +} + + +##' Source FILE into an environment. After having a look at each new object in +##' the environment, decide what to do with it. Handles plain objects, +##' functions, existing S3 methods, S4 classes and methods. +##' @param fallback_env environment to assign objects which don't exist in the +##' package namespace +.ess.ns_source <- function(file, visibly, output, expr, + package = "", verbose = FALSE, + fake.source = FALSE, + fallback_env = NULL, + local_env = NULL) { + pname <- paste("package:", package, sep = "") + envpkg <- tryCatch(as.environment(pname), error = function(cond) NULL) + + if (is.null(envpkg)) { + if (suppressWarnings(require(package, quietly = TRUE, character.only = TRUE))) { + envpkg <- tryCatch(as.environment(pname), error = function(cond) NULL) + } else { + ## no such package; source in current (local) user environment + return(.ess.source(file, visibly = visibly, + output = output, local = local_env, + fake.source = fake.source)) + } + } + + envns <- tryCatch(asNamespace(package), error = function(cond) NULL) + if (is.null(envns)) + stop(gettextf("Can't find a namespace environment corresponding to package name '%s\"", + package), domain = NA) + + ## Here we know that both envns and envpkg exists and are environments + if (is.null(fallback_env)) + fallback_env <- .ess.ns_insert_essenv(envns) + + ## Get all Imports envs where we propagate objects + pkgEnvNames <- Filter(.ess.is_package, search()) + packages <- lapply(pkgEnvNames, function(envName) substring(envName, 9)) + importsEnvs <- lapply(packages, function(pkgName) parent.env(asNamespace(pkgName))) + + ## Evaluate the FILE into new ENV + env <- .ess.ns_evalSource(file, visibly, output, substitute(expr), package, fake.source) + envPackage <- getPackageName(env, FALSE) + if (nzchar(envPackage) && envPackage != package) + warning(gettextf("Supplied package, %s, differs from package inferred from source, %s", + sQuote(package), sQuote(envPackage)), domain = NA) + + ## Get all sourced objects, methods and classes + allObjects <- objects(envir = env, all.names = TRUE) + allObjects <- allObjects[!(allObjects %in% c(".cacheOnAssign", ".packageName"))] + MetaPattern <- methods:::.TableMetaPattern() + ClassPattern <- methods:::.ClassMetaPattern() + allPlainObjects <- allObjects[!(grepl(MetaPattern, allObjects) | + grepl(ClassPattern, allObjects))] + allMethodTables <- allObjects[grepl(MetaPattern, allObjects)] + allClassDefs <- allObjects[grepl(ClassPattern, allObjects)] + + ## PLAIN OBJECTS and FUNCTIONS: + funcNs <- funcPkg <- newFunc <- newNs <- newObjects <- newPkg <- objectsNs <- objectsPkg <- character() + dependentPkgs <- list() + + for (this in allPlainObjects) { + thisEnv <- get(this, envir = env) + thisNs <- NULL + + ## NS + if (exists(this, envir = envns, inherits = FALSE)){ + thisNs <- get(this, envir = envns) + if(is.function(thisNs) || is.function(thisEnv)){ + if(is.function(thisNs) && is.function(thisEnv)){ + if(.ess.differs(thisEnv, thisNs)){ + environment(thisEnv) <- environment(thisNs) + .ess.assign(this, thisEnv, envns) + funcNs <- c(funcNs, this) + if(exists(".__S3MethodsTable__.", envir = envns, inherits = FALSE)){ + S3_table <- get(".__S3MethodsTable__.", envir = envns) + if(exists(this, envir = S3_table, inherits = FALSE)) + .ess.assign(this, thisEnv, S3_table) + } + } + }else{ + newNs <- c(newNs, this) + } + }else{ + if(!identical(thisEnv, thisNs)){ + .ess.assign(this, thisEnv, envns) + objectsNs <- c(objectsNs, this) + } + } + }else{ + newNs <- c(newNs, this) + } + + ## PKG + if (exists(this, envir = envpkg, inherits = FALSE)){ + thisPkg <- get(this, envir = envpkg) + if(is.function(thisPkg) || is.function(thisEnv)){ + if(is.function(thisPkg) && is.function(thisEnv)){ + if(.ess.differs(thisPkg, thisEnv)){ + environment(thisEnv) <- environment(thisPkg) + .ess.assign(this, thisEnv, envpkg) + funcPkg <- c(funcPkg, this) + } + }else{ + newPkg <- c(newPkg, this) + } + }else{ + if(!identical(thisPkg, thisEnv)){ + .ess.assign(this, thisEnv, envpkg) + objectsPkg <- c(objectsPkg, this) + } + } + }else{ + newPkg <- c(newPkg, this) + } + + if (!is.null(thisNs)) { + isDependent <- .ess.ns_propagate(thisEnv, this, importsEnvs) + newDeps <- stats::setNames(list(packages[isDependent]), this) + dependentPkgs <- c(dependentPkgs, newDeps) + } + } + + ## deal with new plain objects and functions + for (this in intersect(newPkg, newNs)) { + thisEnv <- get(this, envir = env, inherits = FALSE) + if (exists(this, envir = fallback_env, inherits = FALSE)){ + thisGl <- get(this, envir = fallback_env) + if (.ess.differs(thisEnv, thisGl)) { + if (is.function(thisEnv)) { + environment(thisEnv) <- envns + newFunc <- c(newFunc, this) + } else { + newObjects <- c(newObjects, this) + } + .ess.assign(this, thisEnv, fallback_env) + if (.is.essenv(fallback_env)) + .ess.assign(this, thisEnv, .GlobalEnv) + } + } else { + if (is.function(thisEnv)) { + environment(thisEnv) <- envns + newFunc <- c(newFunc, this) + } else { + newObjects <- c(newObjects, this) + } + .ess.assign(this, thisEnv, fallback_env) + if (.is.essenv(fallback_env)) + .ess.assign(this, thisEnv, .GlobalEnv) + } + } + + if(length(funcNs)) + objectsNs <- c(objectsNs, sprintf("FUN[%s]", paste(funcNs, collapse = ", "))) + if(length(funcPkg)) + objectsPkg <- c(objectsPkg, sprintf("FUN[%s]", paste(funcPkg, collapse = ", "))) + if(length(newFunc)) + newObjects <- c(newObjects, sprintf("FUN[%s]", paste(newFunc, collapse = ", "))) + + ## CLASSES + classesPkg <- classesNs <- newClasses <- character() + for(this in allClassDefs){ + newPkg <- newNs <- FALSE + thisEnv <- get(this, envir = env) + if(exists(this, envir = envpkg, inherits = FALSE)){ + if(!.ess.identicalClass(thisEnv, get(this, envir = envpkg))){ + .ess.assign(this, thisEnv, envir = envpkg) + classesPkg <- c(classesPkg, this) + } + }else{ + newPkg <- TRUE + } + if(exists(this, envir = envns, inherits = FALSE)){ + if(!.ess.identicalClass(thisEnv, get(this, envir = envns))){ + .ess.assign(this, thisEnv, envir = envns) + classesNs <- c(classesNs, this) + } + }else{ + newNs <- TRUE + } + if(newNs && newPkg){ + if(exists(this, envir = fallback_env, inherits = FALSE)){ + if(!.ess.identicalClass(thisEnv, get(this, envir = fallback_env))){ + .ess.assign(this, thisEnv, envir = fallback_env) + newClasses <- c(newClasses, this) + } + }else{ + .ess.assign(this, thisEnv, envir = fallback_env) + newClasses <- c(newClasses, this) + } + } + } + if(length(classesPkg)) + objectsPkg <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(classesPkg, collapse = ", "))) + if(length(classesNs)) + objectsNs <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(classesNs, collapse = ", "))) + if(length(newClasses)) + newObjects <- gettextf("CLS[%s]", sub(ClassPattern, "", paste(newClasses, collapse = ", "))) + + ## METHODS: + ## Method internals: For efficiency reasons setMethod() caches + ## method definition into a global table which you can get with + ## 'getMethodsForDispatch' function, and when a method is dispatched that + ## table is used. When ess-developer is used to source method definitions the + ## two copies of the functions are identical up to the environment. The + ## environment of the cached object has namespace:foo as it's parent but the + ## environment of the object in local table is precisely namespace:foo. This + ## does not cause any difference in evaluation. + methodNames <- allMethodTables + methods <- sub(methods:::.TableMetaPrefix(), "", methodNames) + methods <- sub(":.*", "", methods) + methodsNs <- newMethods <- character() + for (i in seq_along(methods)){ + table <- methodNames[[i]] + tableEnv <- get(table, envir = env) + if(exists(table, envir = envns, inherits = FALSE)){ + inserted <- .ess.ns_insertMethods(tableEnv, get(table, envir = envns), envns) + if(length(inserted)) + methodsNs <- c(methodsNs, gettextf("%s{%s}", methods[[i]], paste(inserted, collapse = ", "))) + }else if(exists(table, envir = fallback_env, inherits = FALSE)){ + inserted <- .ess.ns_insertMethods(tableEnv, get(table, envir = fallback_env), envns) + if(length(inserted)) + newMethods <- c(newMethods, gettextf("%s{%s}", methods[[i]], paste(inserted, collapse = ", "))) + }else{ + .ess.assign(table, tableEnv, envir = fallback_env) + newMethods <- c(newMethods, gettextf("%s{%s}", methods[[i]], paste(objects(envir = tableEnv, all.names = T), collapse = ", "))) + } + } + if(length(methodsNs)) + objectsNs <- c(objectsNs, gettextf("METH[%s]", paste(methodsNs, collapse = ", "))) + if(length(newMethods)) + newObjects <- c(newObjects, gettextf("METH[%s]", paste(newMethods, collapse = ", "))) + + if (verbose) { + msgs <- unlist(list( + if(length(objectsPkg)) + sprintf("PKG: %s", paste(objectsPkg, collapse = ", ")), + if(length(objectsNs)) + sprintf("NS: %s", paste(objectsNs, collapse = ", ")), + if(length(dependentPkgs)) + .ess.ns_format_deps(dependentPkgs), + if(length(newObjects)) { + env_name <- .ess.ns_env_name(fallback_env) + sprintf("%s: %s", env_name, paste(newObjects, collapse = ", ")) + })) + if(length(msgs)) + .ess_mpi_message(paste(msgs, collapse = " ")) + + } + + invisible(env) +} + + +.ess.ns_insertMethods <- function(tableEnv, tablePkg, envns) { + inserted <- character() + for(m in ls(envir = tableEnv, all.names = T)){ + if(exists(m, envir = tablePkg, inherits = FALSE)){ + thisEnv <- get(m, envir = tableEnv) + thisPkg <- get(m, envir = tablePkg) + if(is(thisEnv, "MethodDefinition") && is(thisPkg, "MethodDefinition") && + .ess.differs(thisEnv@.Data, thisPkg@.Data)){ + environment(thisEnv@.Data) <- envns + ## environment of cached method in getMethodsForDispatch table is still env + ## not a problem as such, but might confuse users + .ess.assign(m, thisEnv, tablePkg) + inserted <- c(inserted, m) + }}} + inserted +} + +## our version of R's evalSource +.ess.ns_evalSource <- function(file, visibly, output, expr, package = "", + fake.source = FALSE) { + envns <- tryCatch(asNamespace(package), error = function(cond) NULL) + if(is.null(envns)) + stop(gettextf("Package \"%s\" is not attached and no namespace found for it", + package), domain = NA) + env <- new.env(parent = envns) + env[[".packageName"]] <- package + methods:::setCacheOnAssign(env, TRUE) + if (missing(file)) + eval(expr, envir = env) + else if (is(file, "character")) + for (f in file) { + .ess.source(f, local = env, visibly = visibly, + output = output, keep.source = TRUE, + max.deparse.length = 300, + fake.source = fake.source, + message.prefix = sprintf("[%s] ", package)) + } + else stop(gettextf("Invalid file argument: got an object of class \"%s\"", + class(file)[[1]]), domain = NA) + env +} + + +.ess.assign <- function(x, value, envir) { + ## Cannot add bindings to locked environments + exists <- exists(x, envir = envir, inherits = FALSE) + if (exists && bindingIsLocked(x, envir)) { + unlockBinding(x, envir) + assign(x, value, envir = envir, inherits = FALSE) + op <- options(warn = -1) + on.exit(options(op)) + lockBinding(x, envir) + } else if (exists || !environmentIsLocked(envir)) { + assign(x, value, envir = envir, inherits = FALSE) + } else { + warning(sprintf("Cannot assign `%s` in locked environment", x), + call. = FALSE) + } + invisible(NULL) +} + +.ess.identicalClass <- function(cls1, cls2, printInfo = FALSE) { + slots1 <- slotNames(class(cls1)) + slots2 <- slotNames(class(cls2)) + if(identical(slots1, slots2)){ + vK <- grep("versionKey", slots1) + if(length(vK)) + slots1 <- slots2 <- slots1[-vK] + out <- sapply(slots1, function(nm) identical(slot(cls1, nm), slot(cls2, nm))) + if(printInfo) print(out) + all(out) + } +} + +.ess.differs <- function(f1, f2) { + if (is.function(f1) && is.function(f2)){ + !(identical(body(f1), body(f2)) && identical(args(f1), args(f2))) + }else + !identical(f1, f2) +} + + +.ess.is_package <- function(envName) { + isPkg <- identical(substring(envName, 0, 8), "package:") + isPkg && (envName != "package:base") +} + +.ess.ns_propagate <- function(obj, name, importsEnvs) { + containsObj <- vapply(importsEnvs, logical(1), FUN = function(envs) { + name %in% names(envs) + }) + + lapply(importsEnvs[containsObj], .ess.assign, + x = name, value = obj) + + containsObj +} + + +.ess.ns_format_deps <- function(dependentPkgs) { + pkgs <- unique(unlist(dependentPkgs, use.names = FALSE)) + + lapply(pkgs, function(pkg) { + isDep <- vapply(dependentPkgs, function(deps) pkg %in% deps, logical(1)) + pkgDependentObjs <- names(dependentPkgs[isDep]) + sprintf("DEP:%s [%s] ", pkg, paste(pkgDependentObjs, collapse = ", ")) + }) +} + +.ess.ns_env_name <- function(env) { + name <- environmentName(env) + name <- + if (name == "") "Local" + else if (grepl("^essenv:", name)) "NEW" + else name + name +} + + +.ess.ns_insert_essenv <- function(nsenv) { + if (is.character(nsenv)) + nsenv <- asNamespace(nsenv) + stopifnot(isNamespace(nsenv)) + if (identical(nsenv, .BaseNamespaceEnv)) + return(.GlobalEnv) + essenv_name <- sprintf("essenv:%s", environmentName(nsenv)) + nsenv_parent <- parent.env(nsenv) + if (environmentName(nsenv_parent) == essenv_name) { + return(nsenv_parent) + } + essenv <- new.env(parent = nsenv_parent) + essenv[[".__ESSENV__."]] <- TRUE + attr(essenv, "name") <- essenv_name + nssym <- ".__NAMESPACE__." + nssym_val <- get(nssym, envir = nsenv, inherits = FALSE) + unlockBinding(nssym, nsenv) + nsenv[[nssym]] <- NULL + on.exit({ + nsenv[[nssym]] <- nssym_val + lockBinding(nssym, nsenv) + }) + parent.env(nsenv) <- essenv + essenv +} + +.is.essenv <- function(env) { + exists(".__ESSENV__.", envir = env, inherits = FALSE) +} diff --git a/elpa/ess-20230419.1527/etc/ESSR/R/pkg.R b/elpa/ess-20230419.1527/etc/ESSR/R/pkg.R new file mode 100644 index 00000000..ebd0463a --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ESSR/R/pkg.R @@ -0,0 +1,26 @@ + +.ess_keep <- function(.x, .f, ...) { + is_true <- vapply(.x, .f, logical(1), ...) + .x[is_true] +} + +.ess_devtools_functions <- function() { + if (!requireNamespace("devtools")) { + .ess_mpi_error("devtools is not installed") + stop("internal error") + } + devtools_env <- asNamespace("devtools") + exports <- getNamespaceExports("devtools") + funs_exported <- as.list(devtools_env)[exports] + + is_first_arg <- function(f, arg) { + args <- names(formals(f)) + length(args) && args[[1]] == arg + } + + funs_pkg <- .ess_keep(funs_exported, is.function) + funs_pkg <- .ess_keep(funs_pkg, is_first_arg, "pkg") + funs_names <- sort(names(funs_pkg)) + + funs_names +} diff --git a/elpa/ess-20230419.1527/etc/Makefile b/elpa/ess-20230419.1527/etc/Makefile new file mode 100644 index 00000000..e2d22768 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/Makefile @@ -0,0 +1,52 @@ +### Makefile - for scripts and icons (./etc) of ESS distribution. +### + +## Before making changes here, please take a look at Makeconf +include ../Makeconf + +#ETCFILES = $(wildcard BACKBUG[S5].BAT backbug[s5] *.S sas-keys.*) +#ETCFILES = ESSR.R ess-developer.R SVN-REVISION *.S sas-keys.* ess-sas-sh-command +# ETCFILES_1 = *.S sas-keys.* ess-sas-sh-command *.jl +ETCFILES_1 = ess-sas-sh-command *.jl +isRELEASE=$(shell test -f .IS.RELEASE && echo 'yes') +ifeq ($(isRELEASE),yes) + ETCFILES = .IS.RELEASE git-ref $(ETCFILES_1) +else + ETCFILES = $(ETCFILES_1) +endif + +#ICONS = $(wildcard icons/*.xpm) +ICONS = icons/*.xpm + +ESSR_UTIL_FILES = ESSR/LOADREMOTE +ESSR_CODE_FILES = ESSR/R/*.R ESSR/R/.*.R + +all: + +show-etc: + @echo $(ETCFILES) + ls -l $(ETCFILES) + +install : + $(INSTALLDIR) $(ETCDIR)/icons + $(INSTALLDIR) $(ETCDIR)/ESSR/R + $(INSTALL) $(ETCFILES) $(ETCDIR) + $(INSTALL) $(ICONS) $(ETCDIR)/icons + $(INSTALL) $(ESSR_UTIL_FILES) $(ETCDIR)/ESSR + $(INSTALL) $(ESSR_CODE_FILES) $(ETCDIR)/ESSR/R + chmod +x $(ETCDIR)/ess-sas-sh-command + +uninstall : + -cd $(ETCDIR) && $(UNINSTALL) $(ETCFILES) + -cd $(ETCDIR) && $(UNINSTALL) $(ICONS) + -cd $(ETCDIR) && $(UNINSTALL) $(ESSR_UTIL_FILES) + -cd $(ETCDIR) && $(UNINSTALL) $(ESSR_CODE_FILES) + + + +## 'clean' shall remove *exactly* those things that are *not* in version control +clean distclean: + rm -rf SVN-REVISION +## 'distclean' removes also things in VC (svn, when they are remade by "make"): +# distclean: clean +# rm -rf ESSR_*.tar.gz diff --git a/elpa/ess-20230419.1527/etc/ess-julia.jl b/elpa/ess-20230419.1527/etc/ess-julia.jl new file mode 100644 index 00000000..efa1ce0c --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ess-julia.jl @@ -0,0 +1,126 @@ +module ESS + +# These methods have been deprecated / moved +macro current_module() + return VERSION >= v"0.7-" ? :(@__MODULE__) : :(current_module()) +end + +parse = VERSION >= v"0.7-" ? Base.Meta.parse : Base.parse +function_module = VERSION >= v"0.7-" ? Base.parentmodule : Base.function_module + +function all_help_topics() + ## There are not clear topics anymore. Approximate those with a very general + ## apropos(" ") + Base.Docs.apropos(" ") +end + +function help(topic::AbstractString) + if (VERSION >= v"1.0-") + Core.eval(parentmodule(ESS), parse("@doc $topic")) + elseif (VERSION >= v"0.4-") + Core.eval(@current_module(), parse("@doc $topic")) + else + Base.Help.help(topic) + end +end + +## modified version of function show(io::IO, m::Method) +function fun_args(m::Method) + tv, decls, file, line = Base.arg_decl_parts(m) + io = VERSION >= v"0.7-" ? Base.stdout : STDOUT::IO # STDOUT is no longer in 1.0 + if !isempty(tv) + Base.show_delim_array(io, tv, '{', ',', '}', false) + end + print(io, "(") + join(io, [escape_string(isempty(d[2]) ? d[1] : d[1]*"::"*d[2]) for d in decls], + ",", ",") + Base.print(io, ")") +end + +## modified versionof show(io::IO, mt::MethodTable) +function fun_args(f::Function) + mt = Base.MethodList(methods(f).mt) + mod = function_module(f) # Base.function_module deprecated in 0.7 + if mod == Main + mod = "nil" + end + print("(list \"$mod\" nil '(") + for d in mt + print("\"") + ## method + fun_args(d) + print("\" ") + end + print("))") +end + +function fun_args(s::AbstractString) + try + mod = VERSION >= v"1.0-" ? parentmodule(ESS) : @current_module() + m = Core.eval(mod, parse(s)) + if ! isa(m, String) + fun_args(m) + end + catch + print("(list nil nil nil)") + end +end + +function fun_args(t::DataType) + print("(list nil nil '(") + for d = fieldnames(t) + print("\"$d\" ") + end + print("))") +end + + +### OBJECT COMPLETION +# Must print an output of the form: +# +# Cache Module +# Write Module +# add Function +# free Function +function components(m::Module) + for v in sort(names(m, all=true, imported=true)) + s = string(v) + if !startswith(s, "#") && isdefined(m,v) + println(rpad(s, 30), summary(Core.eval(m,v))) + end + end +end + +function components(t::DataType) + for v in sort(fieldnames(t)) + println(rpad(string(v), 30), "field") + end +end + +function components(v) + t = typeof(v) + if isa(t, DataType) + return components(t) + end +end + + +### MISC +function main_modules(m::Module) + for nm in names(m) + if isdefined(m, nm) + mod = Core.eval(m, nm) + if isa(mod, Module) + print("\"$nm\" ") + end + end + end +end + +if VERSION >= v"0.7-" + main_modules() = main_modules(Base.parentmodule(@current_module())) +else + main_modules() = main_modules(@current_module()) +end + +end diff --git a/elpa/ess-20230419.1527/etc/ess-sas-sh-command b/elpa/ess-20230419.1527/etc/ess-sas-sh-command new file mode 100755 index 00000000..7c1d9101 --- /dev/null +++ b/elpa/ess-20230419.1527/etc/ess-sas-sh-command @@ -0,0 +1,76 @@ +#!/bin/sh + +### (C) 1997, Richard M. Heiberger. +### This file is part of ESS. + +## This file is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2, or (at your option) +## any later version. + +## This file is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## A copy of the GNU General Public License is available at +## https://www.r-project.org/Licenses/ + + +# For executing SAS, and running it in the proper manner for ESS +# (feeding output back into appropriate ESS buffers). + +#echo $0 $@ +#sas $1 2>$2 $3 + +set -x +stdout=$1 +stderr=$2 +shift 2 +set +x +echo sas \$stdout 2\>$stderr $@ +sas $stdout 2>$stderr $@ + +## From the SAS online tech support: +## +## Redirecting the SAS Log and Output under UNIX. +## +## There are several ways of redirecting the SAS Log and Output under +## UNIX. +## +## To redirect the SAS Log, follow one of these steps: +## +## 1. +## In the source code, place the following line: +## +## proc printto log=stdout; +## +## to make a duplicate copy of the log in a file in addition +## to redirecting it to stdout, use this command to invoke +## SAS: +## +## sas -altlog doit.log doit.sas +## +## 2.Execute SAS in the background and use the UNIX 'tail' command +## to copy lines to stdout as they are added to the log. Use the +## command: +## +## sas doit.sas &; tail -f doit.log +## +## To redirect the SAS Log and Output under the Korn shell, use the +## following command: +## +## sas -stdio < doit.sas > doit.lst 2> doit.log +## +## To redirect the SAS Log and Output under the C-Shell, use the +## following command: +## +## (sas -stdio < doit.sas > doit.lst) >& doit.log + +## From WWW.SAS.COM: +## How can I make SAS in batch mode behave like interactive SAS, +## continue running my SAS job, and not enter syntax check mode when +## it encounters an error? +## +## You can specify the NOSYNTAXCHECK option when you invoke your SAS +## program. diff --git a/elpa/ess-20230419.1527/obsolete/ess-eldoc.el b/elpa/ess-20230419.1527/obsolete/ess-eldoc.el new file mode 100644 index 00000000..59f0c466 --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/ess-eldoc.el @@ -0,0 +1,173 @@ +;;; ess-eldoc.el --- Use eldoc to report R function names. -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: Stephen Eglen +;; Created: 2007-06-30 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;;;;; eldoc functionality has been moved into the core ;;;;; +;;;;; this file has no effect and is left in ESS in order not to break +;;;;; users configuration + +;; This is an initial attempt to use the emacs facility ELDOC in R +;; buffers. Eldoc is used in Emacs lisp buffers to show the function +;; arglist and docstrings for variables. To try it, view an emacs +;; lisp buffer, and then do M-x turn-on-eldoc-mode, and move over +;; function and variable names. + +;; This file extends eldoc to work in R buffers. It currently uses +;; Sven's ess-r-args.el file to retrieve args for a given R function +;; (via ess-r-args-get). Note that it works slightly different to +;; Sven's code, in that you just need to have the point over the name +;; of an R function, or inside its arguments list, for eldoc to show +;; the arg list. + +;; To use this functionality, simply add +;; +;; (require 'ess-eldoc) +;; +;; to your .emacs file. When you visit a R mode, eldoc will be turned +;; on. However, you will first need to associate the R buffer with an +;; *R* process so that args can be looked up -- otherwise, eldoc will +;; silently not report anything. So, e.g. try: +;; C-x C-f somefile.R +;; M-x R (so that somefile.R is associated with *R*) +;; eldoc should then work. + +;; e.g. put the following rnorm() command in an R buffer. The line +;; underneath shows a key of what arg list will be shown as you move +;; across the rnorm line. + +;; rnorm(n=100, mean=sqrt(20), sd=10) +;; 1111111111111222223333333311444111 +;; 1: rnorm +;; 2: mean +;; 3: sqrt +;; 4: sd +;; + +;; Note that the arg list for rnorm() should be shown either when you +;; are on the function name, or in the arg list. However, since the +;; 2nd and 3rd arguments are also function names, the arg lists of +;; those function names are reported instead. This might be seen as +;; undesirable behaviour, in which case a solution would be to only +;; look up the function name if it is followed by (. + +;; If you want to use this feature in *R* buffers, add the following +;; to .emacs: +;; (add-hook 'inferior-ess-mode-hook 'ess-use-eldoc) + + +;; In the current version, I do not cache the arg list, but that was +;; done in an earlier version, to save repeated calls to +;; ess-r-args-get. + +;; This code has been tested only in Emacs 22.1. It will not work on +;; Emacs 21, because it needs the variable +;; eldoc-documentation-function. + +;;;; VS [25-02-2012]: all these issues were at least partially addressed in the +;;;; new implementation: + +;; Bug (in eldoc?): the arg list for legend() is too long to fit in +;; minibuffer, and it seems that we see the last N lines of the arg +;; list, rather than the first N lines. It would be better to see the +;; first N lines since the more important args come first. + +;; Doc issue: the eldoc vars (e.g. eldoc-echo-area-use-multiline-p) +;; work only for elisp mode. + +;; Issue: You will probably see the message "Using process 'R'" flash; +;; this is generated by `ess-request-a-process', and I'd like to avoid +;; that appearing, non-interactively. + +;; If *R* is currently busy (e.g. processing Sys.sleep(999)), then the +;; eldoc commands won't work; ess-command could be silenced in this +;; regard perhaps with a new SILENT arg for example to prevent the +;; call to (ess-error). + + +;;; Code: + +;; ;; This could be done on buffer local basis. +;; (setq ess-r-args-noargsmsg "") + +;; ;; following two defvars are not currently used. +;; (defvar ess-eldoc-last-name nil +;; "Name of the last function looked up in eldoc. +;; We remember this to see whether we need to look up documentation, or used +;; the cached value in `ess-eldoc-last-args'.") + +;; (defvar ess-eldoc-last-args nil +;; "Args list last looked up for eldoc. Used as cache.") + +;; (defun ess-eldoc-2 () +;; ;; simple, old version. +;; (interactive) +;; (ess-r-args-get (ess-read-object-name-default))) + +;; (defun ess-eldoc-1 () +;; "Return the doc string, or nil. +;; This is the first version; works only on function name, not within arg list." +;; (interactive) + +;; ;; Possible ways to get the function at point. +;; ;;(setq name (thing-at-point 'sexp)) +;; ;;(setq name (ess-read-object-name-default)) +;; ;;(setq name (find-tag-default)) + +;; (if ess-current-process-name +;; (progn +;; (setq name (ess-guess-fun)) ;guess the word at point. +;; (if (equal (length name) 0) +;; nil +;; ;; else +;; (unless (equal name ess-eldoc-last-name) +;; ;; name is different to the last name we lookedup, so get +;; ;; new args from R and store them. +;; (setq ess-eldoc-last-args (ess-r-args-get name) +;; ess-eldoc-last-name name)) +;; ess-eldoc-last-args)) +;; ;; no ESS process current. +;; nil) +;; ) + + +;; (defsubst ess-guess-fun () +;; "Guess what the function at point is." +;; ;; Derived from Man-default-man-entry in man.el +;; (let (word) +;; (save-excursion +;; (skip-chars-backward "-a-zA-Z0-9._+:") +;; (let ((start (point))) +;; (skip-chars-forward "-a-zA-Z0-9._+:") +;; (setq word (buffer-substring-no-properties start (point))))) +;; word)) + +(defun ess-use-eldoc () + "Does nothing. Defined not to break old users' code." + (interactive)) + +(provide 'ess-eldoc) + +;;; ess-eldoc.el ends here diff --git a/elpa/ess-20230419.1527/obsolete/ess-font-lock.el b/elpa/ess-20230419.1527/obsolete/ess-font-lock.el new file mode 100755 index 00000000..0487b550 --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/ess-font-lock.el @@ -0,0 +1,150 @@ +;;; ess-font-lock.el --- font-lock color options -*- lexical-binding: t; -*- + +;; Copyright (C) 2000-2022 Free Software Foundation, Inc. + +;; Author: Richard M. Heiberger +;; Created: 06 Feb 2000 + +;; Keywords: languages, faces + +;; This file is part of ESS + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; A copy of the GNU General Public License is available at +;; https://www.r-project.org/Licenses/ + +;;; Commentary: + +;; provides syntax highlighting support. + +;;; Code: + + ; Requires and autoloads + +(require 'font-lock) +(require 'paren) + +;; FIXME: What is this doing here!? +(if (fboundp 'show-paren-mode) (show-paren-mode 1)) + +;;; Emacs 20.x notes: + +;; font-lock faces are defined in /emacs/emacs-20.5/lisp/font-lock.el +;; The font-lock faces are applied to ESS buffers by +;; ess-mode.el ess-inf.el ess-trns.el ess-custom.el +;; The keywords for faces are defined in the ess[dl]*.el files. +;; All faces can be looked at, under Emacs 20.x, with +;; [menu-bar] [Edit] [Text Properties] [Display Faces} + +(defun ess-font-lock-rmh () + "Set font-lock colors to Richard Heiberger's usual choice." + ;; FIXME: Turn it into a Custom theme! + (interactive) + + (set-foreground-color "Black") + (set-background-color "lightcyan") + + (set-face-background 'mode-line "lightskyblue") + (set-face-foreground 'mode-line "midnightblue") + + (set-face-foreground 'font-lock-comment-face "Firebrick") + (set-face-foreground 'font-lock-function-name-face "Blue") + (set-face-foreground 'font-lock-keyword-face "Purple") + (set-face-foreground 'font-lock-constant-face "Brown") + (set-face-foreground 'font-lock-string-face "VioletRed") + (set-face-foreground 'font-lock-type-face "Sienna") + (set-face-foreground 'font-lock-variable-name-face "Black")) + +(defun ess-font-lock-blue () + "Set font-lock colors to Richard Heiberger's blue color scheme." + ;; FIXME: Turn it into a Custom theme! + (interactive) + + (set-foreground-color "Black") + (set-background-color "LightBlue") + + (set-face-foreground 'mode-line "LightBlue") + (set-face-background 'mode-line "DarkSlateBlue") + + (set-face-foreground 'font-lock-comment-face "Firebrick") + (set-face-foreground 'font-lock-function-name-face "Blue") + (set-face-foreground 'font-lock-keyword-face "Purple") + (set-face-foreground 'font-lock-constant-face "Brown") + (set-face-foreground 'font-lock-string-face "VioletRed") + (set-face-foreground 'font-lock-type-face "Sienna") + (set-face-foreground 'font-lock-variable-name-face "Black")) + +(defun ess-font-lock-wheat () + "Set font-lock colors to Richard Heiberger's wheat color scheme." + ;; FIXME: Turn it into a Custom theme! + (interactive) + + (set-foreground-color "Black") + (set-background-color "Wheat") + + (set-face-foreground 'mode-line "Wheat") + (set-face-background 'mode-line "Sienna") + + (set-face-foreground 'font-lock-comment-face "Firebrick") + (set-face-foreground 'font-lock-function-name-face "Blue") + (set-face-foreground 'font-lock-keyword-face "Purple") + (set-face-foreground 'font-lock-constant-face "Brown") + (set-face-foreground 'font-lock-string-face "VioletRed") + (set-face-foreground 'font-lock-type-face "Sienna") + (set-face-foreground 'font-lock-variable-name-face "Black")) + + +(defun ess-font-lock-bw () + "Set font-lock colors to Richard Heiberger's black and white color scheme." + ;; FIXME: Turn it into a Custom theme! + (interactive) + + (set-foreground-color "Black") + (set-background-color "white") + + (set-face-foreground 'mode-line "gray10") + (set-face-background 'mode-line "gray90") + + ;; modify-face is an interactive compiled Lisp function in `faces'. + ;; Sample usage: + + ;;(modify-face FACE FOREGROUND BACKGROUND STIPPLE BOLD-P ITALIC-P UNDERLINE-P &optional INVERSE-P FRAME) + + (modify-face 'mode-line "gray10" "gray90" nil nil t nil ) + (modify-face 'font-lock-comment-face "black" "white" nil nil t nil ) + (modify-face 'font-lock-function-name-face "black" "white" nil t nil nil ) + (modify-face 'font-lock-keyword-face "black" "white" nil nil nil t ) + (modify-face 'font-lock-constant-face "black" "white" nil t nil nil ) + (modify-face 'font-lock-string-face "black" "white" nil nil t t ) + (modify-face 'font-lock-type-face "black" "white" nil t t nil ) + (modify-face 'font-lock-variable-name-face "black" "white" nil nil nil nil ) + (modify-face 'font-lock-builtin-face "black" "white" nil t nil nil ) + (modify-face 'font-lock-warning-face "black" "white" nil t nil nil ) + (modify-face 'show-paren-match-face "gray20" "gray80" nil t nil nil ) + (modify-face 'show-paren-mismatch-face "white" "gray40" nil t t nil )) + +(defun ess-font-lock-db () + "Set font-lock colors (leave fore-/back-ground alone) courtesy David Brahm " + ;; FIXME: Turn it into a Custom theme! + (interactive) + (set-face-foreground 'font-lock-comment-face "Firebrick") ; #... %... + (set-face-foreground 'font-lock-string-face "SeaGreen") ; "..." "..." + (set-face-foreground 'font-lock-keyword-face "MediumBlue") ; if \end + (set-face-foreground 'font-lock-function-name-face "VioletRed") ; talk<- {center} + (set-face-foreground 'font-lock-variable-name-face "Blue") ; xv + (set-face-foreground 'font-lock-type-face "Goldenrod") ; T,F ? + (set-face-foreground 'font-lock-constant-face "Magenta") ; <- {eq1} + ) + +(provide 'ess-font-lock) + +;;; ess-font-lock.el ends here diff --git a/elpa/ess-20230419.1527/obsolete/ess-mouse.el b/elpa/ess-20230419.1527/obsolete/ess-mouse.el new file mode 100644 index 00000000..6e6976d8 --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/ess-mouse.el @@ -0,0 +1,222 @@ +;;; ess-mouse.el --- Support for mouse- or cursor-sensitive actions -*- lexical-binding: t; -*- + +;; Copyright (C) 2001-2022 Free Software Foundation, Inc. +;; Author: Richard M. Heiberger +;; Created: 25 Mar 2001 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; Support for mouse- or cursor-sensitive actions. This is based on +;; and uses mouseme.el. mouseme.el only does mouse sensitivity. +;; The new functions ess-mouse-me and ess-mouse-me-helper do similar +;; things based on the cursor, not the mouse, and can be bound to a +;; keystroke. + +;;; Code: + + ; Requires and autoloads + +;;*;; Requires +(require 'mouseme) +(require 'ess-trns) +;;(if (or (equal window-system 'w32) +;; (equal window-system 'win32) +;; (equal window-system 'mswindows)) +;; (require 'essiw32b)) + +(defun ess-mouse-me () + "Popup a menu of functions to run on selected string or region." + (interactive) + (ess-mouse-me-helper + (lambda (name) + (or (x-popup-menu (list '(0 0) + (get-buffer-window (get-buffer (buffer-name)))) + (funcall mouse-me-build-menu-function name)) + (error "No command to run"))))) + + + +(defun ess-mouse-me-helper (func) + "Determine the string to use to process EVENT and call FUNC to get cmd." + (let (name sp sm mouse beg end cmd mmtype) + ;; temporarily goto where the event occurred, get the name clicked + ;; on and enough info to figure out what to do with it + (save-match-data + (save-excursion + (setq sp (point)) ; saved point + (setq sm (mark t)) ; saved mark +;;; (set-buffer (window-buffer (posn-window (event-start event)))) +;;; (setq mouse (goto-char (posn-point (event-start event)))) + (setq mouse (point)) ;; ess-mouse-me-helper + ;; if there is a region and point is inside it + ;; check for sm first incase (null (mark t)) + ;; set name to either the thing they clicked on or region + (if (and sm + (or (and transient-mark-mode mark-active) + (eq last-command 'mouse-drag-region)) + (>= mouse (setq beg (min sp sm))) + (<= mouse (setq end (max sp sm)))) + (setq name (buffer-substring beg end)) + (setq name (funcall mouse-me-get-string-function)) + (if (listp name) + (setq beg (nth 1 name) + end (nth 2 name) + name (car name)) + (goto-char mouse) + (while (not (looking-at (regexp-quote name))) + (backward-char 1)) + (setq beg (point)) + (setq end (search-forward name)))))) + ;; check if name is null, meaning they clicked on no word + (if (or (null name) + (and (stringp name) (string= name "" ))) + (error "No string to pass to function")) + ;; popup a menu to get a command to run + (setq cmd (funcall func name)) + ;; run the command, eval'ing if it was a list + (if (listp cmd) + (setq cmd (eval cmd t))) + (setq mmtype (get cmd 'mouse-me-type)) + (cond ((eq mmtype 'region) + (funcall cmd beg end)) + ((eq mmtype 'string) + (funcall cmd name)) + (t + (funcall cmd name))))) + +(defcustom ess-S-mouse-me-menu-commands-alist + '("S-Plus 4 and 6 GUI under Windows" + ("Edit.data" . ess-mouse-me-Edit.data) + "----" + ("print" . ess-mouse-me-print) + ("summary" . ess-mouse-me-summary) + ("plot" . ess-mouse-me-plot) + ("show" . ess-mouse-me-show) + ("help" . ess-display-help-on-object) + ("args" . ess-mouse-me-args) + "----" + ("Browser on" . ess-mouse-me-browser-on) + ("Browser off" . ess-mouse-me-browser-off)) + "Command menu used by `mouse-me-build-menu'. +A alist of elements where each element is either a cons cell or a string. +If a cons cell the car is a string to be displayed in the menu and the +cdr is either a function to call passing a string to, or a list which evals +to a function to call passing a string to. If the element is a string +it makes a non-selectable element in the menu. To make a separator line +use a string consisting solely of hyphens. + +The function returned from this menu will be called with one string +argument. Or if the function has the symbol property `mouse-me-type' +and if its value is the symbol `region' it will be called with the +beginning and ending points of the selected string. If the value is +the symbol `string' it will be called with one string argument." + :type '(repeat sexp) + :group 'mouseme) + + +(defun ess-mouse-me-Edit.data (string) + (ess-mouse-me-eval-expanded string "Edit.data(" ")" nil nil nil)) + +(defun ess-mouse-me-print (string) + (ess-mouse-me-eval-expanded string "" "" nil nil t)) +(defun ess-mouse-me-summary (string) + (ess-mouse-me-eval-expanded string "summary(" ")" nil nil t)) +(defun ess-mouse-me-plot (string) + (ess-mouse-me-eval-expanded string "plot(" ")") nil nil nil) +(defun ess-mouse-me-show (string) + (ess-mouse-me-eval-expanded string "show(" ")") nil nil nil) +(defun ess-mouse-me-args (string) + (ess-mouse-me-eval-expanded string "args(" ")" nil nil t)) + +(defun ess-mouse-me-browser-on (string) + (if (equal (substring ess-dialect 0 1) "R") + (ess-eval-linewise (concat "debug(" string ")")) + (ess-mouse-me-eval-expanded string "trace(" ", exit=browser)") nil nil nil)) + +(defun ess-mouse-me-browser-off (string) + (if (equal (substring ess-dialect 0 1) "R") + (ess-eval-linewise (concat "undebug(" string ")")) + (ess-mouse-me-eval-expanded string "untrace(" ")") nil nil nil)) + + + +(defun ess-mouse-me-eval-expanded (string &optional head tail commands-buffer + _page value-returned) + "Send the expanded STRING to the inferior-ess process using `ess-command' +after first concating the HEAD and TAIL. Put answer in COMMANDS-BUFFER if +specified, otherwise in \"tmp-buffer\". In either +case the buffer containing the answer is renamed to the value of the +constructed command. If PAGE is non-nil, expand +the string one more time by embedding it in a \"page()\" command." + (interactive) + (let* (scommand + ;; page-scommand + (lproc-name ess-local-process-name) + (ess-mouse-customize-alist ess-local-customize-alist)) + (if (not head) (setq head "summary(")) + (if (not tail) (setq tail ")")) + (if (not commands-buffer) (setq commands-buffer + (get-buffer-create "tmp-buffer"))) + (setq scommand (concat head string tail)) + + (ess-make-buffer-current) + (pop-to-buffer-same-window commands-buffer) + (ess-setq-vars-local (eval ess-mouse-customize-alist t) (current-buffer)) + (setq ess-local-process-name lproc-name) + (ess-command (concat scommand "\n") commands-buffer) + (if (not value-returned) (pop-to-buffer-same-window (nth 1 (buffer-list)))) + (if (not value-returned) + nil + (if ess-microsoft-p ;; there ought to be a filter + (while (search-forward "\r" nil t) ;; function to keep the ^M + (replace-match "" nil t))) ;; from showing up at all + (ess-transcript-mode) + (setq ess-local-process-name lproc-name) + (rename-buffer scommand)))) + + + ; Provide package + +(provide 'ess-mouse) + + + +;;;;;;;; STARTUP STUFF ;;;;;;;;;;;; + +(make-variable-buffer-local 'mouse-me-menu-commands) + +(defun ess-S-mouse-me-menu-commands () + (if (equal ess-language "S") + (setq mouse-me-menu-commands ess-S-mouse-me-menu-commands-alist))) + +;; (define-key ess-mode-map [S-mouse-3] 'ess-mouse-me) +;; (define-key inferior-ess-mode-map [S-mouse-3] 'ess-mouse-me) +;; (defun ess-S-mouse-me-ess-transcript-mode () +;; (define-key ess-transcript-mode-map [S-mouse-3] 'ess-mouse-me)) +;; +(add-hook 'ess-mode-hook #'ess-S-mouse-me-menu-commands) +(add-hook 'inferior-ess-mode-hook #'ess-S-mouse-me-menu-commands) +(add-hook 'ess-transcript-mode-hook #'ess-S-mouse-me-menu-commands) +;; (add-hook 'ess-transcript-mode-hook 'ess-S-mouse-me-ess-transcript-mode) + + +;;; ess-mouse.el ends here diff --git a/elpa/ess-20230419.1527/obsolete/ess-r-a.el b/elpa/ess-20230419.1527/obsolete/ess-r-a.el new file mode 100644 index 00000000..7872fbac --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/ess-r-a.el @@ -0,0 +1,153 @@ +;;; ess-r-a.el -- Possible local customizations for R with ESS. -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 Free Software Foundation, Inc. +;; Author: A.J. Rossini +;; Created: 17 November 1999 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; The purpose of this file is to demonstrate some of the extras that +;; have been constructed for the ESS R mode; if they prove +;; interesting, then they might be migrated to ess-r-mode, the primary +;; ESS R mode tools. + +;;; Code: +(require 'ess-inf) +(require 'ess-r-mode) + +;; you can invoke ESS/R from emacs by typing +;; C-u M-x essr +;; with vsize set to (for example) 40M, and nsize set to 600000. + +;; Undefined on non-apple devices +(declare-function ns-do-applescript "nsfns.m" (script)) +(declare-function do-applescript "ess-r-a" (script)) +(unless (fboundp 'do-applescript) + (defalias 'do-applescript #'ns-do-applescript)) + +(defalias 'essr + (read-kbd-macro + "C-u M-x R RET - - vsize = 40M SPC - - nsize = 600000 2*RET")) + +(defun ess-r-do-region (start end) + "Send from START to END to R via AppleScript." + (interactive "r\nP") + (message "Starting evaluation...") + (do-applescript (concat + "try\n" + "tell application \"R\"\n" + "activate\n" + "with timeout of 0 seconds\n" + "cmd \"" (buffer-substring start end) + "\"\n" + "end timeout\n" + "end tell\n" + "end try\n")) + (message "Finished evaluation")) + +(defun ess-r-do-line () + "Send the current line to R via AppleScript." + (interactive) ;; "r\nP") + (message "Starting evaluation...") + (save-excursion + (let ((end (point))) + (move-to-column 0) + (do-applescript (concat + "try\n" + "tell application \"R\"\n" + "activate\n" + "with timeout of 0 seconds\n" + "cmd \"" (buffer-substring (point) end) + "\"\n" + "end timeout\n" + "end tell\n" + "end try\n")))) + (message "Finished evaluation")) + +(defun ess-r-var (beg end) + "Load the current region of numbers into an R variable. +Prompts for a variable name. If none is given, it uses a default +variable name, e. BEG and END denote the region in the current +buffer to be sent." + (interactive "r") + (save-window-excursion + (let ((tmp-file (make-temp-file "ess-r-var")) + cmd + var) + (write-region beg end tmp-file) + + ;; Decide on the variable name to use in R; could use completion. + (setq var (read-string "R Variable name (default e): ")) + (if (equal var "") + (setq var "e")) + + ;; Command to send to the R process. Get R to delete the file + ;; rather than Emacs in case it takes R a long time to run the + ;; scan command. + (setq cmd (concat var " <- scan(\"" tmp-file "\"); " + "unlink(\"" tmp-file "\")" )) + + ;; Put the output from the scan command into the process buffer so + ;; the user has a record of it. + (ess-execute cmd 'buffer)))) + + +;;; Peter Dalgaard's code. +;;; This needs to be cleaned and validated! + +(defun pd::set-up-demo () + (run-ess-r) + (split-window-vertically 6) + (find-file "demos.R") + + ;; Don't need to run this as a function -- ought to be fine if set + ;; just once. + + (defun ajr::scroll-to-end::peterD (emacs) + "Goal: map prompt to bottom of the screen after every command. +Alternatively, use the scroll-in-place package, not sure where that +is)." + (interactive) + (other-buffer 1) + (if (= emacs "emacs") + (setq scroll-up-aggressively t) + (setq scroll-conservatively -4)) ;; <- change this + (other-buffer -1)) + + (defun show-max-other-window () + (interactive) + (other-window 1) + (comint-show-maximum-output) + (other-window -1)) + + ;; call this once + ;; (ajr::scroll-to-end::peterD "emacs") + + (global-set-key [f11] #'show-max-other-window) + (global-set-key [f12] #'ess-eval-line-visibly-and-step)) + + + ; Provide package + +(provide 'ess-r-a) + +;;; ess-r-a.el ends here diff --git a/elpa/ess-20230419.1527/obsolete/mouseme.el b/elpa/ess-20230419.1527/obsolete/mouseme.el new file mode 100644 index 00000000..82e7c61d --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/mouseme.el @@ -0,0 +1,354 @@ +;;; mouseme.el --- mouse menu with commands that operate on strings -*- lexical-binding: t; -*- + +;; Copyright (C) 1997-2022 by Free Software Foundation, Inc. + +;; Author: Howard Melman +;; Keywords: mouse, menu + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; This package provides a command `mouse-me' to be bound to a mouse +;; button. It pops up a menu of commands that operate on strings or a +;; region. The string passed to the selected command is the word or +;; symbol clicked on (with surrounding quotes or other punctuation +;; removed), or the region (if either it was just selected with the +;; mouse or if it was active with `transient-mark-mode' on). If the +;; command accepts a region, the selected region (or the region of the +;; word or symbol clicked on) will be passed to the command. + +;; The idea is that for any given string in a buffer you may want to +;; do different things regardless of the mode of the buffer. URLs +;; now appear in email, news articles, comments in code, and in plain +;; text. You may want to visit that URL in a browser or you may just +;; want to copy it to the kill-ring. For an email address you might +;; want to compose mail to it, finger it, look it up in bbdb, copy it to +;; the kill ring. For a word you may want to spell check it, copy it, +;; change its case, grep for it, etc. Mouse-me provides a menu to +;; make this easy. + +;; The menu popped up is generated by calling the function in the +;; variable `mouse-me-build-menu-function' which defaults to calling +;; `mouse-me-build-menu' which builds the menu from the variable +;; `mouse-me-menu-commands'. See the documentation for these +;; functions and variables for details. + +;; To install, add something like the following to your ~/.emacs: +;; (require 'mouseme) +;; (global-set-key [S-mouse-2] 'mouse-me) + +;;; Code: + +(require 'browse-url) +(require 'thingatpt) + +(eval-when-compile (require 'compile)) + +;;;; Variables + +(defgroup mouseme nil + "Popup menu of commands that work on strings." + :prefix "mouse-me-" + :group 'hypermedia) + +(defcustom mouse-me-get-string-function 'mouse-me-get-string + "Function used by `mouse-me' to get string when no region selected. +The default is `mouse-me-get-string' but this variable may commonly +be made buffer local and set to something more appropriate for +a specific mode (e.g., `word-at-point'). The function will be called +with no arguments and with point at where the mouse was clicked. +It can return either the string or to be most efficient, a list of +three elements: the string and the beginning and ending points of the +string in the buffer." + :type 'function + :options '(mouse-me-get-string)) + +(defcustom mouse-me-build-menu-function 'mouse-me-build-menu + "Function used by `mouse-me' to build the popup menu. +The default is `mouse-me-build-menu' but this variable may commonly +be made buffer local and set to something more appropriate for +a specific mode. The function will be called with one argument, +the string selected, as returned by `mouse-me-get-string-function'." + :type 'function + :options '(mouse-me-build-menu)) + +(defvar mouse-me-grep-use-extension 't + "If non-nil `mouse-me-grep' grep's in files with current file's extension.") + +(defcustom mouse-me-menu-commands + '(("Copy" . kill-new) + ("Kill" . kill-region) + ("Capitalize" . capitalize-region) + ("Lowercase" . downcase-region) + ("Uppercase" . upcase-region) + ("ISpell" . ispell-region) + "----" + ("Browse URL" . browse-url) + ("Dired" . dired) + ("Execute File" . mouse-me-execute) + ("Mail to" . compose-mail) + ("Finger" . mouse-me-finger) + ("BBDB Lookup" . mouse-me-bbdb) + "----" + ("Imenu" . imenu) + ("Find Tag" . find-tag) + ("Grep" . mouse-me-grep) + ("Find-Grep" . mouse-me-find-grep) + "----" + ("Apropos" . apropos) + ("Describe Function" . mouse-me-describe-function) + ("Describe Variable" . mouse-me-describe-variable) + ("Command Info" . mouse-me-emacs-command-info) + ("Man Page" . (if (fboundp 'woman) 'woman 'man)) + ("Profile Function" . mouse-me-elp-instrument-function)) + "Command menu used by `mouse-me-build-menu'. +A list of elements where each element is either a cons cell or a string. +If a cons cell the car is a string to be displayed in the menu and the +cdr is either a function to call passing a string to, or a list which evals +to a function to call passing a string to. If the element is a string +it makes a non-selectable element in the menu. To make a separator line +use a string consisting solely of hyphens. + +The function returned from this menu will be called with one string +argument. Or if the function has the symbol property `mouse-me-type' +and if its value is the symbol `region' it will be called with the +beginning and ending points of the selected string. If the value is +the symbol `string' it will be called with one string argument." + :type '(repeat sexp)) + +(put 'kill-region 'mouse-me-type 'region) +(put 'ispell-region 'mouse-me-type 'region) +(put 'capitalize-region 'mouse-me-type 'region) +(put 'downcase-region 'mouse-me-type 'region) +(put 'upcase-region 'mouse-me-type 'region) + +;;;; Commands + +;;;###autoload +(defun mouse-me (event) + "Popup a menu of functions to run on selected string or region." + (interactive "e") + (mouse-me-helper event (lambda (name) + (or (x-popup-menu event (funcall mouse-me-build-menu-function name)) + (error "No command to run"))))) + +;;;; Exposed Functions + +;; Some tests: +;; +;; +;; http://foo.bar.com/sss/ss.html +;; http://www.ditherdog.com/howard/ +;; mailto:howard@silverstream.com +;; howard@silverstream.com +;; +;; import com.sssw.srv.agents.AgentsRsrc; +;; public AgoHttpRequestEvent(Object o, String db, Request r) +;;
+;; d:\howard\elisp\spoon +;; \howard\elisp\spoon +;; \\absolut\howard\elisp\spoon +;; //absolut/d/Howard/Specs/servlet-2.1.pdf +;; \\absolut\d\Howard\Specs\servlet-2.1.pdf +;; gnuserv-frame. + +(defun mouse-me-get-string () + "Return a string from the buffer of text surrounding point. +Returns a list of three elements, the string and the beginning and +ending positions of the string in the buffer in that order." + (save-match-data + (save-excursion + (let ((start (point)) beg end str) + (skip-syntax-forward "^ >()\"") + (setq end (point)) + (goto-char start) + (skip-syntax-backward "^ >()\"") + (setq beg (point)) + (setq str (buffer-substring-no-properties beg end)) + ;; remove junk from the beginning + (if (string-match "^\\([][\"'`.,?:;!@#$%^&*()_+={}|<>-]+\\)" str) + (setq str (substring str (match-end 1)) + beg (+ beg (match-end 1)))) + ;; remove URL: from the front, it's common in email + (if (string-match "^\\(URL:\\)" str) + (setq str (substring str (match-end 1)) + beg (+ beg (match-end 1)))) + ;; remove junk from the end + (if (string-match "\\([][\"'.,?:;!@#$%^&*()_+={}|<>-]+\\)$" str) + (setq end (- end (length (match-string 1 str))) ; must set end first + str (substring str 0 (match-beginning 1)))) + (list str beg end))))) + +(defun mouse-me-build-menu (name) + "Return a menu tailored for NAME for `mouse-me' from `mouse-me-menu-commands'." + (list "Mouse Me" (cons "Mouse Me" + (append (list (cons + (if (< (length name) 65) + name + "...Long String...") + 'kill-new) + "---") + mouse-me-menu-commands)))) + +;;;; Commands for the menu + +(defun mouse-me-emacs-command-info (string) + "Look in Emacs info for command named STRING." + (interactive "sCommand: ") + (let ((s (intern-soft string))) + (if (and s (commandp s)) + (Info-goto-emacs-command-node s) + (error "No command named `%s'" string)))) + +(defun mouse-me-describe-function (string) + "Describe function named STRING." + (interactive "sFunction: ") + (let ((s (intern-soft string))) + (if (and s (fboundp s)) + (describe-function s) + (error "No function named `%s'" string)))) + +(defun mouse-me-describe-variable (string) + "Desribe variable named STRING." + (interactive "sVariable: ") + (let ((s (intern-soft string))) + (if (and s (boundp s)) + (describe-variable s) + (error "No variable named `%s'" string)))) + +(defun mouse-me-elp-instrument-function (string) + "Instrument Lisp function named STRING." + (interactive "sFunction: ") + (let ((s (intern-soft string))) + (if (and s (fboundp s)) + (elp-instrument-function s) + (error "Must be the name of an existing Lisp function")))) + +(defun mouse-me-execute (string) + "Execute STRING as a filename." + (interactive "sFile: ") + (if (fboundp 'w32-shell-execute) + (w32-shell-execute "open" (convert-standard-filename string)) + (message "This function currently working only in W32."))) + + +(defun mouse-me-bbdb (string) + "Lookup STRING in bbdb." + (interactive "sBBDB Lookup: ") + (if (fboundp 'bbdb) + (bbdb string nil) + (error "BBDB not loaded"))) + +(defun mouse-me-finger (string) + "Finger a STRING mail address." + (interactive "sFinger: ") + (save-match-data + (if (string-match "\\(.*\\)@\\([-.a-zA-Z0-9]+\\)$" string) + (finger (match-string 1 string) (match-string 2 string)) + (error "Not in user@host form: %s" string)))) + +(defun mouse-me-grep (string) + "Grep for a STRING." + (interactive "sGrep: ") + (require 'compile) + (grep-compute-defaults) + (let ((ext (mouse-me-buffer-file-extension))) + (grep (concat grep-command string + (if mouse-me-grep-use-extension + (if ext + (concat " *" ext) + " *")))))) + +(defun mouse-me-find-grep (string) + "Grep for a STRING." + (interactive "sGrep: ") + (grep-compute-defaults) + (let ((reg grep-find-command) + (ext (mouse-me-buffer-file-extension))) + (if (string-match "\\(^.+-type f \\)\\(.+$\\)" reg) + (setq reg (concat (match-string 1 reg) + (if mouse-me-grep-use-extension + (concat "-name \"*" ext "\" ")) + (match-string 2 reg)))) + (grep-find (concat reg string)))) + +;;;; Internal Functions + +(defun mouse-me-buffer-file-extension () + "Return the extension of the current buffer's filename or nil. +Returned extension is a string beginning with a period." + (let* ((bfn (buffer-file-name)) + (filename (and bfn (file-name-sans-versions bfn))) + (index (and filename (string-match "\\.[^.]*$" filename)))) + (if index + (substring filename index) + ""))) + +(defun mouse-me-helper (event func) + "Determine the string to use to process EVENT and call FUNC to get cmd." + (let (name sp sm mouse beg end cmd mmtype) + ;; temporarily goto where the event occurred, get the name clicked + ;; on and enough info to figure out what to do with it + (save-match-data + (save-excursion + (setq sp (point)) ; saved point + (setq sm (mark t)) ; saved mark + (set-buffer (window-buffer (posn-window (event-start event)))) + (setq mouse (goto-char (posn-point (event-start event)))) + ;; if there is a region and point is inside it + ;; check for sm first incase (null (mark t)) + ;; set name to either the thing they clicked on or region + (if (and sm + (or (and transient-mark-mode mark-active) + (eq last-command 'mouse-drag-region)) + (>= mouse (setq beg (min sp sm))) + (<= mouse (setq end (max sp sm)))) + (setq name (buffer-substring beg end)) + (setq name (funcall mouse-me-get-string-function)) + (if (listp name) + (setq beg (nth 1 name) + end (nth 2 name) + name (car name)) + (goto-char mouse) + (while (not (looking-at (regexp-quote name))) + (backward-char 1)) + (setq beg (point)) + (setq end (search-forward name)))))) + ;; check if name is null, meaning they clicked on no word + (if (or (null name) + (and (stringp name) (string= name "" ))) + (error "No string to pass to function")) + ;; popup a menu to get a command to run + (setq cmd (funcall func)) + ;; run the command, eval'ing if it was a list + (if (listp cmd) + (setq cmd (eval cmd t))) + (setq mmtype (get cmd 'mouse-me-type)) + (cond ((eq mmtype 'region) + (funcall cmd beg end)) + ((eq mmtype 'string) + (funcall cmd name)) + (t + (funcall cmd name))))) + +(provide 'mouseme) + +;;; mouseme.el ends here diff --git a/elpa/ess-20230419.1527/obsolete/msdos.el b/elpa/ess-20230419.1527/obsolete/msdos.el new file mode 100644 index 00000000..f3e1d9a8 --- /dev/null +++ b/elpa/ess-20230419.1527/obsolete/msdos.el @@ -0,0 +1,163 @@ +;;; msdos.el --- Run an MS-DOS shell in an NTemacs buffer with bash as the shell -*- lexical-binding: t; -*- + +;; Copyright (C) 1999-2022 Free Software Foundation, Inc. +;; Author: Richard M. Heiberger +;; Created: February 1999 +;; Maintainer: ESS-core + +;; This file is part of GNU Emacs. + +;;; License: +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; + +;;; Commentary: + +;; The file msdos.el in the next mail message opens an *msdos* buffer +;; in shell-mode and msdos-minor-mode. When cmdproxy.exe/command.com +;; is the Emacs shell, then this gets various setting right that M-x +;; shell currently misses. The function M-x msdos-minor-mode could be +;; automatically run by Emacs in shell-mode in that case. + +;; When bash is the Emacs shell, msdos.el still opens a +;; cmdproxy.exe/command.com shell in the buffer *msdos*. There are +;; occasions when it is necessary to run DOS character-based programs +;; in an Emacs window. + +;; I followed the suggestion by AndrewI to look at M-x shell and modify +;; it. It turns out not to have been trivial. + +;;; Code: + +(require 'shell); and hence 'comint + +;;; Customization and Buffer Variables + +(defcustom explicit-msdos-shell-file-name "cmdproxy.exe" + "*If non-nil, is file name to use for explicitly requested msdos +inferior shell." + :type '(choice (const :tag "None" nil) file) + :group 'shell) + +(defcustom explicit-msdos-comspec-file-name + (if (w32-using-nt) + "cmd.exe" + "command.com") + "*If non-nil, is file name to use for explicitly requested COMSPEC +environment variable." + :type '(choice (const :tag "None" nil) file) + :group 'shell) + +(defvar-local msdos-minor-mode nil + "Non-nil if using msdos-minor mode as a minor mode of some other mode.") + +(defun msdos () + "Run an inferior msdos shell, with I/O through buffer *msdos*. +This function is intended to be used in an Ntemacs session in which +bash is the primary shell. But sometimes an MSDOS window, within emacs, +is also needed. + +If buffer exists but shell process is not running, make new shell. +If buffer exists and shell process is running, just switch to buffer `*msdos*'. +Program used comes from variable `explicit-msdos-shell-file-name'. +If a file `~/.emacs_SHELLNAME' exists, it is given as initial input + (Note that this may lose due to a timing error if the shell + discards input when it starts up.) +The buffer is put in Shell mode, giving commands for sending input +and controlling the subjobs of the shell. See `shell-mode'. +See also the variable `shell-prompt-pattern'. + +The buffer is put into \\[msdos-minor-mode]. See `msdos-minor-mode'. + +The COMSPEC environment variable in the inferior shell, but not in the emacs +process, is set to `explicit-msdos-comspec-file-name'. +The SHELL environment variable in the inferior shell, but not in the emacs +process, is set to `explicit-msdos-shell-file-name'. + +The shell file name (sans directories) is used to make a symbol name +such as `explicit-csh-args'. If that symbol is a variable, +its value is used as a list of arguments when invoking the shell. + +\(Type \\[describe-mode] in the shell buffer for a list of commands.)" + (interactive) + (if (not (comint-check-proc "*msdos*")) + (let* ((prog explicit-msdos-shell-file-name) + (name (file-name-nondirectory prog)) + (startfile (concat "~/.emacs_" name)) + (xargs-name (intern-soft (concat "explicit-" name "-args"))) + shell-buffer + (comspec (getenv "COMSPEC")) + (shell (getenv "SHELL")) + ) + (save-excursion + (setenv "COMSPEC" explicit-msdos-comspec-file-name) + (setenv "SHELL" explicit-msdos-shell-file-name) + (set-buffer (apply #'make-comint "msdos" prog + (if (and xargs-name (boundp xargs-name)) + (symbol-value xargs-name)) + (if (file-exists-p startfile) + (concat "/k " startfile)))) + (setenv "COMSPEC" comspec) + (setenv "SHELL" shell) + (setq shell-buffer (current-buffer)) + (shell-mode) + (msdos-minor-mode) + (sleep-for 4) ; need to wait, else working too fast! + ;;; The `exit' warning should precede the "c:\" prompt. + ;;; If not, then increase the sleep-for time! + (goto-char (point-min)) + (insert + "Remember to exit this buffer with `exit'. If you kill the +buffer without exiting, you may not be able to shut down Windows cleanly.") + (goto-char (point-max))) + (pop-to-buffer shell-buffer)) + (pop-to-buffer "*msdos*"))) + + +(defun msdos-minor-mode () + "Minor mode for running msdos in a shell-mode buffer: +a. Uses \\[set-buffer-process-coding-system] to set the coding system +to `'raw-text-dos'. The DOS C-m C-l end-of-line is critical. The +shell freezes without it. + +b. The variable `comint-completion-addsuffix' is set to `\\' for directories. + +c. Prevents echoing of commands. + +d. strips ctrl-m from output. +" + (interactive) + (setq msdos-minor-mode t) + (set (make-local-variable 'comint-completion-addsuffix) '("\\" . " ")) + (setq comint-process-echoes t) + (add-hook 'comint-output-filter-functions #'shell-strip-ctrl-m nil t) + (set-process-coding-system (get-buffer-process (current-buffer)) 'raw-text-dos 'raw-text-dos) + ;; buffer-process-coding-system is critical. + ) + +;; Install ourselves: + + +(put 'msdos-minor-mode 'permanent-local t) +(or (assq 'msdos-minor-mode minor-mode-alist) + (setq minor-mode-alist + (append minor-mode-alist + (list '(msdos-minor-mode " msdos"))))) + +;; Provide ourselves: + +(provide 'msdos) + +;;; msdos.el ends here