--- /dev/null
+;;; 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)))
--- /dev/null
+This is allnews.info, produced by makeinfo version 6.5 from
+allnews.texi.
+
+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" <ess-config-here>)' 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 invokations
+ 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 commond 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 insterting 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 initialisation 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 recognised when
+ they are function definitions or function calls.
+ * ESS[R]: Backquoted names and '%op%' operators are recognised 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 '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 <https://github.com/emacs-ess/ESS/pull/65>
+ * 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;
+ <https://ess.r-project.org/Manual/ess.html>
+ * 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.VehtariNOSPAMhut.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:brendanNOSPAMessex.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:brahmNOSPAMalum.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.
+
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+This is announc.info, produced by makeinfo version 6.5 from
+announc.texi.
+
+\1f
+File: announc.info, Node: Announce
+
+1 ANNOUNCING ESS
+****************
+
+The ESS Developers proudly announce the release of ESS 18.10.2
+
+ 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 and XEmacs text editors
+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::
+
+\1f
+File: announc.info, Node: Latest Version, Next: Current Features, Prev: Announce, Up: Announce
+
+1.1 Getting the Latest Version
+==============================
+
+ESS supports GNU Emacs versions 24.3 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::
+
+\1f
+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.
+
+\1f
+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: <https://github.com/emacs-ess/ESS>. '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.
+
+\1f
+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.
+
+\1f
+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'.
+
+\1f
+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
+
+\1f
+File: announc.info, Node: Requirements, Next: Mailing List, Prev: Current Features, Up: Announce
+
+1.7 Requirements
+================
+
+ESS supports GNU Emacs versions 24.3 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.
+
+\1f
+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 <ess-help-requestNOSPAMr-project.org>; contributions
+to the list may be mailed to <ess-helpNOSPAMr-project.org>. 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 on Emacs and XEmacs.
+ * suggestions for improvements.
+ * announcements of new releases of ESS.
+ * posting small patches to ESS.
+
+\1f
+File: announc.info, Node: Reporting Bugs, Next: Authors, Prev: Mailing List, Up: Announce
+
+1.9 Reporting Bugs
+==================
+
+Please send bug reports, suggestions etc. to <ESS-bugsNOSPAMr-project.org>,
+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.
+
+\1f
+File: announc.info, Node: Authors, Next: License, Prev: Reporting Bugs, Up: Announce
+
+1.10 Authors
+============
+
+ * A.J. Rossini (mailto:blindglobeNOSPAMgmail.com)
+ * Richard M. Heiberger (mailto:rmhNOSPAMtemple.edu)
+ * Kurt Hornik (mailto:Kurt.HornikNOSPAMR-project.org)
+ * Martin Maechler (mailto:maechlerNOSPAMstat.math.ethz.ch)
+ * Rodney A. Sparapani (mailto:rsparapaNOSPAMmcw.edu)
+ * Stephen Eglen (mailto:stephenNOSPAMgnu.org)
+ * Sebastian P. Luque (mailto:spluqueNOSPAMgmail.com)
+ * Henning Redestig (mailto:henning.redNOSPAMgooglemail.com)
+ * Vitalie Spinu (mailto:spinuvitNOSPAMgmail.com)
+ * Lionel Henry (mailto:lionel.hryNOSPAMgmail.com)
+ * J. Alexander Branham (mailto:alex.branhamNOSPAMgmail.com)
+
+\1f
+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.
+
+\1f
+File: announc.info, Node: New Features, Prev: License, Up: Announce
+
+1.12 New Features
+=================
+
+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" <ess-config-here>)' 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 invokations
+ 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 commond 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 insterting 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 initialisation 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 recognised when
+ they are function definitions or function calls.
+ * ESS[R]: Backquoted names and '%op%' operators are recognised 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
+
+
+\1f
+Tag Table:
+Node: Announce\7f75
+Node: Latest Version\7f1303
+Node: Installing from a third-party repository\7f2246
+Node: Installing from source\7f3197
+Node: Activating and Loading ESS\7f4793
+Node: Check Installation\7f5871
+Node: Current Features\7f6095
+Node: Requirements\7f7638
+Node: Mailing List\7f8073
+Node: Reporting Bugs\7f8799
+Node: Authors\7f9679
+Node: License\7f10363
+Node: New Features\7f11013
+\1f
+End Tag Table
--- /dev/null
+This is authors.info, produced by makeinfo version 6.5 from
+authors.texi.
+
+ * A.J. Rossini (mailto:blindglobeNOSPAMgmail.com)
+ * Richard M. Heiberger (mailto:rmhNOSPAMtemple.edu)
+ * Kurt Hornik (mailto:Kurt.HornikNOSPAMR-project.org)
+ * Martin Maechler (mailto:maechlerNOSPAMstat.math.ethz.ch)
+ * Rodney A. Sparapani (mailto:rsparapaNOSPAMmcw.edu)
+ * Stephen Eglen (mailto:stephenNOSPAMgnu.org)
+ * Sebastian P. Luque (mailto:spluqueNOSPAMgmail.com)
+ * Henning Redestig (mailto:henning.redNOSPAMgooglemail.com)
+ * Vitalie Spinu (mailto:spinuvitNOSPAMgmail.com)
+ * Lionel Henry (mailto:lionel.hryNOSPAMgmail.com)
+ * J. Alexander Branham (mailto:alex.branhamNOSPAMgmail.com)
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+This is bugrept.info, produced by makeinfo version 6.5 from
+bugrept.texi.
+
+Please send bug reports, suggestions etc. to <ESS-bugsNOSPAMr-project.org>,
+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.
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+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:blindglobeNOSPAMgmail.com)
+ * Richard M. Heiberger (mailto:rmhNOSPAMtemple.edu)
+ * Kurt Hornik (mailto:Kurt.HornikNOSPAMR-project.org)
+ * Martin Maechler (mailto:maechlerNOSPAMstat.math.ethz.ch)
+ * Rodney A. Sparapani (mailto:rsparapaNOSPAMmcw.edu)
+ * Stephen Eglen (mailto:stephenNOSPAMgnu.org)
+ * Sebastian P. Luque (mailto:spluqueNOSPAMgmail.com)
+ * Henning Redestig (mailto:henning.redNOSPAMgooglemail.com)
+ * Vitalie Spinu (mailto:spinuvitNOSPAMgmail.com)
+ * Lionel Henry (mailto:lionel.hryNOSPAMgmail.com)
+ * J. Alexander Branham (mailto:alex.branhamNOSPAMgmail.com)
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+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
+
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+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.
+\1f
+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<Return>" 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).
--- /dev/null
+;;; ess-arc-d.el --- ARC customization
+
+;; Copyright (C) 2000 A. J. Rossini
+;; Copyright (C) 2001--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Created: 30 Jun 2000
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 extends the XLispStat configuration for ARC, the extension of the
+;; R-Code.
+
+;;; Code:
+
+(require 'ess-lsp-l)
+(require 'ess-inf)
+(declare-function ess-write-to-dribble-buffer "ess-utils")
+(defvar ess-customize-alist)
+(defvar ess-dialect)
+
+(defvar ARC-customize-alist
+ '((ess-customize-alist . ARC-customize-alist )
+ (ess-language . "XLS" )
+ (ess-dialect . "ARC" )
+ (ess-object-name-db-file . "ess-xls-namedb.el" )
+ (ess-help-sec-regex . " ")
+ (ess-help-sec-keys-alist . " ")
+ (inferior-ess-primary-prompt . "> ?" )
+ (comint-use-prompt-regexp . t)
+ (inferior-ess-program . inferior-ARC-program)
+ (inferior-ess-help-command . "(help '%s)\n" )
+ (inferior-ess-objects-command . "(variables)\n" )
+ (inferior-ess-exit-command . "(exit)\n" )
+ ;;(inferior-ess-start-args . nil)
+ (inferior-ess-start-file . nil)) ; "~/.ess-ARC")
+
+ "Variables to customize for ARC, a dialect of XLS.")
+
+
+(defun ARC-mode (&optional proc-name)
+ "Major mode for editing ARC source. NOT EVEN STARTED."
+ (interactive)
+ (setq ess-customize-alist ARC-customize-alist)
+ (lisp-mode))
+
+
+(defun ARC ()
+ "Call 'ARC', the extend XLispStat statistical system, from Forrest Young."
+
+ (interactive)
+ (setq ess-customize-alist ARC-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "(ARC): ess-dialect=%s , buf=%s\n"
+ ess-dialect (current-buffer)))
+ (inferior-ess))
+
+(fset 'arc 'ARC)
+
+\f ; Provide package
+
+(provide 'ess-arc-d)
+
+;;; ess-arc-d.el ends here
--- /dev/null
+;;; ess-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "ess" "ess.el" (0 0 0 0))
+;;; Generated autoloads from ess.el
+
+(autoload 'ess-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}
+
+Extra binding to note: 'ESC C-\\' indent-region.
+
+Entry to this mode runs the hooks in ess-mode-hook.
+
+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-beginning-of-function' and `ess-end-of-function' move the point to
+ the beginning and end of the current ESS function.
+ `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-tab-always-indent'
+ Non-nil means TAB in ESS mode should always reindent the current line,
+ regardless of where in the line point is when the TAB command is used.
+ `ess-auto-newline'
+ Non-nil means automatically newline before and after braces inserted in S
+ code.
+ `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. At present, predefined style are `BSD', `GNU', `K&R', `C++',
+`CLB' (quoted from C language style).
+
+\(fn &optional ALIST PROC-NAME IS-DERIVED)" nil nil)
+
+(autoload 'ess-dump-object-into-edit-buffer "ess" "\
+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.
+
+\(fn OBJECT)" t nil)
+
+(autoload 'ess-version "ess" "\
+Return a string with ESS version information.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-arc-d" "ess-arc-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-arc-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-arc-d" '("ARC")))
+
+;;;***
+\f
+;;;### (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" "\
+ESS[BUGS]: 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))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-bugs-d" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-bugs-l" "ess-bugs-l.el" (0 0 0 0))
+;;; Generated autoloads from ess-bugs-l.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-bugs-l" '("ess-bugs-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-custom" "ess-custom.el" (0 0 0 0))
+;;; Generated autoloads from ess-custom.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-custom" '("ess-" "inferior-" "comint-highlight-prompt" "SAS-mode-hook" "S+" "S-" "Rnw-mode-hook" "R-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-dde" "ess-dde.el" (0 0 0 0))
+;;; Generated autoloads from ess-dde.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-dde" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-font-lock" "ess-font-lock.el" (0 0 0 0))
+;;; Generated autoloads from ess-font-lock.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-font-lock" '("ess-font-lock-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-generics" "ess-generics.el" (0 0 0 0))
+;;; Generated autoloads from ess-generics.el
+
+(autoload 'ess-defgeneric "ess-generics" "\
+Define a new function, as with `defun', which can be overloaded.
+NAME is the name of the function to create. ARGS are the
+arguments to the function. DOCSTRING is a documentation string to
+describe the function. The docstring will automatically have
+details about its overload symbol appended to the end. BODY is
+code that would be run when there is no override defined. The
+default is to signal error if {name}-function is not defined.
+
+\(fn NAME ARGS DOCSTRING &rest BODY)" nil t)
+
+(function-put 'ess-defgeneric 'doc-string-elt '3)
+
+(function-put 'ess-defgeneric 'lisp-indent-function 'defun)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-generics" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-gretl" "ess-gretl.el" (0 0 0 0))
+;;; Generated autoloads from ess-gretl.el
+
+(autoload 'gretl-mode "ess-gretl" "\
+Major mode for editing gretl source. See `ess-mode' for more help.
+
+\(fn &optional PROC-NAME)" 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)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-gretl" '("ess-gretl-post-run-hook" "inferior-gretl-args" "gretl-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-help" "ess-help.el" (0 0 0 0))
+;;; Generated autoloads from ess-help.el
+
+(autoload 'ess-display-help-on-object "ess-help" "\
+Display documentation for OBJECT in another window.
+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
+suplied, it is used instead of `inferior-ess-help-command'.
+
+\(fn OBJECT &optional COMMAND)" t nil)
+
+(defalias 'ess-help 'ess-display-help-on-object)
+
+(autoload 'ess-helpobjs-at-point "ess-help" "\
+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.
+
+\(fn SLIST)" nil nil)
+
+(autoload 'ess-goto-info "ess-help" "\
+Display node NODE from `ess-mode' info.
+
+\(fn NODE)" nil nil)
+
+(autoload 'ess-submit-bug-report "ess-help" "\
+Submit a bug report to the ESS maintainers.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-help" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-inf" "ess-inf.el" (0 0 0 0))
+;;; Generated autoloads from ess-inf.el
+
+(autoload 'ess-proc-name "ess-inf" "\
+Return name of process N, as a string, with NAME prepended.
+If `ess-plain-first-buffername', then initial process is number-free.
+
+\(fn N NAME)" nil nil)
+
+(autoload 'inferior-ess "ess-inf" "\
+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
+ESS-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'.
+An initialization file (dumped into the process) is specified by
+`inferior-ess-start-file', and `inferior-ess-start-args' is used
+to accompany the call for `inferior-ess-program'.
+
+When creating a new process, the process buffer replaces the
+current window if `inferior-ess-same-window' is non-nil.
+Alternatively, it can appear in its own frame if
+`inferior-ess-own-frame' is non-nil.
+
+\(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.
+
+\(fn &optional ESS-START-ARGS CUSTOMIZE-ALIST NO-WAIT)" t nil)
+
+(ess-defgeneric ess-load-file (&optional filename) "Load a source file into an inferior ESS process.\nThis handles Tramp when working on a remote." (interactive (list (or (and (memq major-mode '(ess-mode ess-julia-mode)) (buffer-file-name)) (expand-file-name (read-file-name "Load source file: " nil nil t))))) (ess-load-file--normalise-buffer filename) (save-selected-window (ess-switch-to-ESS t)) (:override (let ((file (ess-load-file--normalise-file filename))) (let ((command (ess-build-load-command file nil t))) (ess-send-string (ess-get-process) command t)))))
+
+(autoload 'inferior-ess-mode "ess-inf" "\
+Major mode for interacting with an inferior ESS process.
+Runs an S interactive job as a subprocess of Emacs, with I/O through an
+Emacs buffer. Variable `inferior-ess-program' controls which S
+is run.
+
+Commands are sent to the ESS process by typing them, and pressing
+\\[inferior-ess-send-input]. Pressing \\[complete-dynamic-complete]
+completes known object names or filenames, as appropriate. Other
+keybindings for this mode are:
+
+\\{inferior-ess-mode-map}
+
+When editing S objects, the use of \\[ess-load-file] is advocated.
+`ess-load-file' keeps source files (if `ess-keep-dump-files' is non-nil) in
+the directory specified by `ess-source-directory', with the
+filename chosen according to `ess-dump-filename-template'. When a file is
+loaded, `ess-mode' parses error messages and jumps to the appropriate file
+if errors occur. The ess-eval- commands do not do this.
+
+Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
+`inferior-ess-mode-hook' (in that order).
+
+You can send text to the inferior ESS process from other buffers
+containing source code. The key bindings of these commands can be
+found by typing \\[describe-mode].
+
+ `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-beginning-of-function' and `ess-end-of-function' move the point to
+ the beginning and end of the current S function.
+ `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-dump-object-into-edit-buffer' moves an S object into a temporary file
+ and buffer for editing
+ `ess-load-file' sources a file of commands to the ESS process.
+
+Commands:
+Return after the end of the process' output sends the text from the
+ end of process to point.
+Return before the end of the process' output copies the sexp ending at point
+ to the end of the process' output, and sends it.
+Delete converts tabs to spaces as it moves back.
+C-M-q does Tab on each line starting within following expression.
+Paragraphs are separated only by blank lines. Crosshatches start comments.
+If you accidentally suspend your process, use \\[comint-continue-subjob]
+to continue it.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-inf" '("ess-" "inferior-ess-" "update-ess-process-name-list" "with-ess-process-buffer")))
+
+;;;***
+\f
+;;;### (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" "\
+ESS[JAGS]: Major mode for JAGS.
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.[Jj][Aa][Gg]\\'" . ess-jags-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-jags-d" '("ess-jags-")))
+
+;;;***
+\f
+;;;### (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 editing julia source. See `ess-mode' for more help.
+
+\(fn)" t nil)
+
+(autoload 'julia "ess-julia" "\
+Call 'julia'.
+Optional prefix (C-u) allows to set command line arguments, such as
+--load=<file>. 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)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-julia" '("ess-" "company-ess-julia-objects" "ac-source-ess-julia-objects" "inferior-julia-args")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-lsp-l" "ess-lsp-l.el" (0 0 0 0))
+;;; Generated autoloads from ess-lsp-l.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-lsp-l" '("Lisp-editing-alist")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-mouse" "ess-mouse.el" (0 0 0 0))
+;;; Generated autoloads from ess-mouse.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-mouse" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-noweb" "ess-noweb.el" (0 0 0 0))
+;;; Generated autoloads from ess-noweb.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-noweb" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-noweb-font-lock-mode" "ess-noweb-font-lock-mode.el"
+;;;;;; (0 0 0 0))
+;;; Generated autoloads from ess-noweb-font-lock-mode.el
+
+(autoload 'ess-noweb-font-lock-mode "ess-noweb-font-lock-mode" "\
+Minor mode for syntax highlighting when using `ess-noweb-mode' to edit noweb files.
+Each chunk is fontified in accordance with its own mode.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-noweb-font-lock-mode" '("ess-noweb-" "nwfl-donowt")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-noweb-mode" "ess-noweb-mode.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from ess-noweb-mode.el
+
+(autoload 'ess-noweb-mode "ess-noweb-mode" "\
+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] goto the next chunk
+\\[ess-noweb-previous-chunk] goto the previous chunk
+\\[ess-noweb-goto-previous] goto the previous chunk of the same name
+\\[ess-noweb-goto-next] goto the next chunk of the same name
+\\[ess-noweb-goto-chunk] goto a chunk
+\\[ess-noweb-next-code-chunk] goto the next code chunk
+\\[ess-noweb-previous-code-chunk] goto the previous code chunk
+\\[ess-noweb-next-doc-chunk] goto the next documentation chunk
+\\[ess-noweb-previous-doc-chunk] goto the previous documentation chunk
+
+Copying/Killing/Marking/Narrowing:
+\\[ess-noweb-copy-chunk-as-kill] copy the chunk the point is in into the kill ring
+\\[ess-noweb-copy-chunk-pair-as-kill] copy the pair of doc/code chunks the point is in
+\\[ess-noweb-kill-chunk] kill the chunk the point is in
+\\[ess-noweb-kill-chunk-pair] kill the pair of doc/code chunks the point is in
+\\[ess-noweb-mark-chunk] mark the chunk the point is in
+\\[ess-noweb-mark-chunk-pair] mark the pair of doc/code chunks the point is in
+\\[ess-noweb-narrow-to-chunk] narrow to the chunk the point is in
+\\[ess-noweb-narrow-to-chunk-pair] narrow to the pair of doc/code chunks the point is in
+\\[widen] widen
+\\[ess-noweb-toggle-narrowing] toggle auto narrowing
+
+Filling and Indenting:
+\\[ess-noweb-fill-chunk] fill (or indent) the chunk at point according to mode
+\\[ess-noweb-fill-paragraph-chunk] fill the paragraph at point, restricted to chunk
+\\[ess-noweb-indent-line] indent the line at point according to mode
+
+Insertion:
+\\[ess-noweb-insert-default-mode-line] insert a line to set this file's code mode
+\\[ess-noweb-new-chunk] insert a new chunk at point
+\\[ess-noweb-complete-chunk] complete the chunk name before point
+\\[ess-noweb-electric-@] insert a `@' or start a new doc chunk
+\\[ess-noweb-electric-<] insert a `<' or start a new code chunk
+
+Modes:
+\\[ess-noweb-set-doc-mode] set the major mode for editing doc chunks
+\\[ess-noweb-set-code-mode] set the major mode for editing code chunks
+\\[ess-noweb-set-this-code-mode] set the major mode for editing this code chunk
+
+Misc:
+\\[ess-noweb-occur] find all occurrences of the current chunk
+\\[ess-noweb-update-chunk-vector] update the markers for chunks
+\\[ess-noweb-describe-mode] describe ess-noweb-mode
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-noweb-mode" '("ess-noweb-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-omg-d" "ess-omg-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-omg-d.el
+
+(autoload 'OMG-mode "ess-omg-d" "\
+Major mode for editing Omegahat source. NOT EVEN STARTED.
+
+\(fn &optional PROC-NAME)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.omg\\'" . omegahat-mode))
+
+(add-to-list 'auto-mode-alist '("\\.hat\\'" . omegahat-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-omg-d" '("OMG")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-omg-l" "ess-omg-l.el" (0 0 0 0))
+;;; Generated autoloads from ess-omg-l.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-omg-l" '("ess-" "OMG-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-a" "ess-r-a.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-a.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-a" '("pd::set-up-demo" "ess")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-completion" "ess-r-completion.el" (0
+;;;;;; 0 0 0))
+;;; Generated autoloads from ess-r-completion.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-completion" '("ess-" "ac-source-R" "company-R-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-flymake" "ess-r-flymake.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-flymake.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-flymake" '("ess-r-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-gui" "ess-r-gui.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-gui.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-gui" '("Rgui" "ess-" "inferior-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-mode" "ess-r-mode.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-mode.el
+
+(defvar ess-dev-map (let (ess-dev-map) (define-prefix-command 'ess-dev-map) (define-key ess-dev-map "\13" '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 "\f" '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 "\17" 'ess-watch) (define-key ess-dev-map "w" 'ess-watch) (define-key ess-dev-map "\ 4" 'ess-debug-flag-for-debugging) (define-key ess-dev-map "d" 'ess-debug-flag-for-debugging) (define-key ess-dev-map "\15" 'ess-debug-unflag-for-debugging) (define-key ess-dev-map "u" 'ess-debug-unflag-for-debugging) (define-key ess-dev-map [(control 68)] 'ess-debug-unflag-for-debugging) (define-key ess-dev-map "\ 2" 'ess-bp-set) (define-key ess-dev-map "b" 'ess-bp-set) (define-key ess-dev-map [(control 66)] 'ess-bp-set-conditional) (define-key ess-dev-map "B" 'ess-bp-set-conditional) (define-key ess-dev-map "\f" 'ess-bp-set-logger) (define-key ess-dev-map "L" 'ess-bp-set-logger) (define-key ess-dev-map "\ f" 'ess-bp-toggle-state) (define-key ess-dev-map "o" 'ess-bp-toggle-state) (define-key ess-dev-map "\v" 'ess-bp-kill) (define-key ess-dev-map "k" 'ess-bp-kill) (define-key ess-dev-map "\v" 'ess-bp-kill-all) (define-key ess-dev-map "K" 'ess-bp-kill-all) (define-key ess-dev-map "\ e" '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 "\10" 'ess-bp-previous) (define-key ess-dev-map "p" 'ess-bp-previous) (define-key ess-dev-map "\ 5" dev-map "?" 'ess-tracebug-show-help) ess-dev-map) "\
+Keymap for commands related to development and debugging.")
+
+(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 'R-mode "ess-r-mode" "\
+Major mode for editing R source. See `ess-mode' for more help.
+
+\(fn &optional PROC-NAME)" t nil)
+
+(defalias 'r-mode #'R-mode)
+
+(defalias 'ess-r-mode #'R-mode)
+
+(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . R-mode))
+
+(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . R-mode))
+
+(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . R-mode))
+
+(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . R-mode))
+
+(add-to-list 'auto-mode-alist '("CITATION\\'" . R-mode))
+
+(autoload 'Rnw-mode "ess-r-mode" "\
+Major mode for editing Sweave(R) source.
+See `ess-noweb-mode' and `R-mode' for more help.
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.[rR]nw\\'" . Rnw-mode))
+
+(add-to-list 'auto-mode-alist '("\\.[sS]nw\\'" . Snw-mode))
+
+(autoload 'R-transcript-mode "ess-r-mode" "\
+Does the right thing.
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.[Rr]out" . R-transcript-mode))
+
+(add-to-list 'interpreter-mode-alist '("Rscript" . R-mode))
+
+(add-to-list 'interpreter-mode-alist '("r" . R-mode))
+
+(add-to-list 'auto-mode-alist '("/Makevars\\(\\.win\\)?$" . makefile-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-mode" '("ess-" "inferior-ess-r-" "R-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-package" "ess-r-package.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-package.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-package" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-syntax" "ess-r-syntax.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-syntax.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-syntax" '("ess-" "backward-ess-r-" "forward-ess-r-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-r-xref" "ess-r-xref.el" (0 0 0 0))
+;;; Generated autoloads from ess-r-xref.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-r-xref" '("ess-r-xref-")))
+
+;;;***
+\f
+;;;### (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.
+
+This mode makes it easier to write R documentation by helping with
+indentation, doing some of the typing for you (with Abbrev mode) and by
+showing keywords, strings, etc. in different faces (with Font Lock mode
+on terminals that support it).
+
+Type \\[list-abbrevs] to display the built-in abbrevs for Rd keywords.
+
+Keybindings
+===========
+
+\\{Rd-mode-map}
+
+Variables you can use to customize Rd mode
+==========================================
+
+`Rd-indent-level'
+ Indentation of Rd code with respect to containing blocks.
+ Default is 2.
+
+Turning on Rd mode runs the hook `Rd-mode-hook'.
+
+To automatically turn on the abbrev(iate) features, add the
+following lines to your `.emacs' file:
+
+ (add-hook 'Rd-mode-hook
+ (lambda ()
+ (abbrev-mode 1)))
+
+\(fn)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode))
+
+(autoload 'Rd-preview-help "ess-rd" "\
+Preview the current Rd buffer contents as help.
+If optional VIA-SHELL is set, using `Rd-to-help-command'.
+If the current buffer is not associated with a file, create a
+temporary one in `temporary-file-directory'.
+
+\(fn &optional VIA-SHELL)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-rd" '("Rd-" "ess")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-rdired" "ess-rdired.el" (0 0 0 0))
+;;; Generated autoloads from ess-rdired.el
+
+(autoload 'ess-rdired "ess-rdired" "\
+Run dired-like mode on R objects.
+This is the main function. See documentation for `ess-rdired-mode' though
+for more information!
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-rdired" '("ess-rdired-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-roxy" "ess-roxy.el" (0 0 0 0))
+;;; Generated autoloads from ess-roxy.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-roxy" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-rutils" "ess-rutils.el" (0 0 0 0))
+;;; Generated autoloads from ess-rutils.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-rutils" '("ess-rutils-")))
+
+;;;***
+\f
+;;;### (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))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-s-lang" '("ess-" "S+common-cust-alist" "S-" "inferior-S-language-start")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-s3-d" "ess-s3-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-s3-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-s3-d" 'nil))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-s4-d" "ess-s4-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-s4-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-s4-d" 'nil))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sas-a" "ess-sas-a.el" (0 0 0 0))
+;;; Generated autoloads from ess-sas-a.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sas-a" '("ess-" "sas-program")))
+
+;;;***
+\f
+;;;### (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 &optional PROC-NAME)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.[Ss][Aa][Ss]\\'" . SAS-mode))
+
+(autoload 'SAS-menu "ess-sas-d" "\
+Start SAS from the menu.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sas-d" '("ess-" "SAS" "inferior-SAS-args")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sas-l" "ess-sas-l.el" (0 0 0 0))
+;;; Generated autoloads from ess-sas-l.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sas-l" '("ess-" "set-sas-file-" "submit-sas" "switch-to-" "sas-" "beginning-of-sas-" "backward-page-top-of-window" "fix-page-breaks" "forward-page-top-of-window" "next-sas-proc" "indent-sas-statement" "SAS-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-site" "ess-site.el" (0 0 0 0))
+;;; Generated autoloads from ess-site.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-site" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sp3-d" "ess-sp3-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-sp3-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sp3-d" '("S+3")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sp4-d" "ess-sp4-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-sp4-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sp4-d" '("Sqpe+4" "S+4" "inferior-S+4-multipleinstances")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sp5-d" "ess-sp5-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-sp5-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sp5-d" '("S+5")))
+
+;;;***
+\f
+;;;### (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)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sp6-d" '("ess-" "S+")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-sp6w-d" "ess-sp6w-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-sp6w-d.el
+
+(add-to-list 'auto-mode-alist '("\\.sp\\'" . S-mode))
+
+(add-to-list 'auto-mode-alist '("\\.[qsS]\\'" . S-mode))
+
+(add-to-list 'auto-mode-alist '("\\.ssc\\'" . S-mode))
+
+(add-to-list 'auto-mode-alist '("\\.SSC\\'" . S-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-sp6w-d" '("S+" "Sqpe+" "ess-sqpe-versions-create" "inferior-S+")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-stata-lang" "ess-stata-lang.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from ess-stata-lang.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-stata-lang" '("ess-" "stata-" "STA-" "ado-set-font-lock-keywords")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-stata-mode" "ess-stata-mode.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from ess-stata-mode.el
+
+(autoload 'STA-mode "ess-stata-mode" "\
+Major mode for editing Stata source. See `ess-mode' for more help.
+
+\(fn &optional PROC-NAME)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.do\\'" . STA-mode))
+
+(add-to-list 'auto-mode-alist '("\\.ado\\'" . STA-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-stata-mode" '("stata" "ess-" "STA-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-swv" "ess-swv.el" (0 0 0 0))
+;;; Generated autoloads from ess-swv.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-swv" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-toolbar" "ess-toolbar.el" (0 0 0 0))
+;;; Generated autoloads from ess-toolbar.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-toolbar" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-tracebug" "ess-tracebug.el" (0 0 0 0))
+;;; Generated autoloads from ess-tracebug.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-tracebug" '("ess-" "org-" "inferior-ess-")))
+
+;;;***
+\f
+;;;### (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 manipulating {ESS} transcript files.
+
+Type \\[ess-transcript-send-command] to send a command in the
+transcript to the current S 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 S commands. Other keybindings are:
+
+\\{ess-transcript-mode-map}
+
+\(fn ALIST &optional PROC)" nil nil)
+
+(autoload 'ess-transcript-clean-region "ess-trns" "\
+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].
+
+\(fn BEG END EVEN-IF-READ-ONLY)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-trns" '("ess-transcript-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-utils" "ess-utils.el" (0 0 0 0))
+;;; Generated autoloads from ess-utils.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-utils" '("ess-")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-vst-d" "ess-vst-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-vst-d.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-vst-d" '("VST-" "ViSta")))
+
+;;;***
+\f
+;;;### (autoloads nil "ess-xls-d" "ess-xls-d.el" (0 0 0 0))
+;;; Generated autoloads from ess-xls-d.el
+
+(autoload 'XLS-mode "ess-xls-d" "\
+Major mode for editing XLispStat source. NOT EVEN STARTED.
+
+\(fn &optional PROC-NAME)" t nil)
+
+(add-to-list 'auto-mode-alist '("\\.lsp\\'" . XLS-mode))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ess-xls-d" '("xls-transcript-mode" "XLS" "ess-help-XLS-sec-keys-alist")))
+
+;;;***
+\f
+;;;### (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 process 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 execute `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)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "essd-els" '("ess-" "S+elsewhere" "inferior-ess-remote-pager")))
+
+;;;***
+\f
+;;;### (autoloads nil "make-regexp" "make-regexp.el" (0 0 0 0))
+;;; Generated autoloads from make-regexp.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "make-regexp" '("make-regexp" "regexp-span")))
+
+;;;***
+\f
+;;;### (autoloads nil "mouseme" "mouseme.el" (0 0 0 0))
+;;; Generated autoloads from mouseme.el
+
+(autoload 'mouse-me "mouseme" "\
+Popup a menu of functions to run on selected string or region.
+
+\(fn EVENT)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "mouseme" '("mouse-me-")))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("ess-mode.el" "ess-pkg.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; ess-autoloads.el ends here
--- /dev/null
+;;; ess-bugs-d.el --- ESS[BUGS] dialect
+
+;; Copyright (C) 2008-2011 Rodney Sparapani
+
+;; Author: Rodney Sparapani
+;; Created: 13 March 2008
+;; Maintainer: ESS-help <ess-helpNOSPAMr-project.org>
+
+;; 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-custom)
+(require 'ess-mode)
+
+(setq auto-mode-alist
+ (append '(("\\.[bB][uU][gG]\\'" . ess-bugs-mode)) auto-mode-alist))
+
+(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 "\\<d\\(bern\\|beta\\|bin\\|cat\\|chisq\\|"
+ "dexp\\|dirch\\|exp\\|\\(gen[.]\\)?gamma\\|hyper\\|"
+ "interval\\|lnorm\\|logis\\|mnorm\\|mt\\|multi\\|"
+ "negbin\\|norm\\(mix\\)?\\|par\\|pois\\|sum\\|t\\|"
+ "unif\\|weib\\|wish\\)[ \t\n]*(")
+ font-lock-constant-face)
+
+ (cons (concat "\\<\\(abs\\|cos\\|C\\|dim\\|\\(i\\)?cloglog\\|equals\\|"
+ "exp\\|for\\|inprod\\|interp[.]line\\|inverse\\|length\\|"
+ "\\(i\\)?logit\\|logdet\\|logfact\\|loggam\\|max\\|mean\\|"
+ "mexp\\|min\\|phi\\|pow\\|probit\\|prod\\|rank\\|round\\|"
+ "sd\\|sin\\|sort\\|sqrt\\|step\\|sum\\|t\\|trunc\\|T\\)[ \t\n]*(")
+ font-lock-function-name-face)
+
+ ;; .bmd files
+ (cons (concat (regexp-opt '(
+ "dicClear" "dicSet" "dicStats"
+ "infoMemory" "infoModules" "infoNodeMethods"
+ "infoNodeTypes" "infoNodeValues"
+ "infoUpdatersbyDepth" "infoUpdatersbyName"
+ "modelCheck" "modelCompile" "modelData"
+ "modelDisable" "modelEnable" "modelGenInits"
+ "modelInits" "modelPrecision" "modelQuit"
+ "modelSaveState" "modelSetAP" "modelSetIts"
+ "modelSetOR" "modelSetRN" "modelUpdate"
+ "ranksClear" "ranksSet" "ranksStats"
+ "samplesAutoC" "samplesBgr" "samplesCoda"
+ "samplesDensity" "samplesHistory" "samplesSet"
+ "sampleStats" "samplesThin"
+ "summaryClear" "summarySet" "summaryStats"
+ ) 'words) "(")
+ font-lock-function-name-face)
+
+ (cons (concat (regexp-opt '("Local Variables" "End") 'words) ":")
+ font-lock-keyword-face)
+ )
+ "ESS[BUGS]: Font lock keywords."
+ )
+
+(defun ess-bugs-switch-to-suffix (suffix &optional bugs-chains bugs-monitor bugs-thin
+ bugs-burnin bugs-update)
+ "ESS[BUGS]: Switch to file with suffix."
+ (find-file (concat ess-bugs-file-dir ess-bugs-file-root suffix))
+
+ (if (equal 0 (buffer-size)) (progn
+ (if (equal ".bug" suffix) (progn
+ ;(insert "var ;\n")
+ (insert "model {\n")
+ (insert " for (i in 1:N) {\n \n")
+ (insert " }\n")
+ (insert "}\n")
+ (insert "#Local Variables" ":\n")
+ ; (insert "#enable-local-variables: :all\n")
+ (insert "#ess-bugs-chains:1\n")
+ (insert "#ess-bugs-monitor:(\"\")\n")
+ (insert "#ess-bugs-thin:1\n")
+ (insert "#ess-bugs-burnin:10000\n")
+ (insert "#ess-bugs-update:10000\n")
+ (insert "#End:\n")
+ ))
+
+ (if (equal ".bmd" suffix) (let
+ ((ess-bugs-temp-chains "") (ess-bugs-temp-monitor "") (ess-bugs-temp-chain ""))
+
+ (if bugs-chains (setq ess-bugs-chains bugs-chains))
+ (if bugs-monitor (setq ess-bugs-monitor bugs-monitor))
+ (if bugs-thin (setq ess-bugs-thin bugs-thin))
+
+ (setq ess-bugs-temp-chains
+ (concat "modelCompile(" (format "%d" ess-bugs-chains) ")\n"))
+
+ (setq bugs-chains ess-bugs-chains)
+
+ (while (< 0 bugs-chains)
+ (setq ess-bugs-temp-chains
+ (concat ess-bugs-temp-chains
+ "modelInits('" ess-bugs-file-root
+ ".##" (format "%d" bugs-chains) "', "
+ (format "%d" bugs-chains) ")\n"))
+ (setq bugs-chains (- bugs-chains 1)))
+
+ (setq ess-bugs-temp-monitor "")
+
+ (while (and (listp ess-bugs-monitor) (consp ess-bugs-monitor))
+ (if (not (string-equal "" (car ess-bugs-monitor)))
+ (setq ess-bugs-temp-monitor
+ (concat ess-bugs-temp-monitor "samplesSet('"
+ (car ess-bugs-monitor)
+ ;", thin(" (format "%d" ess-bugs-thin)
+ "')\n")))
+ (setq ess-bugs-monitor (cdr ess-bugs-monitor)))
+
+ (insert "modelCheck('" ess-bugs-file-root ".bug')\n")
+ (insert "modelData('" ess-bugs-file-root ".bdt')\n")
+ (insert (ess-replace-in-string ess-bugs-temp-chains "##" "in"))
+ (insert "modelGenInits()\n")
+ (insert "modelUpdate(" (format "%d" bugs-burnin) ")\n")
+ ;(insert "modelUpdate(" (format "%d" (* bugs-thin bugs-burnin)) ")\n")
+ (insert ess-bugs-temp-monitor)
+ (insert "modelUpdate(" (format "%d" (* bugs-thin bugs-update)) ")\n")
+ ; (insert (ess-replace-in-string
+ ; (ess-replace-in-string ess-bugs-temp-chains
+ ; "modelCompile([0-9]+)" "#") "##" "to"))
+
+ (if (< 1 bugs-thin) (insert "samplesThin(" (format "%d" bugs-thin) ")\n"))
+
+ (insert "samplesCoda('*', '" ess-bugs-file-root "')\n")
+
+ ; (if ess-bugs-system (progn
+ ; (insert "system rm -f " ess-bugs-file-root ".ind\n")
+ ; (insert "system ln -s " ess-bugs-file-root "index.txt " ess-bugs-file-root ".ind\n")
+
+ ; (setq bugs-chains ess-bugs-chains)
+
+ ; (while (< 0 bugs-chains)
+ ; (setq ess-bugs-temp-chain (format "%d" bugs-chains))
+
+ ; ;.txt not recognized by BOA and impractical to over-ride
+ ; (insert "system rm -f " ess-bugs-file-root ess-bugs-temp-chain ".out\n")
+ ; (insert "system ln -s " ess-bugs-file-root "chain" ess-bugs-temp-chain ".txt "
+ ; ess-bugs-file-root ess-bugs-temp-chain ".out\n")
+ ; (setq bugs-chains (- bugs-chains 1)))))
+
+ (insert "modelQuit()\n")
+ (insert "Local Variables" ":\n")
+ ; (insert "enable-local-variables: :all\n")
+ (insert "ess-bugs-chains:" (format "%d" ess-bugs-chains) "\n")
+ (insert "ess-bugs-command:\"" ess-bugs-command "\"\n")
+ (insert "End:\n")
+ ))
+ ))
+ )
+
+(defun ess-bugs-na-bmd (bugs-command bugs-chains)
+ "ESS[BUGS]: Perform the Next-Action for .bmd."
+ ;(ess-save-and-set-local-variables)
+ (if (equal 0 (buffer-size)) (ess-bugs-switch-to-suffix ".bmd")
+ ;else
+ (shell)
+ (ess-sleep)
+
+ (when (and (when (fboundp 'w32-shell-dos-semantics)
+ (w32-shell-dos-semantics))
+ (string-equal ":" (substring ess-bugs-file 1 2)))
+ (insert (substring ess-bugs-file 0 2)))
+
+ (comint-send-input)
+ (insert "cd \"" ess-bugs-file-dir "\"")
+ (comint-send-input)
+
+ ; (let ((ess-bugs-temp-chains ""))
+ ;
+ ; (while (< 0 bugs-chains)
+ ; (setq ess-bugs-temp-chains
+ ; (concat (format "%d " bugs-chains) ess-bugs-temp-chains))
+ ; (setq bugs-chains (- bugs-chains 1)))
+
+ ;; (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 "' > " 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
+(defun ess-bugs-mode ()
+ "ESS[BUGS]: Major mode for BUGS."
+ (interactive)
+ (kill-all-local-variables)
+ (ess-setq-vars-local '((comment-start . "#")))
+ (setq major-mode 'ess-bugs-mode)
+ (setq mode-name "ESS[BUGS]")
+ (use-local-map ess-bugs-mode-map)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(ess-bugs-font-lock-keywords nil t))
+ (setq ess-language "S") ; mimic S for ess-smart-underscore
+ (run-mode-hooks 'ess-bugs-mode-hook)
+
+ (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))))))
+
+(setq features (delete 'ess-bugs-d features))
+(provide 'ess-bugs-d)
+
+;;; ess-bugs-d.el ends here
--- /dev/null
+;;; ess-bugs-l.el --- ESS[BUGS] languages
+
+;; Copyright (C) 2006-2011 Rodney Sparapani
+
+;; Author: Rodney Sparapani
+;; Created: 16 August 2006
+;; Maintainer: ESS-help <ess-helpNOSPAMr-project.org>
+
+;; 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 'font-lock)
+(require 'shell)
+(require 'comint)
+(require 'ess-utils)
+(require 'ess-custom)
+(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 ess-microsoft-p (if (w32-shell-dos-semantics) 'dos 'sh) '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 nil
+ "ESS[BUGS]: Keymap for mode.")
+
+(if ess-bugs-mode-map nil (setq ess-bugs-mode-map (make-keymap)))
+(define-key ess-bugs-mode-map (quote [f2]) 'ess-revert-wisely)
+ ;(define-key ess-bugs-mode-map (quote [f12]) 'ess-bugs-next-action)
+(define-key ess-bugs-mode-map "\C-c\C-c" 'ess-bugs-next-action)
+(define-key ess-bugs-mode-map "=" 'ess-bugs-hot-arrow)
+(define-key ess-bugs-mode-map "_" 'ess-bugs-hot-arrow)
+
+(defvar ess-bugs-syntax-table nil
+ "ESS[BUGS]: Syntax table for mode.")
+
+(if ess-bugs-syntax-table nil (setq ess-bugs-syntax-table (make-syntax-table)))
+(modify-syntax-entry ?\\ "." ess-bugs-syntax-table)
+(modify-syntax-entry ?# "<" ess-bugs-syntax-table)
+(modify-syntax-entry ?\n ">" ess-bugs-syntax-table)
+(modify-syntax-entry ?\( "()" ess-bugs-syntax-table)
+ (modify-syntax-entry ?\) ")(" ess-bugs-syntax-table)
+(modify-syntax-entry ?. "w" ess-bugs-syntax-table)
+
+(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 (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)
+ (switch-to-buffer (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
--- /dev/null
+;;; ess-custom.el --- Customize variables for ESS
+
+;; 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 <blindglobeNOSPAMgmail.com>
+;; Created: 05 June 2000
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 'comint)
+(require 'custom)
+(require 'executable)
+(require 'font-lock)
+
+;; 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 coments/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-origS nil
+ "ESS: Original S Dialect from Bell Labs/AT&T."
+ :group 'ess-S
+ :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-XLS nil
+ "ESS: XLispStat."
+ :group 'ess
+ :prefix "ess-")
+
+(defgroup ess-OMG nil
+ "ESS: Omegahat."
+ :group 'ess
+ :prefix "ess-")
+
+(defgroup ess-mouse nil ;; FIXME: this is not used yet <--> ./ess-mous.el
+ "ESS: Mouse."
+ :group 'ess
+ :prefix "ess-")
+
+(defgroup ess-roxy nil
+ "Mode for editing in-code Roxygen documentation."
+ :group 'ess
+ :group 'convenience
+ :group 'ess-extras
+ :prefix "ess-" ;; << -- added for ESS integration FIXME??
+ :group 'tools)
+
+(defgroup ess-sweave nil
+ "Mode for editing Sweave (*.[SR]nw) files."
+ :group 'ess-S
+ :prefix "ess-")
+
+(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
+ :prefix "ess-")
+
+;; Variables (not user-changeable)
+
+(defvar ess-version "18.10.2" ;; updated by 'make'
+ "Version of ESS currently loaded.")
+
+(defvar ess-revision nil ;; set
+ "The subversion revision and date of ESS.
+Is set by \\[ess-version-string].")
+
+
+\f ; User changeable variables
+
+;;*;; Options and Initialization
+
+;; 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)
+
+(defvar ess-imenu-generic-expression nil
+ "Placeholder for imenu-generic-expression. Dialect specific.")
+
+(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 available for call by
+`ess-handy-commands' and `ess-smart-comma' function."
+ :group 'ess
+ :type 'alist)
+
+(defvar ess--local-handy-commands nil
+ "Store handy commands locally")
+(make-variable-buffer-local 'ess--local-handy-commands)
+
+(defvar ess-install-library-function nil
+ "Dialect-specific function to install a library.")
+(make-variable-buffer-local 'ess-install-library-function)
+
+
+(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 `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)")
+ ("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 by calling 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 ess-language nil
+ "Determines the language to use for the current buffer.
+See also `ess-dialect'.")
+(make-variable-buffer-local 'ess-language)
+
+(defvar 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.")
+(make-variable-buffer-local 'ess-dialect)
+
+(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 `ess-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
+ "No fancy process buffname for the first process of each type (novice mode)."
+ :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.
+
+Some useful keys for IDO completion:
+
+ - C-s (next) or C-r (previous) to move through the list.
+ - C-SPC to restrict the list to currently matched items.
+ - TAB to display possible completion in a buffer
+ - C-t `ido-toggle-regexp'
+"
+ :group 'ess
+ :type 'boolean)
+
+
+(defcustom ess-tab-complete-in-script nil
+ "If non-nil, TAB in script buffers tries to complete if there is nothing to indent.
+See also `ess-first-tab-never-complete'."
+ :group 'ess
+ :type 'boolean)
+
+(defvaralias 'ess-first-tab-never-completes-p 'ess-first-tab-never-complete)
+(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
+ "How ess-eldoc string should be abbreviated when it doesn't fit into one 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 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)))
+
+(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-ac-sources nil
+ "Dialect specific, ESS specific list of ac-sources")
+
+(defvar ess-company-backends nil
+ "Dialect specific, ESS specific list of `company-backends'")
+
+(defvar ess--completing-hist nil
+ "Variable to store completion history.
+Used by `ess-completion-read' command.")
+
+(defvar 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'.")
+(make-variable-buffer-local 'ess-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 axplicit list of operators, use only those
+operators.
+
+In current verion 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.")
+
+(defcustom ess-smart-S-assign-key "_"
+ "Key used by `ess-smart-S-assign'.
+Should be nil or a \"simple\" key, in other words no key
+modifiers.
+
+This variable is deprecated and will be removed in the future.
+Please bind `ess-insert-assign' in `ess-mode-map' to your key of
+choice with `define-key' or similar."
+ :group 'ess-S
+ :type '(choice (const :tag "Nothing" :value nil) string))
+(make-obsolete-variable 'ess-smart-S-assign-key nil "ESS 18.10")
+
+(defcustom ess-assign-list (cons (if (boundp 'ess-S-assign) 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 behaviour
+
+(defcustom ess-filenames-map t
+ "Declares if the filenames in an attached directory are the same
+as objects in that directory (when t). 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 behaviour
+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 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 M-q three times sets N to 1 while calling M-q
+twice then C-U 2 M-q 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
+ "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, 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
+the next 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 a call or a continuation will first
+blink the filling region."
+ :group 'ess-edit
+ :type 'boolean)
+
+(defcustom ess-mode-silently-save t
+ "Non-nil means automatically save ESS source buffers before loading."
+ :group 'ess-edit
+ :type 'boolean)
+
+;;*;; 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
+
+(defcustom ess-auto-newline nil
+ "Non-nil means automatically newline before and after braces
+inserted in S code."
+ :type 'boolean
+ :group 'ess-edit)
+
+(defcustom ess-tab-always-indent t
+ "Non-nil means TAB in S mode should always reindent the current line,
+regardless of where in the line point is when the TAB command is used."
+ :type 'boolean
+ :group 'ess-edit)
+
+(defvar ess-indent-line-function nil
+ "Function to be used for the current dialect
+nil means to use R/S indentation.")
+(make-variable-buffer-local 'ess-indent-line-function)
+
+(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.")
+
+(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
+ ))
+
+
+Wnen 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
+ "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 declaring function calls for which
+`ess-offset-arguments-newline' should be ignored. These calls
+will be vertically aligned instead. The default is `ifelse',
+resulting in the following indentation for nested ifelse calls:
+
+ 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]*(")
+ "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 should be 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' should be
+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 syntactic elements that should be indented from the
+left-hand 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 will be treated as if they were
+one call and 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 distiguish 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-default-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', with the key KEY.
+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-default-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)))
+
+(defcustom ess-default-style 'RRR
+ "The default value of `ess-indent-style'.
+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."
+ :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)
+
+;; the real setting of this happens via <foo>-editing-alist:
+(defvar ess-style ess-default-style
+ "Current ESS indentation style, see `ess-style-alist' for more.")
+
+;;*;; Variables controlling behaviour 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)
+
+
+;;*;; Hooks
+
+(defcustom ess-mode-hook nil
+ "Hook for customizing ESS each time it is entered."
+ :group 'ess-hooks
+ :type 'hook)
+
+(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 inferior-ess-mode-hook nil
+ "Hook for customizing inferior ESS mode. Called after
+`inferior-ess-mode' is entered and variables have been initialised."
+ :group 'ess-hooks
+ :type 'hook)
+
+;;; make it possible to save an inferior-ess-mode buffer without losing
+;;; the connection to the running ESS process.
+(put 'inferior-ess-mode 'mode-class 'special)
+;; FIXME AJR: Should the above be there? I don't think so!
+;; MM : the functionality should be, right? Move statement to ./ess.el ?
+;; AJR: No, we should move the statement to ./ess-inf.el
+
+(defcustom ess-help-mode-hook nil
+ "Functions to call when entering `ess-help-mode'."
+ :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)
+
+(defcustom ess-transcript-mode-hook nil
+ "Hook for customizing ESS transcript mode."
+ :group 'ess-hooks
+ :type 'hook)
+
+(defcustom R-mode-hook nil
+ "Hook run when entering R mode."
+ :type 'hook
+ :group 'ess-R)
+
+(defcustom Rnw-mode-hook nil
+ "Hook run when entering Rnw mode."
+ :type 'hook
+ :group 'ess-R)
+
+(defcustom SAS-mode-hook nil
+ "Hook to run when entering SAS mode."
+ :type 'hook
+ :group 'ess-sas)
+
+(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"))
+ :group 'ess)
+
+(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)
+ :group 'ess)
+
+;; ---- ./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")
+ "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 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)
+
+(defcustom ess-roxy-re "^#+'"
+ "Regular expression to recognize roxygen blocks."
+ :group 'ess-roxy
+ :type '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)))
+
+(defvar ess-roxy-insert-prefix-on-newline t
+ "When non-nil, `ess-newline-and-indent' will make sure the new
+line starts with the roxy prefix.")
+
+\f ; System variables
+
+;; SJE -- this should not be defcustom - user does not set it.
+(defvaralias 'ess-current-process-name 'ess-local-process-name)
+(defvar 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)
+(make-variable-buffer-local 'ess-local-process-name)
+
+(defcustom ess-switch-to-end-of-proc-buffer t
+ "If t, `ess-switch-to-inferior-or-script-buffer goes to end of
+process buffer."
+ :group 'ess
+ :type 'boolean)
+
+(defcustom ess-gen-proc-buffer-name-function 'ess-gen-proc-buffer-name:projectile-or-simple
+ "Function used for generation of the buffer name of the newly created ESS process.
+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:projectile-or-simple' -- *proc:projectile-root* or *proc*.
+ `ess-gen-proc-buffer-name:projectile-or-directory' -- *proc:projectile-root* or *proc:dir*.
+
+Strategies based on projectile default to built-in strategies if
+projectile.el is not loaded or 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:projectile-root* or *proc*" ess-gen-proc-buffer-name:projectile-or-simple)
+ (const :tag "*proc:projectile-root* or *proc:dir*" ess-gen-proc-buffer-name:projectile-or-directory)
+ function))
+
+
+(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)
+
+
+\f ; ess-inf: variables for inferior-ess.
+
+(defcustom inferior-ess-own-frame nil
+ "Non-nil means that inferior ESS buffers should start in their own frame.
+The parameters of this frame are stored in `inferior-ess-frame-alist'."
+ :group 'ess-proc
+ :type 'boolean)
+
+(defcustom inferior-ess-frame-alist default-frame-alist
+ "Alist of frame parameters used to create new frames for iESS buffers.
+This defaults to `default-frame-alist' and is used only when
+the variable `inferior-ess-own-frame' is non-nil."
+ :group 'ess-proc
+ :type 'alist)
+
+(defcustom inferior-ess-same-window t
+ "Non-nil indicates new inferior ESS process appears in current window.
+Otherwise, the new inferior ESS buffer is shown in another window in the
+current frame. This variable is ignored if `inferior-ess-own-frame' is
+non-nil."
+ :group 'ess-proc
+ :type 'boolean)
+
+(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 (see 'R --help') used when starting R,
+including the versions of R created via variable `ess-r-versions'."
+ :group 'ess-R
+ :type 'string)
+
+(defcustom ess-R-readline nil
+ "nil indicates that \"--no-readline \" should be used as argument when starting R.
+This has been the default since 1998 and 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 ess evaluation completely."
+ :group 'ess-R
+ :type 'boolean)
+
+(defcustom inferior-STA-start-file nil
+ "Initialization file for Stata."
+ :group 'ess-Stata
+ :type '(choice (const nil) string))
+
+(defcustom inferior-STA-start-args ""
+ "String of switches used when starting stata.
+Don't use this to send initialization command to stata, use
+`inferior-STA-start-file' instead. 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 retriving the working directory from the process.")
+
+(defvar ess-setwd-command nil
+ "Command string to set working directory.
+Should contain a formating %s to be replaced by a
+path (as in 'setwd(%s)\\n'.")
+
+(defcustom ess-program-files ;; 32 bit version
+ (if ess-microsoft-p
+ (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
+ (if (and ess-microsoft-p (getenv "ProgramW6432"))
+ (w32-short-file-name (getenv "ProgramW6432"))
+ nil)
+ "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
+ "nil (the default) means the search for all occurences 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 pathnames 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 `exec-path' variable 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))
+
+(defcustom ess-SHOME-versions
+ ;; ess-program-files ~= "c:/progra~1" for typical locales/languages
+ (mapcar
+ (lambda (ch) (concat ess-program-files ch))
+ '("/Insightful/splus62"
+ "/Insightful/splus61"
+ "/MathSoft/splus6"
+ "/spls45se"
+ "/Insightful/splus62netclient"
+ "/Insightful/splus62net/server"
+ "/Insightful/splus61netclient"
+ "/Insightful/splus61net/server"
+ "/Insightful/splus6se"
+ "/Insightful/splus61se"
+ "/Insightful/splus62se"
+ "/Insightful/splus70"
+ "/Insightful/splus71"
+ "/Insightful/splus8.0.1"
+ "/Insightful/splus8.0.4"
+ "/Insightful/splus80"
+ "/TIBCO/splus81"
+ "/TIBCO/splus82"
+ ))
+ "List of possible values of the environment variable SHOME for recent
+releases of S-Plus. These are the default locations for several
+current and recent releases of S-Plus. If any of these pathnames
+correspond to a directory on your machine, running the function
+`ess-sqpe-versions-create' will create a function, for example,
+\\[splus70], that will start the corresponding version Sqpe inside an
+emacs buffer in iESS[S] mode. If you have versions of S-Plus in
+locations other than these default values, redefine this variable with
+a `custom-set-variables' statement in your site-start.el or .emacs
+file. The list of functions actually created appears in the *ESS*
+buffer and should appear in the \"ESS / Start Process / Other\"
+menu."
+ :group 'ess-SPLUS
+ :type '(repeat string))
+
+(defcustom ess-SHOME-versions-64
+ ;; ess-program-files-64 ~= "c:/progra~1" for typical locales/languages
+ (mapcar
+ (lambda (ch) (concat ess-program-files-64 ch))
+ '("/TIBCO/splus82"
+ ))
+ "List of possible values of the environment variable SHOME for recent
+releases of 64-bit S-Plus. These are the default locations for several
+current and recent releases of S-Plus. If any of these pathnames
+correspond to a directory on your machine, running the function
+`ess-sqpe-versions-create' will create a function, for example,
+\\[splus70], that will start the corresponding version Sqpe inside an
+emacs buffer in iESS[S] mode. If you have versions of 64-bit S-Plus in
+locations other than these default values, redefine this variable with
+a `custom-set-variables' statement in your site-start.el or .emacs
+file. The list of functions actually created appears in the *ESS*
+buffer and should appear in the \"ESS / Start Process / Other\"
+menu."
+ :group 'ess-SPLUS
+ :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+3-program-name
+ 'inferior-S+3-program "ESS 18.10")
+(define-obsolete-variable-alias 'inferior-S-program-name
+ 'inferior-S+3-program "ESS 18.10")
+(defcustom inferior-S+3-program "Splus"
+ "Program name for invoking an inferior ESS with S+3()."
+ :group 'ess-SPLUS
+ :type '(choice (string) file))
+
+(define-obsolete-variable-alias 'inferior-S+4-program-name
+ 'inferior-S+4-program "ESS 18.10")
+(defcustom inferior-S+4-program
+ (concat ess-program-files "/spls45se/cmd/Splus.exe")
+ "Program name for invoking an external GUI S+4.
+The default value is correct for a default installation of
+S-Plus 4.5 Student Edition 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 pathname.
+Use double backslashes if you use the msdos shell."
+ :group 'ess-SPLUS
+ :type 'string)
+
+(defcustom inferior-S+4-print-command "S_PRINT_COMMAND=emacsclientw.exe"
+ "Destination of print icon in S+4 Commands window."
+ :group 'ess-SPLUS
+ :type 'string)
+
+(defcustom inferior-S+4-editor-pager-command
+ "options(editor='emacsclient.exe', pager='emacsclientw.exe')"
+ "Programs called by the editor() and pager() functions
+in S+4 Commands window and in Sqpe+4 buffer."
+ :group 'ess-S
+ :type 'string)
+
+(define-obsolete-variable-alias 'inferior-Sqpe+4-program-name
+ 'inferior-Sqpe+4-program "ESS 18.10")
+(defcustom inferior-Sqpe+4-program
+ (concat ess-program-files "/spls45se/cmd/Sqpe.exe")
+ "Program name for invoking an inferior ESS with Sqpe+4()."
+ :group 'ess-SPLUS
+ :type '(choice (const nil) (string)))
+
+(defcustom inferior-Sqpe+4-SHOME-name
+ (if ess-microsoft-p (concat ess-program-files "/spls45se" ""))
+ "SHOME name for invoking an inferior ESS with Sqpe+4().
+The default value is correct for a default installation of
+S-Plus 4.5 Student Edition. For any other version or location,
+change this value in ess-site.el or site-start.el. Use the 8.3
+version of the pathname."
+ :group 'ess-SPLUS
+ :type '(choice (const nil) (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)
+
+(define-obsolete-variable-alias
+ 'inferior-ESS-elsewhere-program-name
+ 'inferior-ESS-elsewhere-program "ESS 18.10")
+(defcustom inferior-ESS-elsewhere-program "sh"
+ "Program name to invoke an inferior ESS with program on a
+different computer."
+ :group 'ess-proc
+ :type 'string)
+
+(define-obsolete-variable-alias 'inferior-S4-program-name
+ 'inferior-S4-program "ESS 18.10")
+(defcustom inferior-S4-program "S4"
+ "Program name to invoke an inferior ESS with S4()."
+ :group 'ess-S
+ :type '(choice (string) (file)))
+
+(define-obsolete-variable-alias 'inferior-S+5-program-name
+ 'inferior-S+5-program "ESS 18.10")
+(defcustom inferior-S+5-program "Splus5"
+ "Program name to invoke an inferior ESS with S+5()."
+ :group 'ess-SPLUS
+ :type '(choice (string) (file)))
+
+(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)
+
+(defvaralias 'inferior-S+6-program 'inferior-S+-program)
+(define-obsolete-variable-alias 'inferior-S+6-program-name
+ 'inferior-S+-program "ESS 18.10")
+
+(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 pathname. 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)
+
+
+(defvaralias 'inferior-Sqpe-start-args 'inferior-Sqpe+-start-args)
+(defcustom inferior-Sqpe+-start-args " "
+ "Default is empty. Can be used for license manager information, for example
+`(setq inferior-Sqpe+-start-args \" S_ELMHOST=@123.456.789.012 ELMTIMEOUT=60 \")'."
+ ;; (setq inferior-Sqpe+-start-args " S_ELMHOST=@123.456.789.012 ELMTIMEOUT=60 ") ;; use this line as the model for your site-start.el
+ :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)
+
+(defvaralias 'inferior-S+6-print-command 'inferior-S+-print-command)
+
+(defcustom inferior-S+-print-command "S_PRINT_COMMAND=emacsclientw.exe"
+ "Destination of print icon in S+ for Windows Commands window."
+ :group 'ess-SPLUS
+ :type 'string)
+
+(defvaralias 'inferior-S+6-editor-pager-command 'inferior-S+-editor-pager-command)
+(defcustom inferior-S+-editor-pager-command
+ "options(editor='emacsclient.exe', pager='emacsclientw.exe')"
+ "Programs called by the editor() and pager() functions in S+
+for Windows Commands window and in Sqpe+6 for Windows buffer."
+ :group 'ess-SPLUS
+ :type 'string)
+
+(defvaralias 'inferior-Sqpe+6-program 'inferior-Sqpe+-program)
+(define-obsolete-variable-alias 'inferior-Sqpe+-program-name
+ 'inferior-Sqpe+-program "ESS 18.10")
+(defcustom inferior-Sqpe+-program
+ (concat ess-program-files "/TIBCO/splus82/cmd/Sqpe.exe")
+ "Program name for invoking an inferior ESS with Sqpe+6() for Windows."
+ :group 'ess-S
+ :type '(choice (const nil) (string)))
+
+(defvaralias 'inferior-Sqpe+6-SHOME-name 'inferior-Sqpe+-SHOME-name)
+(defcustom inferior-Sqpe+-SHOME-name
+ (if ess-microsoft-p (concat ess-program-files "/TIBCO/splus82" ""))
+ "SHOME name for invoking an inferior ESS with Sqpe+6 and higher for Windows.
+The default value is correct for a default installation of
+S-Plus 8.1. For any other version or location,
+change this value in ess-site.el or site-start.el. Use the 8.3
+version of the pathname."
+ :group 'ess-SPLUS
+ :type '(choice (const nil) (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 C-c C-q.
+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-XLS-program-name
+ 'inferior-XLS-program "ESS 18.10")
+(defcustom inferior-XLS-program "xlispstat"
+ "Program name for invoking an inferior ESS with \\[XLS]."
+ :group 'ess-XLS
+ :type '(choice (string) (file)))
+
+(define-obsolete-variable-alias 'inferior-VST-program-name
+ 'inferior-VST-program "ESS 18.10")
+(defcustom inferior-VST-program "vista"
+ "Program name for invoking an inferior ESS with \\[ViSta]."
+ :group 'ess-XLS
+ :type '(choice (string) (file)))
+
+(define-obsolete-variable-alias 'inferior-ARC-program-name
+ 'inferior-ARC-program "ESS 18.10")
+(defcustom inferior-ARC-program "arc"
+ "Program name for invoking an inferior ESS with \\[ARC]."
+ :group 'ess-XLS
+ :type '(choice (string) (file)))
+
+(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)))
+
+(defcustom ess-sta-delimiter-friendly nil
+ "Non-nil means convert embedded semi-colons to newlines for Stata processing."
+ :group 'ess-Stata
+ :type 'boolean)
+
+(define-obsolete-variable-alias 'inferior-OMG-program-name
+ 'inferior-OMG-program "ESS 18.10")
+(defcustom inferior-OMG-program "omegahat"
+ "Program name for invoking an inferior ESS with omegahat()."
+ :group 'ess-OMG
+ :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 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 ess-pager nil
+ "*Pager by which the process sends information to an emacs buffer.")
+
+(defvar inferior-ess-language-start nil
+ "*Initialization commands sent to the ESS process.")
+
+(make-variable-buffer-local 'ess-editor)
+(make-variable-buffer-local 'ess-pager)
+(make-variable-buffer-local 'inferior-ess-language-start)
+
+
+
+;;;;; names for S-Plus help files on MS-Windows
+
+(defcustom inferior-ess-help-filetype nil
+ "S-Plus and Sqpe for Windows use the \"chm\" (compiled html) filetype
+for help files. The default value is nil for other systems."
+ :group 'ess-proc
+ :type '(choice (const nil) (string)))
+(make-variable-buffer-local 'inferior-ess-help-filetype)
+
+;;;;; names for communication using MS-Windows 9x/NT ddeclient mechanism
+
+(defcustom inferior-ess-ddeclient nil
+ "ddeclient is the intermediary between emacs and the stat program."
+ :group 'ess-proc
+ :type '(choice (const nil) (string)))
+
+(defcustom inferior-ess-client-name nil
+ "Name of ESS program ddeclient talks to."
+ :group 'ess-proc
+ :type '(choice (const nil) (string)))
+
+(defcustom inferior-ess-client-command nil
+ "ddeclient command sent to the ESS program."
+ :group 'ess-proc
+ :type '(choice (const nil) string))
+
+(make-variable-buffer-local 'inferior-ess-client-name)
+(make-variable-buffer-local 'inferior-ess-ddeclient)
+(make-variable-buffer-local 'inferior-ess-client-command)
+
+(defvar inferior-S-program inferior-S+3-program
+ "Program name for invoking an inferior ESS with S.")
+
+(define-obsolete-variable-alias 'inferior-ess-program-name
+ 'inferior-ess-program "ESS 18.10")
+(defvar inferior-ess-program nil ;inferior-S-program
+ "Default program name for invoking `inferior-ess'.
+The other variables ...-program should be changed, for the
+corresponding program.")
+(make-variable-buffer-local 'inferior-ess-program)
+
+(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-start-file nil
+ "File dumped into process, if non-nil."
+ :group 'ess-proc
+ :type '(choice (const nil) file))
+
+(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 inferior-ess-primary-prompt "> "
+ "Regular expression used by `ess-mode' to detect the primary prompt.")
+(make-variable-buffer-local 'inferior-ess-primary-prompt)
+
+(defvar 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.")
+(make-variable-buffer-local 'inferior-ess-secondary-prompt)
+
+(defvar ess-traceback-command nil
+ "Command to generate error traceback.")
+
+;; need this to recognise + + + > > >
+;; and "+ . + " in tracebug prompt
+;; VS[17-08-2012]: all of the occurrences in the code should should eventually
+;; go away, (once we are sure this doesn't break anything)
+(defvaralias 'inferior-ess-S-prompt 'inferior-S-prompt)
+(defvar inferior-S-prompt "[]a-zA-Z0-9.[]*\\(?:[>+.] \\)+"
+ "Regexp used in S and R inferior and transcript buffers for prompt navigation.
+Must 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,
+ (see \\[deactivate-mark])."
+ :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-eval-ddeclient-sleep 0.06
+ "If non-nil, a number specifying *seconds* to wait after certain
+\\[ess-eval-linewise-ddeclient] calls, such as those at startup."
+ ;; i.e this currently only applies to (if microsoft-p ...) !
+ :group 'ess-proc
+ :type '(choice (const nil) number))
+
+(defcustom ess-sleep-for-shell (if ess-microsoft-p 5 1)
+ "*Pause before sending output to the shell."
+ :group 'ess-proc
+ :type 'number)
+
+\f ; System variables
+;; VS[06-04-2016]: fixme: move all inf vars into ess-inf.el.
+
+;;*;; Variables relating to multiple processes
+
+(defvar 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 ot one of the standard mode line
+objecst. 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)
+(make-variable-buffer-local 'ess--mode-line-process-indicator)
+
+(defvar 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 varialbe used by tools like `ess-developer'
+and `ess-tracebug'.")
+(put 'ess--local-mode-line-process-indicator 'risky-local-variable t)
+(make-variable-buffer-local 'ess--local-mode-line-process-indicator)
+
+(defvar ess-process-name-list nil
+ "Alist of active ESS processes.")
+
+;;*;; Inferior ESS commands
+
+(defvar 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 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 ess-build-eval-message-function nil
+ "Dialect-specific function for formatting an evaluation message.")
+
+(make-variable-buffer-local 'ess-eval-command)
+(make-variable-buffer-local 'ess-load-command)
+(make-variable-buffer-local 'ess-build-eval-message-function)
+
+(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 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.")
+(make-variable-buffer-local 'inferior-ess-help-command)
+
+(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 ess-get-help-topics-function nil
+ "Dialect specific help topics retrieval")
+
+(defvar ess-display-help-on-object-function nil
+ "Dialect specific function for displaying help on object.")
+
+(defvar ess-find-help-file-function nil
+ "Dialect specific function for displaying help on object.")
+
+(defvar ess-build-help-command-function nil
+ "Dialect specific function for building an help command.")
+
+(make-variable-buffer-local 'ess-get-help-topics-function)
+(make-variable-buffer-local 'ess-display-help-on-object-function)
+(make-variable-buffer-local 'ess-find-help-file-function)
+(make-variable-buffer-local 'ess-build-help-command-function)
+
+(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 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 <ess-lang>-customize-alist in ess[dl]-*.el")
+(make-variable-buffer-local 'inferior-ess-search-list-command)
+
+(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)
+
+(defcustom inferior-ess-get-prompt-command "options()$prompt\n"
+ "Command to find the value of the current S prompt."
+ :group 'ess-command
+ :type 'string)
+
+;;*;; Regular expressions
+(defvar 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 customise-alist it is constructed at run time
+from `inferior-ess-primary-prompt' and `inferior-ess-secondary-prompt'.")
+
+(make-variable-buffer-local 'inferior-ess-prompt)
+
+(defvar ess-change-sp-regexp ""
+ "The regexp for matching the S/R/.. commands that change the search path.")
+(make-variable-buffer-local 'ess-change-sp-regexp)
+
+(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.")
+
+(defvar ess-S-change-sp-regexp
+ "\\(attach(\\([^)]\\|$\\)\\|detach(\\|library(\\|source(\\)"
+ "The regexp for matching the S 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 ess-search-list nil
+ "Deprecated. Use (ess-search-list) or (ess-process-get 'search-list) instead.")
+(make-obsolete-variable 'ess-search-list nil "ESS[12.09]")
+
+(defvar ess-sl-modtime-alist nil
+ "Alist of modification times for all ess directories accessed this session.")
+(make-variable-buffer-local 'ess-sl-modtime-alist)
+
+(defvar ess-sp-change nil
+ "Variable not used. Use (ess-process-get 'sp-for-help-changed?) instead.")
+(make-obsolete-variable 'ess-sp-change nil "ESS[12.09]")
+;; (make-variable-buffer-local 'ess-sp-change)
+
+(defvar 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.")
+
+(make-variable-buffer-local 'ess-prev-load-dir/file)
+
+(defvar 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")
+
+(make-variable-buffer-local 'ess-object-list)
+
+(defvar ess-help-topics-list nil
+ ;; List of currently known help topics.
+ "Cache of help topics")
+
+(make-variable-buffer-local 'ess-help-topics-list)
+
+
+;;*;; Miscellaneous system variables
+
+(defvar ess-temp-point nil
+ "Variable used to retain a buffer position past let or let*.")
+
+
+;; 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 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'.")
+
+(make-variable-buffer-local 'ess-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
+ "Internal. Holds a name of the dialect sepcific font-lock
+keywords in the current buffer. See `ess-R-font-lock-keywords'
+for an example.")
+(make-variable-buffer-local 'ess-font-lock-keywords)
+
+(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 "[-=+></]+" 'ess-operator-face)
+ "Operators.")
+
+(defvar ess-S-fl-keyword:modifiers
+ (cons (regexp-opt ess-S-modifiers 'words)
+ 'ess-modifiers-face) ; modify search list or source (i.e. directives)
+ "Font lock keyword R modifiers.")
+
+(defvar ess-S-fl-keyword:fun-defs
+ (cons ess-S-function-name-regexp
+ '(1 font-lock-function-name-face t))
+ "Font-lock function definitions keyword.")
+
+(defvar ess-S-fl-keyword:keywords
+ (cons (regexp-opt ess-S-keywords 'words) 'ess-keyword-face))
+
+(defvar ess-S-fl-keyword:assign-ops
+ (cons (regexp-opt ess-S-assign-ops) 'ess-assignment-face)
+ "Font-lock assign operators")
+
+(defvar ess-S-fl-keyword:constants
+ (cons (regexp-opt ess-S-constants 'words) 'ess-constant-face)
+ "Font-lock constants keyword.")
+
+(defcustom ess-S-font-lock-keywords
+ '((ess-S-fl-keyword:modifiers . t)
+ (ess-S-fl-keyword:fun-defs . t)
+ (ess-S-fl-keyword:keywords . t)
+ (ess-S-fl-keyword:assign-ops . t)
+ (ess-S-fl-keyword:constants . t)
+ (ess-fl-keyword:fun-calls)
+ (ess-fl-keyword:numbers)
+ (ess-fl-keyword:operators)
+ (ess-fl-keyword:delimiters)
+ (ess-fl-keyword:=))
+ "An alist of available font-lock keywords for the S mode.
+The key of each cons cell is a name of the keyword. The value
+should be t or nil to indicate if the keyword is activated by
+default or not."
+ :group 'ess-S
+ :group 'ess-faces
+ :type '(repeat (cons symbol boolean)))
+
+(defvar ess-R-fl-keyword:modifiers
+ '(eval . (cons (concat "\\(" (regexp-opt ess-R-modifiers 'words) "\\)\\s-*(")
+ '(1 ess-modifiers-face)))
+ "Font-lock keyword R modifiers.
+See `ess-R-modifiers' for the list of modifiers.")
+
+(defvar ess-R-fl-keyword:fun-defs
+ '(eval . (cons ess-R-function-name-regexp
+ '(1 font-lock-function-name-face nil)))
+ "Font-lock keyword for function names in function definitions.
+When this keyword is on, function names on the left hand side of
+<- are highlighted with `font-lock-function-name-face'.")
+
+(defvar ess-R-fl-keyword:keywords
+ '(ess-r--find-fl-keyword . ess-keyword-face)
+ "Font lock keyword for `ess-R-keywords'.")
+
+(defvar ess-R-fl-keyword:assign-ops
+ '(eval . (cons (regexp-opt ess-R-assign-ops) 'ess-assignment-face))
+ "Font-lock assign operators.
+See `ess-R-assign-ops' for the ops.")
+
+(defvar ess-R-fl-keyword:constants
+ '(eval . (cons (regexp-opt ess-R-constants 'words) 'ess-constant-face))
+ "Font-lock constants keyword.
+See `ess-R-constants' for the list of constants.")
+
+(defvar ess-R-fl-keyword:F&T
+ '("\\b[FT]\\b" . ess-constant-face)
+ "Highlight T and F in addition to TRUE and FALSE in R.")
+
+(defvar ess-R-fl-keyword:%op% nil
+ "Highlight %op% operators.")
+
+(defcustom ess-R-font-lock-keywords
+ '((ess-R-fl-keyword:keywords . t)
+ (ess-R-fl-keyword:constants . t)
+ (ess-R-fl-keyword:modifiers . t)
+ (ess-R-fl-keyword:fun-defs . t)
+ (ess-R-fl-keyword:assign-ops . t)
+ (ess-R-fl-keyword:%op% . t)
+ (ess-fl-keyword:fun-calls)
+ (ess-fl-keyword:numbers)
+ (ess-fl-keyword:operators)
+ (ess-fl-keyword:delimiters)
+ (ess-fl-keyword:=)
+ (ess-R-fl-keyword:F&T))
+ "An alist of available font-lock keywords for the R mode.
+The key of each cons cell is a name of the keyword. The value
+should be t or nil to indicate if the keyword is active or not."
+ :group 'ess-R
+ :group 'ess-faces
+ :type '(repeat (cons symbol boolean)))
+
+(defvar inferior-ess-font-lock-keywords nil
+ "Internal. Holds a name of the dialect sepcific font-lock
+keywords in the current buffer. See
+`inferior-ess-r-font-lock-keywords' for an example.")
+(make-variable-buffer-local 'inferior-ess-font-lock-keywords)
+
+(defvar ess-S-fl-keyword:prompt
+ (cons (concat "^" inferior-S-prompt) 'comint-highlight-prompt)
+ "Highlight prompts missed by comint.")
+
+(defvar ess-fl-keyword:matrix-labels
+ ;; also matches subsetting
+ (cons "\\[,?[1-9][0-9]*,?\\]" 'ess-matrix-face)
+ "Matrix and vector numeric labels.")
+
+(defvar ess-R-fl-keyword:messages
+ (cons (regexp-opt ess-R-message-prefixes 'enc-paren)
+ 'font-lock-warning-face)
+ "Inferior-ess problems or errors.")
+
+(defvaralias 'inferior-R-font-lock-keywords 'inferior-ess-r-font-lock-keywords)
+(defcustom inferior-ess-r-font-lock-keywords
+ '((ess-S-fl-keyword:prompt . t)
+ (ess-R-fl-keyword:keywords . t)
+ (ess-R-fl-keyword:constants . t)
+ (ess-R-fl-keyword:modifiers . t)
+ (ess-R-fl-keyword:messages . t)
+ (ess-R-fl-keyword:fun-defs . t)
+ (ess-R-fl-keyword:assign-ops . t)
+ (ess-fl-keyword:matrix-labels . t)
+ (ess-fl-keyword:fun-calls)
+ (ess-fl-keyword:numbers)
+ (ess-fl-keyword:operators)
+ (ess-fl-keyword:delimiters)
+ (ess-fl-keyword:=)
+ (ess-R-fl-keyword:F&T))
+ "Font-lock patterns used in inferior-R-mode buffers.
+The key of each cons cell is a name of the keyword. The value
+should be t or nil to indicate if the keyword is active or not."
+ :group 'ess-R
+ :group 'ess-faces
+ :type '(repeat (cons symbol boolean)))
+
+(defvar ess-S-fl-keyword:messages
+ (cons (regexp-opt ess-S-message-prefixes 'enc-paren)
+ 'font-lock-warning-face)
+ "Inferior-ess problems or errors.")
+
+(defcustom inferior-S-font-lock-keywords
+ '((ess-S-fl-keyword:prompt . t)
+ (ess-S-fl-keyword:messages . t)
+ (ess-S-fl-keyword:modifiers . t)
+ (ess-S-fl-keyword:fun-defs . t)
+ (ess-S-fl-keyword:keywords . t)
+ (ess-S-fl-keyword:assign-ops . t)
+ (ess-S-fl-keyword:constants . t)
+ (ess-fl-keyword:fun-calls)
+ (ess-fl-keyword:numbers)
+ (ess-fl-keyword:operators)
+ (ess-fl-keyword:delimiters)
+ (ess-fl-keyword:=))
+ "Font-lock patterns used in inferior-S-mode buffers.
+The key of each cons cell is a name of the keyword. The value
+should be t or nil to indicate if the keyword is active by
+default."
+ :group 'ess-S
+ :group 'ess-faces
+ :type '(repeat (cons symbol boolean)))
+
+\f
+;;;*;;; ess-help variables
+
+;; This will never need to be loaded independently of any of the other modules,
+;; but they can all call it so we may as well put it here.
+
+(defcustom ess-help-pop-to-buffer t
+ "If non-nil ess-help buffers are given focus during the display.
+The default is t (except when `focus-follows-mouse' and
+`mouse-autoselect-window' are both t)."
+ :group 'ess-help
+ :type 'boolean)
+
+(defcustom ess-help-own-frame nil
+ "Controls whether ESS help buffers should start in a different frame.
+
+Possible values are:
+ nil: Display help in current frame.
+ 'one: All help buffers are shown in one dedicated frame.
+ t: Each help buffer gets its own frame.
+
+Note if you set this to t you should also set
+`ess-help-reuse-window' to nil to ensure that help buffers are
+displayed in a new frame.
+
+The parameters of the own frame are stored in `ess-help-frame-alist'.
+See also `inferior-ess-own-frame'."
+ :group 'ess-help
+ :type '(choice (const :tag "Display in current frame" nil)
+ (const :tag "Display in one frame" one)
+ (const :tag "Always display in a new frame" t)))
+
+(defcustom ess-help-reuse-window t
+ "If t, ESS tries to display new help buffers in the existing help window."
+ :type 'boolean
+ :group 'ess-help)
+
+(defcustom ess-help-frame-alist default-frame-alist
+ "Alist of frame parameters used to create help frames.
+This defaults to `default-frame-alist' and is used only when
+the variable `ess-help-own-frame' is non-nil."
+ :group 'ess-help
+ :type 'alist
+ :package-version '(ess . "18.10"))
+
+
+\f ; Faces
+;;;=====================================================
+
+(defconst comint-highlight-prompt 'comint-highlight-prompt)
+
+(defconst ess-function-call-face 'ess-function-call-face)
+(defface ess-function-call-face
+ '((default (:slant normal :inherit font-lock-function-name-face)))
+ "Font Lock face used to highlight function calls in ess buffers."
+ :group 'ess-faces)
+
+(defconst ess-numbers-face 'ess-numbers-face)
+(defface ess-numbers-face
+ '((default (:slant normal :inherit font-lock-type-face)))
+ "Font Lock face used to highlight numbers in ess-mode buffers."
+ :group 'ess-faces)
+
+(defconst ess-operator-face 'ess-operator-face)
+(defface ess-operator-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font Lock face for operators."
+ :group 'ess-faces)
+
+(defconst ess-%op%-face 'ess-%op%-face)
+(defface ess-%op%-face
+ '((default (:inherit ess-operator-face)))
+ "Font Lock face used to highlight %op% operators in ess-mode buffers."
+ :group 'ess-faces)
+
+(defconst ess-assignment-face 'ess-assignment-face)
+(defface ess-assignment-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font lock face used to highlight assignment operators."
+ :group 'ess-faces)
+
+(defconst ess-paren-face 'ess-paren-face)
+(defface ess-paren-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font lock face used to highlight parentheses."
+ :group 'ess-faces)
+
+(defconst ess-operator-face 'ess-operator-face)
+(defface ess-operator-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font lock face used to highlight operators."
+ :group 'ess-faces)
+
+(defconst ess-modifiers-face 'ess-modifiers-face)
+(defface ess-modifiers-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font lock face used to highlight modifiers.
+In `R-mode', for example, this includes \"library,\" \"attach,\"
+and others. See `ess-R-modifiers'."
+ :group 'ess-faces)
+
+(defconst ess-constant-face 'ess-constant-face)
+(defface ess-constant-face
+ '((default (:inherit font-lock-type-face)))
+ "Font lock face used to highlight constants.
+In `R-mode', for example, this includes TRUE, FALSE, Inf and
+others. See `ess-R-constants'."
+ :group 'ess-faces)
+
+(defconst ess-matrix-face 'ess-matrix-face)
+(defface ess-matrix-face
+ '((default (:inherit font-lock-constant-face)))
+ "Font lock face used to highlight row/column labels in matrices."
+ :group 'ess-faces)
+
+(defconst ess-keyword-face 'ess-keyword-face)
+(defface ess-keyword-face
+ '((default (:inherit font-lock-keyword-face)))
+ "Font lock face used to highlight reserved keywords.
+In `R-mode', for example, this includes \"while,\" \"if/else\",
+\"function,\" and others. See `ess-R-keywords'."
+ :group 'ess-faces)
+
+(defconst ess-r-control-flow-keyword-face 'ess-r-control-flow-keyword-face)
+(defface ess-r-control-flow-keyword-face
+ '((default (:inherit ess-keyword-face)))
+ "Font lock face used to highlight control flow keywords.
+In `R-mode', for example, this includes \"switch(),\"
+\"tryCatch()\", and \"stop(),\". See
+`ess-R-control-flow-keywords'. By default, these keywords are
+highlighted with the same face as `ess-R-keywords'"
+ :group 'ess-faces)
+
+(defcustom ess-help-kill-bogus-buffers t
+ "Non-nil means kill ESS help buffers immediately if they are \"bogus\"."
+ :group 'ess-help
+ :type 'boolean)
+
+(defvar ess-execute-screen-options-command nil
+ "Dialect specific command run by `ess-execute-screen-options'.")
+
+(defvar ess-help-web-search-command nil
+ "Dialect specific command web help search.
+Passed to `ess-execute-dialect-specific' which see.")
+(make-variable-buffer-local 'ess-help-web-search-command)
+
+(defvar ess-manual-lookup-command nil
+ "Dialect specific command manual lookup.
+Passed to `ess-execute-dialect-specific' which see.")
+(make-variable-buffer-local 'ess-manual-lookup-command)
+
+(defvar ess-reference-lookup-command nil
+ "Dialect specific command for reference lookup.
+Passed to `ess-execute-dialect-specific' which see.")
+(make-variable-buffer-local 'ess-reference-lookup-command)
+
+(defvar ess-funargs-command nil
+ "Dialect specific command to return a list of function arguments.
+See `ess-function-arguments' and .ess_funargs command in R and
+S+ for details of the format that should be returned.")
+(make-variable-buffer-local 'ess-funargs-command)
+
+(defvar ess-eldoc-function nil
+ "Holds a dialect specific eldoc function.
+See `ess-r-eldoc-function' and `ess-julia-eldoc-function' for examples.")
+
+\f ; System variables
+;;;=====================================================
+;;; Users note: You will rarely have to change these
+;;; variables.
+
+;;*;; Variables relating to ess-help-mode
+
+;;-- ess-help-S-.. and ess-help-R-.. : in ess-s-lang.el (are used in ess-inf).
+
+(defvar ess-help-sec-keys-alist nil
+ "Alist of (key . string) pairs for use in section searching.")
+
+(defvar ess-help-sec-regex nil
+ "Reg(ular) Ex(pression) of section headers in help file.")
+
+(make-variable-buffer-local 'ess-help-sec-keys-alist)
+(make-variable-buffer-local 'ess-help-sec-regex)
+
+
+\f ; julia-mode
+(define-obsolete-variable-alias 'inferior-julia-program-name
+ 'inferior-julia-program "ESS 18.10")
+(defcustom inferior-julia-program (or (executable-find "julia-basic")
+ "julia")
+ "Executable for Julia.
+Should be an absolute path to the julia executable."
+ :group 'ess-Julia
+ :type '(choice (string) (file)))
+
+\f ; ess-mode: editing S source
+
+;;; This syntax table is required by ess-mode.el, ess-inf.el and
+;;; ess-trns.el, so we provide it here.
+(defvar ess-mode-syntax-table nil "Syntax table for `ess-mode'.")
+(defvar ess-mode-completion-syntax-table nil "Completion and help syntax table for `ess-mode'.")
+(make-variable-buffer-local 'ess-mode-syntax-table)
+(make-variable-buffer-local 'ess-mode-completion-syntax-table)
+
+(defvar inferior-ess-mode-syntax-table nil "Syntax table for `inferior-ess-mode'.")
+(make-variable-buffer-local 'inferior-ess-mode-syntax-table)
+
+
+\f ; Buffer local customization stuff
+
+(defcustom ess-error-buffer-name "*ESS-errors*"
+ "Name of buffer to keep process error messages in.
+Created for each process."
+ :group 'ess-proc
+ :type 'string)
+
+(defvar ess-error-regexp-alist nil
+ "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.")
+
+(defcustom ess-write-to-dribble t
+ "Non-nil means write to `ess-dribble-buffer'.
+See also `ess-verbose'."
+ :group 'ess-proc
+ :type 'boolean
+ :package-version '(ess . "18.10"))
+
+(defcustom ess-verbose nil
+ "Non-nil means write more information to `ess-dribble-buffer' than usual."
+ :group 'ess-proc
+ :type 'boolean)
+
+(defvar ess-dribble-buffer "*ESS*"
+ "Buffer or name of buffer for printing debugging information.")
+
+(defvar ess-customize-alist nil
+ "Variable settings to use for proper behavior.
+Not buffer local!")
+;; TODO: fixme We cannot make it local as yet, Not list is set on inferior startup.
+;; (make-variable-buffer-local 'ess-customize-alist)
+;; (defvaralias 'ess-local-customize-alist 'ess-customize-alist)
+
+(defvar ess-local-customize-alist nil
+ "Buffer local settings for proper behavior.
+Used to store the values for passing on to newly created buffers.")
+
+(make-variable-buffer-local 'ess-local-customize-alist)
+
+(defvar ess-mode-editing-alist nil
+ "Variable settings for `ess-mode'.")
+
+(defvar ess-transcript-minor-mode nil
+ "Non-nil if using `ess-transcript-mode' as a minor mode of some other mode.")
+
+(make-variable-buffer-local 'ess-transcript-minor-mode)
+
+(defvar ess-listing-minor-mode nil
+ "Non-nil if using `ess-listing-minor-mode'.")
+
+(make-variable-buffer-local 'ess-listing-minor-mode)
+
+(defvar ess--enable-experimental-projects nil
+ "Enable experimental project support in ESS.")
+
+(defvar ess-STERM nil
+ "Placeholder for dialect-specific STERM.")
+
+(make-obsolete-variable 'ess-S-loop-timeout "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-XLS-loop-timeout "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-mode-load-hook "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-speedbar-use-p "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-synchronize-evals "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-eval-visibly-at-end "It is ignored." "ESS 18.10")
+(make-obsolete-variable 'ess-font-lock-mode 'global-font-lock-mode "ESS 18.10")
+(provide 'ess-custom)
+
+;;; ess-custom.el ends here
--- /dev/null
+;;; ess-dde.el --- ESS customization for ddeclients under Windows 9x/NT
+
+;; Copyright (C) 1998--1999 Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Copyright (C) 2000--2006 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Created: 9 Dec 1998
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 running external processes on Windows 9x/NT
+;; through ddeclient.
+
+;;; Code:
+
+(require 'ess-custom)
+(require 'ess-mode)
+(require 'ess-utils)
+
+(defun ess-ddeclient-p ()
+ "Returns t iff `ess-local-process-name' is associated with an
+inferior-ess-ddeclient, and nil if the ess-process is running as an
+ordinary inferior process. Alway nil on Unix machines."
+ (interactive)
+ (when ess-microsoft-p
+ ;; Debug: C-c C-l fails (to start R or give good message) in Windows
+ (ess-write-to-dribble-buffer
+ (format "*ddeclient-p: ess-loc-proc-name is '%s'" ess-local-process-name))
+ (ess-force-buffer-current "Process to load into: ")
+ (not (equal (ess-get-process-variable 'inferior-ess-ddeclient)
+ (default-value 'inferior-ess-ddeclient)))))
+
+;; C-c C-r
+(defun ess-dde-send-region (proc start end &optional visibly message)
+ "Loop through lines in region and send them to ESS via ddeclient.
+
+PROC, VISIBLY and MESSAGE are ignored."
+ (setq ;; set the following variables for the current ddeESS process.
+ inferior-ess-ddeclient (ess-get-process-variable 'inferior-ess-ddeclient)
+ inferior-ess-client-name (ess-get-process-variable 'inferior-ess-client-name)
+ inferior-ess-client-command (ess-get-process-variable 'inferior-ess-client-command))
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (let ((beg))
+ (while (or (< (point) (point-max))
+ (and (= 1 (point-max))
+ (bound-and-true-p ess-dde-even-empty)))
+ (setq beg (point))
+ (end-of-line)
+ ;; call-process-region won't send over a 0-character line.
+ ;; We go outside the loop to create a 1-character line " " in the
+ ;; *ESS-temporary* buffer
+ (if (= beg (point)) ;; do empty line outside loop
+ (ess-dde-eval-linewise " " nil 'eob t)
+ ;;(call-process-region start end
+ ;; "ddeclient" nil nil nil "S-PLUS" "SCommand")
+ (call-process-region
+ beg (point)
+ inferior-ess-ddeclient nil nil nil
+ inferior-ess-client-name inferior-ess-client-command))
+ (forward-line 1))
+ (widen)))
+
+;; C-c C-n
+(defun ess-dde-eval-linewise (text-withtabs &optional invisibly eob
+ even-empty wait-last-prompt &rest args)
+ (with-current-buffer (get-buffer-create "*ESS-temporary*")
+ (ess-setq-vars-local ess-customize-alist (current-buffer))
+ (erase-buffer)
+ (insert text-withtabs)
+ (let ((ess-dde-even-empty even-empty))
+ (ess-dde-send-region nil (point-min) (point-max))))
+ (when wait-last-prompt
+ ess-eval-ddeclient-sleep)) ; in addition to timeout-ms
+
+;; C-c C-v
+(defun ess-dde-display-help-on-object (object &rest args)
+ "Display the ESS documentation for OBJECT in another window.
+If prefix arg is given, forces a query of the ESS process for the help
+file. Otherwise just pops to an existing buffer if it exists."
+ (ess-force-buffer-current "Process to load into: ")
+ (ess-dde-eval-linewise (concat "help(" object ")")))
+
+(defun ess-dde-find-help-file (p-string)
+ (read-string "Help on: "))
+
+;; C-c C-l
+(defun ess-dde-load-file (filename)
+ "Load an S source file into an inferior ESS process; alternate behavior for
+`ess-load-file', required with S-Plus GUI for Windows: Sends the S-Plus command
+source(\"filename\") to S. This version does not guarantee to save .Last.value,
+nor offer alternate buffers or editing capability."
+ (let ((source-buffer (get-file-buffer filename)))
+ (if (ess-check-source filename)
+ (error "Buffer %s has not been saved" (buffer-name source-buffer))
+ ;; Find the process to load into
+ (if source-buffer
+ (with-current-buffer source-buffer
+ (ess-force-buffer-current "Process to load into: ")
+ ;; (ess-check-modifications) ;;; not possible with ddeclient
+ ;; it calls ess-command which requires two-way communication
+ ;; with the S-Plus process
+ )))
+ (ess-dde-eval-linewise (format ess-load-command filename)))
+ (widen))
+
+
+;; C-c C-d
+(defun ess-dde-dump-object (object filename)
+ "Dump the ESS object OBJECT into file FILENAME."
+ (ess-force-buffer-current "Process to load into: ")
+ (ess-dde-eval-linewise (concat "dump('" object "','" filename "')"))
+ (sleep-for 5)
+ (find-file filename)
+ (widen))
+
+(defun ess-dde-read-object-name (p-string)
+ (read-string "Object to edit: "))
+
+(defun ess-dput-expression-ddeclient (object filename)
+ "Dump the ESS object found by evaluating OBJECT into file FILENAME."
+ (ess-force-buffer-current "Process to load into: ")
+ (ess-dde-eval-linewise (concat "dput(" object ",'" filename "')"))
+ (sleep-for 2)
+ (find-file filename))
+
+(defun ess-command-ddeclient-proposed (com &optional buf sleep)
+ "ddeclient version of real `ess-command'.
+Send the ESS process command COM and redirect its output to the
+temporary file named BUF. The temporary filename is constructed
+in emacs, not in the ESS process. The default name for the
+temporary buffer is \"ess-temp.st\". The function waits
+SLEEP (which defaults to 1) seconds and then brings the temporary
+file into an emacs buffer and displays it."
+ (let (filename bufname)
+ (if (not buf) (setq buf "ess-temp.st"))
+ (if (not sleep) (setq sleep 1))
+ (setq filename (concat (file-name-as-directory (getenv "TEMP")) buf))
+ (ess-dde-eval-linewise
+ (concat ".old.Last.value <- .Last.value; sink('"
+ filename
+ "'); print("
+ com
+ "); sink(); .Last.value <- .old.Last.value"))
+ (setq bufname (ess-get-file-or-buffer filename)) ;; must follow the eval
+ (sleep-for sleep)
+ (if (not bufname)
+ (find-file filename)
+ (switch-to-buffer bufname))
+ (revert-buffer t t) ;; this allows the user to reuse the BUF name
+ ))
+
+;; previous version (ESS-5.2.12 and earlier)
+(defun ess-dde-command (com &optional buf sleep)
+ "ddeclient bypass of real ess-command"
+ (ess-eval-linewise com))
+
+(provide 'ess-dde)
+
+;;; ess-dde.el ends here
--- /dev/null
+This is ess-defs.info, produced by makeinfo version 6.5 from
+ess-defs.texi.
+
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+;;; ess-font-lock.el --- font-lock color options
+
+;; Copyright (C) 2000--2006 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; 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 <David.BrahmNOSPAMfmr.com>"
+ ;; 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
--- /dev/null
+;;; ess-generics.el --- Mode-generic functions
+;;
+;; Copyright (C) ESS-core <ESS-coreNOSPAMr-project.org>
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+;;
+;; 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/
+;;
+;;; Comment
+;;
+;; Define generic method with `ess-defgeneric' and dialect specific override with
+;; `ess-defmethod`. Current implementation is using `{name}-function' and
+;; `ess-customize-alist' as the backbone mechanism. This might change in the
+;; future.
+;;
+;;; Code
+
+(defun ess-generics--override (name args body)
+ (let ((funname (intern (format "%s-function" name)))
+ (arg-list (delq '&rest (delq '&optional (copy-alist args)))))
+ `(if (fboundp ,funname)
+ ,(if (memq '&rest args)
+ `(apply ,funname ,@arg-list)
+ `(funcall ,funname ,@arg-list))
+ ,@(or body
+ `((error (format "`%s' is not implemented for dialect `%s'"
+ ',name ess-dialect)))))))
+
+(defun ess-generics--expand-overrides (name args body)
+ ;; ripped off from `mode-local--expand-overrides'
+ (let ((forms body)
+ (ditto t)
+ form xbody)
+ (while forms
+ (setq form (car forms))
+ (cond
+ ((atom form))
+ ((eq (car form) :override)
+ (setq form (ess-generics--override name args (cdr form))))
+ ((eq (car form) :override-with-args)
+ (setq form (ess-generics--override name (cadr form) (cddr form))))
+ ((setq form (ess-generics--expand-overrides name args form))))
+ (setq ditto (and ditto (eq (car forms) form))
+ xbody (cons form xbody)
+ forms (cdr forms)))
+ (if ditto body (nreverse xbody))))
+
+;;;###autoload
+(defmacro ess-defgeneric (name args docstring &rest body)
+ "Define a new function, as with `defun', which can be overloaded.
+NAME is the name of the function to create. ARGS are the
+arguments to the function. DOCSTRING is a documentation string to
+describe the function. The docstring will automatically have
+details about its overload symbol appended to the end. BODY is
+code that would be run when there is no override defined. The
+default is to signal error if {name}-function is not defined."
+ (declare (doc-string 3) (indent defun) (debug defun))
+ (let ((funname (intern (format "%s-function" name))))
+ `(eval-and-compile
+ (defvar-local ,funname nil ,(format "When defined this function is called by `%s'." name))
+ (defun ,name ,args ,(format "%s\n\nUse `ess-defmethod' to define dialect specific overrides." docstring)
+ ,@(ess-generics--expand-overrides name args body)))))
+
+(defmacro ess-defmethod (dialect name args &rest body)
+ "Define a dialect specific override of the method NAME.
+If NAME wasn't created with `ess-defgeneric' signal an
+error. DIALECT is the dialect name this override is being defined
+for. ARGS are the function arguments, which should match those of
+the same named function created with `ess-defgeneric'. BODY is the
+implementation of this function."
+ (declare (indent defun) (debug (&define sexp sexp lambda-list def-body)))
+ (let ((new-name (intern (format "%s:%s" name dialect)))
+ (fun-name (intern (format "%s-function" name)))
+ (alist-name (intern (downcase (format "ess-%s-customize-alist" dialect)))))
+ `(eval-and-compile
+ (unless (boundp ',alist-name)
+ (defvar ,alist-name nil
+ ,(format "Variables to customize dialect '%s'." dialect)))
+ (add-to-list ',alist-name
+ '(,fun-name . ',new-name))
+ (defun ,new-name ,args
+ ,(format "%s\nThis is an override for `%s' for `%s' dialect."
+ ;; fixme: NAME might be undefined as yet. Look at help-fns-describe-function-functions
+ (or (and (fboundp name)
+ (documentation name)
+ ;; hackish
+ (replace-regexp-in-string "\nUse.*ess-defmethod.*\\." "" (documentation name)))
+ "")
+ name dialect)
+ ;; The body for this implementation
+ ,@body)
+ ;; For find-func to locate the definition of NEW-NAME.
+ (put ',new-name 'definition-name ',name))))
+
+
+
+(provide 'ess-generics)
--- /dev/null
+;; ess-gretl.el --- ESS gretl mode and inferior interaction
+;;
+;; Copyright (C) 2012 Allin Cottrell
+;; Copyright (C) 2012 Ahmadou DICKO
+;; Copyright (C) 2013 ESS core team
+;;
+;; Filename: ess-gretl.el
+;; Author: Ahmadou DICKO, Spinu Vitalie and Allin Cottrell (based on ess-julia.el and gretl.el)
+;; Maintainer: Ahmadou DICKO
+;; Created: 01-10-2012 (ESS 12.09)
+;; Keywords: ESS, gretl, econometrics
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+
+;; This file is *NOT* part of GNU Emacs.
+;; This file is *NOT YET* 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, 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:
+;; start the inferior with M-x gretl.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+(require 'compile); for compilation-* below
+(require 'ess-r-mode)
+
+
+;;; Code:
+(defvar gretl-mode-hook nil)
+(add-to-list 'auto-mode-alist '("\\.inp$" . 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 `gretl-mode'.")
+
+;; syntax table that holds within strings
+(defvar gretl-mode-string-syntax-table
+ (let ((table (make-syntax-table)))
+ table)
+ "Syntax table for `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"
+ "funcerr" "return" "while" "elif" "const" "3sls" "liml" "fiml"
+ "sur" "params" "deriv" "orthog" "weights" "series" "scalar" "genr")
+ "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" "autocorr" "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)
+ ; (save-excursion
+ (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)))
+
+
+(defvar gretl-editing-alist
+ '((paragraph-start . (concat "\\s-*$\\|" page-delimiter))
+ (paragraph-separate . (concat "\\s-*$\\|" page-delimiter))
+ (paragraph-ignore-fill-prefix . t)
+ (require-final-newline . mode-require-final-newline)
+ (comment-start . "# ")
+ (comment-add . 1)
+ (comment-start-skip . "\\s<+\\s-*")
+ (comment-column . 40)
+ ;;(comment-indent-function . 'S-comment-indent)
+ ;;(ess-comment-indent . 'S-comment-indent)
+ ;;(ess-indent-line . 'S-indent-line)
+ (ess-calculate-indent . 'ess-calculate-indent)
+ (ess-indent-line-function . 'gretl-indent-line)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style) ;; ignored
+ (ess-local-process-name . nil)
+ ;;(ess-keep-dump-files . 'ask)
+ (ess-mode-syntax-table . gretl-syntax-table)
+ ;; (add-log-current-defun-header-regexp . "^.*function[ \t]*\\([^ \t(]*\\)[ \t]*(")
+ )
+ "General options for gretl source files.")
+
+
+;; (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)
+ (with-current-buffer (ess-command command)
+ (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)))
+
+(defun gretl-get-help-topics-function (name)
+ (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")
+ (gretl--get-words-from-command "help functions\n" "Accessors:" "^Functions")
+ (gretl--get-words-from-command "help functions\n" "^Functions" "^For")
+ )))
+
+;; (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-get-help-topics-function . 'gretl-get-help-topics-function)
+ (font-lock-defaults . '(gretl-font-lock-keywords))
+ (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-mode-syntax-table . gretl-syntax-table)
+ (ess-mode-editing-alist . gretl-editing-alist)
+ (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-help-filetype . nil)
+ (inferior-ess-exit-command . "exit\n")
+ ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
+ (inferior-ess-start-file . nil) ;; "~/.ess-R"
+ (inferior-ess-start-args . "")
+ (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.
+These arguments are currently not passed to other versions of gretl that have
+been created using the variable `ess-r-versions'."
+ :group 'ess-gretl
+ :type 'string)
+
+;;;###autoload
+(defun gretl-mode (&optional proc-name)
+ "Major mode for editing gretl source. See `ess-mode' for more help."
+ (interactive "P")
+ ;; (setq ess-customize-alist gretl-customize-alist)
+ ;;(setq imenu-generic-expression R-imenu-generic-expression)
+ (ess-mode gretl-customize-alist proc-name)
+ ;; for emacs < 24
+ ;; (add-hook 'comint-dynamic-complete-functions 'ess-complete-object-name nil 'local)
+ ;; for emacs >= 24
+ ;; (remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
+ ;; (add-hook 'completion-at-point-functions 'ess-object-completion nil 'local)
+ ;; (add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
+ (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
+ (set (make-local-variable 'end-of-defun-function) 'ess-end-of-function)
+ ;; (local-set-key "\t" 'gretl-indent-line) ;; temp workaround
+ ;; (set (make-local-variable 'indent-line-function) 'gretl-indent-line)
+ ;; (ess-imenu-gretl)
+ (run-mode-hooks 'gretl-mode-hook))
+
+
+(defvar ess-gretl-post-run-hook nil
+ "Functions run in process buffer after the initialization of
+ Gretl process.")
+
+
+
+;;;###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")
+ (setq ess-customize-alist gretl-customize-alist)
+ (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))))
+ (inferior-ess r-start-args)
+ (set (make-local-variable 'indent-line-function) 'gretl-indent-line)
+ (set (make-local-variable '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-ess-process-buffer nil
+ (run-mode-hooks 'ess-gretl-post-run-hook))
+ ))
+
+
+;;;; 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)
+;; (provide 'ess-gretl)
+
+(provide 'ess-gretl)
+
+;;; ess-gretl.el ends here
--- /dev/null
+;;; ess-help.el --- Support for viewing ESS help files
+
+;; Copyright (C) 1989-1994, 2017 Bates, Kademan, Ritter and Smith
+;; Copyright (C) 1997, A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Copyright (C) 1998--2001 A.J. Rossini, Martin Maechler, Kurt Hornik and
+;; Richard M. Heiberger <rmhNOSPAMtemple.edu>.
+;; 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 <dsmithNOSPAMstats.adelaide.edu.au>
+;; Created: 7 Jan 1994
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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.<LANGUAGE> where
+;; <LANGUAGE> is one of `S', `SAS', `Stata'or `XLispStat'.
+
+;;; Code:
+
+\f ; Requires and autoloads
+(require 'cl-lib)
+(eval-when-compile
+ (require 'tramp)
+ (require 'reporter))
+(require 'info)
+(require 'ess-mode)
+(require 'ess-inf)
+(require 'ess-utils)
+
+(defvar ess--help-frame nil
+ "Stores the frame used for displaying R help buffers.")
+
+\f ; ess-help-mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; In this section:
+;;;;
+;;;; * The function ess-display-help-on-object
+;;;; * The major 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 ess-help-type nil
+ "Type of help file, help, index, vingettes etc.
+Local in `ess-help' buffers.")
+(make-variable-buffer-local 'ess-help-type)
+
+(defvar 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.")
+(make-variable-buffer-local 'ess-help-object)
+
+;;;###autoload
+(defun ess-display-help-on-object (object &optional command)
+ "Display documentation for OBJECT in another window.
+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
+suplied, 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"))))
+ (if (fboundp ess-display-help-on-object-function)
+ (funcall ess-display-help-on-object-function object command)
+ (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)
+ current-prefix-arg
+ (ess--help-get-bogus-buffer-substring old-hb-p))
+ (ess-with-current-buffer tbuffer
+ (setq ess-help-object object
+ ess-help-type 'help)
+ (setq buffer-read-only t)
+ (ess--flush-help-into-current-buffer object command)))
+ (unless (ess--help-kill-bogus-buffer-maybe tbuffer)
+ (ess--switch-to-help-buffer tbuffer)))))
+
+;;;###autoload
+(defalias 'ess-help 'ess-display-help-on-object)
+
+(defun ess-build-help-command (object)
+ (if (fboundp ess-build-help-command-function)
+ (funcall ess-build-help-command-function object)
+ ;; TODO-CLEANUP: Remove the inferior- prefix for consistency
+ (format inferior-ess-help-command object)))
+
+(defun ess--flush-help-into-current-buffer (object &optional command dont-ask)
+ (let ((inhibit-modification-hooks t)
+ (inhibit-read-only t))
+ (delete-region (point-min) (point-max))
+ (ess-help-mode)
+ (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)
+ (setq truncate-lines 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 subproces
+ ;; 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."
+ (interactive)
+ (let* ((string (button-label button))
+ (command (when (fboundp ess-build-help-command-function)
+ (funcall ess-build-help-command-function string))))
+ (ess-display-help-on-object string command)))
+
+(defun ess-display-package-index ()
+ "Prompt for package name and display its index."
+ (interactive)
+ (let ((object (buffer-name))
+ (alist ess-local-customize-alist)
+ (pname ess-local-process-name)
+ pack buff all-packs not-implemented
+ ;; Available customization for ess languages/dialects:
+ com-package-for-object ;command to get the package of current help object
+ com-packages ;command to get a list of available packages (REQUIRED)
+ com-package-index ;command to get the package index (REQUIRED)
+ reg-keyword ;regexp used to find keywords for linking in index listing
+ ; only (1st subexpression is used)
+ reg-start ;regexp from where to start searching for keywords in index listing
+ )
+ (cond
+ ((string-match "^R" ess-dialect)
+ ;; carefully using syntax to be parsed in old R versions (no '::', '_'):
+ (setq com-package-for-object "sub('package:', '', .ess.findFUN('%s'))\n"
+ com-packages ".packages(all.available=TRUE)\n"
+ com-package-index ".ess.help(package='%s', help.type='text')\n"
+ reg-keyword "^\\([^ \t\n:]+\\)"
+ reg-start "^Index:"))
+ ((string-match "julia" ess-dialect)
+ (setq com-packages "_ess_list_categories()\n"
+ com-package-index "_ess_print_index(\"%s\")\n"
+ reg-keyword "^\\(.*+\\):$*"
+ reg-start ":"
+ ))
+ (t (error "Not implemented for %s " ess-dialect)))
+ (when (and com-package-for-object
+ ess-help-object
+ (eq ess-help-type 'help))
+ (setq pack (car (ess-get-words-from-vector
+ (format com-package-for-object ess-help-object)))))
+ (setq all-packs (ess-get-words-from-vector com-packages))
+ (unless pack ;try symbol at point
+ (setq pack (car (member (ess-read-object-name-default) all-packs))))
+ (setq pack (ess-completing-read "Index of"
+ all-packs nil nil nil nil pack))
+ (ess--display-indexed-help-page
+ (format com-package-index pack)
+ reg-keyword
+ (format "*help[%s](index:%s)*" ess-dialect pack)
+ 'index nil nil reg-start pack)))
+
+(defalias 'ess-display-index 'ess-display-package-index)
+(make-obsolete 'ess-display-index 'ess-display-package-index "ESS[12.09]")
+
+(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
+ ;; REG-START gives the start location from where to search linkifying"
+ (interactive)
+ (let ((inhibit-modification-hooks t)
+ (object (buffer-name))
+ (alist ess-local-customize-alist)
+ (pname ess-local-process-name)
+ (buff (get-buffer-create title)))
+ (with-current-buffer buff
+ (setq ess-help-object help-object)
+ (ess-setq-vars-local (eval alist))
+ (setq ess-help-sec-regex "\\(^\\s-.*\n\\)\\|\\(^\n\\)"
+ ess-local-process-name pname)
+ (setq buffer-read-only nil)
+ (delete-region (point-min) (point-max))
+ (ess-help-mode)
+ (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 places all these spaces?
+ ;; (goto-char (point-min))
+ ;; (while (re-search-forward " \\{10,\\} *" nil t)
+ ;; (replace-match "\t\t\t")))
+ (setq buffer-read-only t)
+ (setq ess-help-type help-type)
+ (setq truncate-lines nil))
+ (unless (ess--help-kill-bogus-buffer-maybe buff)
+ (ess--switch-to-help-buffer 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."
+ (interactive)
+ (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")
+ (cond
+ ((equal ess-dialect "R") (ess-R-display-vignettes all))
+ (t (message "Sorry, not implemented for %s" ess-dialect))))
+
+(defun ess-R-display-vignettes (&optional all)
+ "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."
+ (interactive "P")
+ (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))
+ (with-current-buffer buff
+ (setq buffer-read-only nil)
+ (delete-region (point-min) (point-max))
+ (ess-setq-vars-local (eval alist))
+ (setq ess-help-sec-regex "^\\w+:$"
+ ess-help-type 'vignettes
+ ess-local-process-name proc-name)
+ (ess-help-mode)
+ (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--switch-to-help-buffer buff)))
+
+(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-command (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--find-displayed-help-window ()
+ (catch 'win
+ (dolist (f (frame-list))
+ (when (frame-visible-p f)
+ (dolist (w (window-list f))
+ (when (eq (buffer-local-value 'major-mode (window-buffer w))
+ 'ess-help-mode)
+ (throw 'win w)))))))
+
+(defun ess--switch-to-help-buffer (buff)
+ "Switch to an ESS help BUFF.
+For internal use. Take into account variable `ess-help-own-frame'."
+ (if (eq ess-help-own-frame t)
+ ;; 0) always pop new frame
+ (let* ((frame (make-frame ess-help-frame-alist))
+ (action `(display-buffer-same-window (reusable-frames . ,frame))))
+ (ess--display-help buff frame action))
+ (let ((help-win (or
+ ;; if this doc is already displayed, reuse
+ (get-buffer-window buff 'all-frames)
+ ;; if help window visible, reuse
+ (and ess-help-reuse-window
+ (ess--find-displayed-help-window)))))
+ (cond
+ ;; 1) existent help window lying somewhere; reuse
+ (help-win
+ (set-window-buffer help-win buff)
+ (let ((action '(display-buffer-reuse-window (reusable-frames . t))))
+ (ess--display-help buff nil action)))
+ ;; 2)
+ ((eq ess-help-own-frame 'one)
+ (let* ((frame (if (frame-live-p ess--help-frame)
+ ess--help-frame
+ (make-frame ess-help-frame-alist)))
+ (action `(display-buffer-same-window (reusable-frames . ,frame))))
+ (setq ess--help-frame frame)
+ (ess--display-help buff frame action)))
+ ;; 3) display help in other window
+ (t
+ (ess--display-help buff))))))
+
+(defun ess--display-help (buff &optional frame action)
+ (let ((action (or action `(nil (reusable-frames . ,(or frame ess-display-buffer-reuse-frames))))))
+ (when (and (framep frame)
+ (not (eq (selected-frame) frame)))
+ ;; VS[04-05-2018]: `display-buffer` framework has no satisfactory
+ ;; functionality to display buffers in selected windows. So, do some extra
+ ;; frame selection here.
+ (raise-frame frame)
+ (if ess-help-pop-to-buffer
+ (select-frame-set-input-focus frame)
+ (select-frame frame)))
+ (if ess-help-pop-to-buffer
+ (pop-to-buffer buff action)
+ (display-buffer buff action))))
+
+(defun ess-help-web-search ()
+ "Search the web for documentation."
+ (interactive)
+ (ess-execute-dialect-specific ess-help-web-search-command "Search for: "))
+
+(defun ess-manual-lookup ()
+ "Search manual for topic."
+ (interactive)
+ (ess-execute-dialect-specific ess-manual-lookup-command ))
+
+(defun ess-reference-lookup ()
+ "Search manual for topic."
+ (interactive)
+ (ess-execute-dialect-specific ess-reference-lookup-command))
+
+(defvar ess-help-sec-map nil "Sub-keymap for ESS help mode.")
+;; this breaks "s ?" rather than to fix any (unbroken !) thing:
+;; (make-variable-buffer-local 'ess-help-sec-map)
+
+(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)
+ (define-key ess-doc-map "\C-r" 'ess-reference-lookup)
+ (define-key ess-doc-map "r" 'ess-reference-lookup)
+ ess-doc-map
+ )
+ "ESS documentation map.")
+
+
+(defvar ess-help-mode-map
+ (let ((map (make-keymap))); Full keymap, in order to
+ (suppress-keymap map) ; suppress all usual "printing" characters
+ (when (boundp 'special-mode-map)
+ (set-keymap-parent map (make-composed-keymap
+ button-buffer-map
+ special-mode-map)))
+ (define-key map "q" 'quit-window)
+ (define-key map "\C-m" 'next-line)
+ ;; (define-key map "s" ess-help-sec-map)
+ (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)
+ ;; TODO: `electric mouse-2'
+ ;; (define-key map [mouse-2] 'ess-display-help-on-object)
+ (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 "?" 'ess-describe-help-mode)
+ ;;-- those should be "inherited" from ess-mode-map ( ./ess-mode.el )
+ (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 <TEACH> 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]
+ ["Describe ESS-help Mode" ess-describe-help-mode t])
+ "Menu used in `ess-help-mode'.")
+
+(defun ess-help-mode ()
+;;; Largely ripped from more-mode.el,
+;;; originally by Wolfgang Rupprecht wolfgangNOSPAMmgm.mit.edu
+ "Mode for viewing ESS help files.
+Use SPC and DEL to page back and forth through the file.
+Use `n' and `p' to move to next and previous section,
+ `s' to jump to a particular section; `s ?' for help.
+Use `q' to return to your ESS session; `x' to kill this buffer first.
+The usual commands for evaluating ESS source are available.
+Other keybindings are as follows:
+\\{ess-help-mode-map}"
+ (interactive)
+ (setq major-mode 'ess-help-mode)
+ (setq mode-name "ESS Help")
+ (setq font-lock-mode nil)
+ (use-local-map ess-help-mode-map)
+ ;;; Keep <tabs> out of the code.
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+ (if ess-mode-syntax-table ;;set in advance by ess-setq-local
+ (set-syntax-table ess-mode-syntax-table))
+ (require 'easymenu)
+ (easy-menu-define ess-help-mode-menu-map ess-help-mode-map
+ "Menu keymap for ess-help mode." ess-help-mode-menu)
+ ;; Add the keys for navigating among sections; this is done
+ ;; dynamically since different languages (e.g. S vs R) have different
+ ;; section headings.
+ (setq ess-help-sec-map (make-sparse-keymap))
+ (setq-local show-trailing-whitespace nil)
+ (dolist (pair ess-help-sec-keys-alist)
+ (define-key ess-help-sec-map (char-to-string (car pair))
+ 'ess-skip-to-help-section))
+ (define-key ess-help-sec-map "?" 'ess-describe-sec-map)
+ (define-key ess-help-sec-map ">" 'end-of-buffer)
+ (define-key ess-help-sec-map "<" 'beginning-of-buffer)
+ (define-key ess-help-mode-map "s" ess-help-sec-map)
+ (run-mode-hooks 'ess-help-mode-hook))
+
+\f
+;;*;; User commands defined in ESS help mode
+
+(defun ess-skip-to-help-section nil
+ "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))
+ (goto-char (point-min))
+ (let ((the-sec (cdr (assoc last-command-event ess-help-sec-keys-alist))))
+ (if (not the-sec) (error "Invalid section key: %c"
+ last-command-event)
+ (if (re-search-forward (concat "^" the-sec) nil t)
+ (recenter)
+ (message "No %s section in this help. Sorry." the-sec)
+ (goto-char old-point))))))
+
+(defun ess-skip-to-next-section nil
+ "Jump to next section in ESS help buffer."
+ (interactive)
+ (let ((case-fold-search nil))
+ (if (re-search-forward ess-help-sec-regex nil 'no-error) nil
+ (message "No more sections."))))
+
+(defun ess-skip-to-previous-section nil
+ "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) nil
+ (message "No previous section."))))
+
+(defun ess-describe-help-mode nil
+ "Display help for `ess-mode'."
+ (interactive)
+ (describe-function 'ess-help-mode))
+
+(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"))
+ (insert "\nFull list of key definitions:\n"
+ (substitute-command-keys
+ "\\{ess-help-sec-map}")))))
+
+(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))
+
+;;;###autoload
+(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)))
+
+(defun ess-find-help-file (p-string)
+ "Find help, prompting for P-STRING.
+Note that we can't search SAS, Stata or XLispStat for additional information."
+ (ess-make-buffer-current)
+ (cond
+ ((fboundp ess-find-help-file-function)
+ (funcall ess-find-help-file-function p-string))
+ ;; Fixme: Are `ess-find-help-file-function' and
+ ;; `ess-get-help-topics-function' redundant?
+ ((fboundp ess-get-help-topics-function)
+ (let* ((help-files-list (funcall ess-get-help-topics-function ess-current-process-name))
+ (hlpobjs (ess-helpobjs-at-point help-files-list)))
+ (ess-completing-read p-string (append (delq nil hlpobjs) help-files-list)
+ nil nil nil nil (car hlpobjs))))
+ (t
+ (read-string (format "%s: " p-string)))))
+
+\f
+;;*;; 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 "_\b" nil t)
+ (backward-delete-char 2)
+ (put-text-property (point) (1+ (point)) 'face 'underline))))
+
+;;*;; Link to Info
+;;;###autoload
+(defun ess-goto-info (node)
+ "Display node NODE from `ess-mode' info."
+ (require 'info)
+ (split-window)
+ ;;(other-window 1)
+ (Info-goto-node (concat "(ess)" node)))
+
+\f
+;; describe object at point
+
+(defvar ess-describe-object-at-point-commands nil
+ "Commands cycled by `ess-describe-object-at-point'.
+Dialect specific.")
+(make-variable-buffer-local 'ess-describe-at-point-commands)
+
+(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)))
+ bs 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)
+ (local-set-key "k" 'kill-this-buffer))
+ (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)))
+
+\f
+;;; Bug Reporting
+
+;;;###autoload
+(defun ess-submit-bug-report ()
+ "Submit a bug report to the ESS maintainers."
+ (interactive)
+ (require 'ess-mode)
+ (require 'reporter)
+ (let ((reporter-prompt-for-summary-p 't))
+ (reporter-submit-bug-report
+ "ess-bugsNOSPAMr-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))))))))
+
+
+(provide 'ess-help)
+;;; ess-help.el ends here
--- /dev/null
+;;; ess-inf.el --- Support for running S as an inferior Emacs process
+
+;; Copyright (C) 1989-1994 Bates, Kademan, Ritter and Smith
+;; Copyright (C) 1997-1999 A.J. Rossini <rossiniNOSPAMu.washington.edu>,
+;; Martin Maechler <maechlerNOSPAMstat.math.ethz.ch>.
+;; 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 <dsmithNOSPAMstats.adelaide.edu.au>
+;; Created: 7 Jan 1994
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+\f ; Requires and autoloads
+(eval-when-compile
+ (require 'tramp))
+(require 'ess-generics)
+(require 'ess-utils)
+(require 'newcomment)
+(require 'comint)
+(require 'overlay)
+(require 'compile)
+(require 'format-spec)
+(require 'ess-tracebug)
+
+;; 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")
+(declare-function tramp-dissect-file-name "tramp")
+(declare-function tramp-tramp-file-p "tramp")
+
+;; TODO: refactor and remove file-local variable
+;; byte-compile-warnings. See ess-r-mode.el also
+(defvar proc)
+(defvar start)
+(defvar end)
+
+\f ;;*;; 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
+;;;###autoload
+(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)))))
+
+;;;###autoload
+(defun inferior-ess (&optional ess-start-args customize-alist 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
+ESS-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'.
+An initialization file (dumped into the process) is specified by
+`inferior-ess-start-file', and `inferior-ess-start-args' is used
+to accompany the call for `inferior-ess-program'.
+
+When creating a new process, the process buffer replaces the
+current window if `inferior-ess-same-window' is non-nil.
+Alternatively, it can appear in its own frame if
+`inferior-ess-own-frame' is non-nil.
+
+\(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.
+
+ ;; Once, long ago, it was used for switching buffers, but we don't
+ ;; do that any more (at least not from here).
+
+ (interactive)
+
+ (let* ((ess-customize-alist (or customize-alist
+ ess-customize-alist))
+ (temp-ess-dialect (eval (cdr (assoc 'ess-dialect
+ ess-customize-alist))))
+ (temp-ess-lang (eval (cdr (assoc 'ess-language
+ ess-customize-alist)))))
+
+ (run-hooks 'ess-pre-run-hook)
+ (ess-write-to-dribble-buffer
+ (format "(inf-ess 1): lang=%s, dialect=%s, tmp-dialect=%s, buf=%s\n"
+ ess-language ess-dialect temp-ess-dialect (current-buffer)))
+ (let* ((process-environment process-environment)
+ ;; Use temp-ess-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 temp-ess-dialect "R")
+ (file-name-nondirectory inferior-ess-r-program)
+ temp-ess-dialect)
+ temp-ess-dialect))
+ (temp-lang temp-ess-lang)
+ ;; Find the next non-existent process N (*R:N*)
+ (procname (let ((ntry 1))
+ (while (get-process (ess-proc-name ntry temp-dialect))
+ (setq ntry (1+ ntry)))
+ (ess-proc-name ntry temp-dialect)))
+ (buf-name-str (funcall ess-gen-proc-buffer-name-function procname))
+ (cur-dir (inferior-ess--maybe-prompt-startup-directory procname temp-dialect))
+ (default-directory cur-dir)
+ buf method)
+ (ess-write-to-dribble-buffer
+ (format "(inf-ess 1.1): procname=%s temp-dialect=%s, buf-name=%s \n"
+ procname temp-dialect buf-name-str))
+
+ (cond
+ ;; 1) try to use current buffer, if inferior-ess-mode but no process
+ ((and (not (comint-check-proc (current-buffer)))
+ (eq major-mode 'inferior-ess-mode))
+ (setq buf (current-buffer))
+ ;; don't change existing buffer name in this case; It is very
+ ;; commong to restart the process in the same buffer.
+ (setq buf-name-str (buffer-name))
+ (setq method 1))
+
+ ;; 2) Take the *R:N* buffer if already exists (and contains dead proc!)
+ ;; fixme: buffer name might have been changed, iterate over all
+ ;; inferior-ess buffers
+ ((get-buffer buf-name-str)
+ (setq buf (get-buffer buf-name-str))
+ (setq method 2))
+
+ ;; 3) Pick up a transcript file or create a new buffer
+ (t
+ (setq buf (if ess-ask-about-transfile
+ (let ((transfilename (read-file-name "Use transcript file (default none):"
+ cur-dir
+ "")))
+ (if (string= transfilename "")
+ (get-buffer-create buf-name-str)
+ (find-file-noselect (expand-file-name transfilename))))
+ (get-buffer-create buf-name-str)))
+ (setq method 3)))
+
+ (ess-write-to-dribble-buffer
+ (format "(inf-ess 2.0) Method #%d start=%s buf=%s\n" method cur-dir buf))
+
+ (set-buffer buf)
+ (set 'default-directory cur-dir)
+ (ess-setq-vars-local ess-customize-alist)
+
+ (ess-write-to-dribble-buffer
+ (format "(inf-ess 2.1): ess-language=%s, ess-dialect=%s buf=%s \n"
+ ess-language ess-dialect (current-buffer)))
+
+ (let* ((infargs (or ess-start-args
+ inferior-ess-start-args))
+ (proc (get-process procname)))
+ ;; If ESS process NAME is running, switch to it
+ (if (and proc (comint-check-proc (process-buffer proc)))
+ (progn ;; fixme: when does this happen? -> log:
+ (ess-write-to-dribble-buffer (format "(inf-ess ..): popping to proc\n"))
+ (pop-to-buffer (process-buffer proc)))
+
+ ;; Otherwise, crank up a new process
+ (let* ((symbol-string
+ (concat "inferior-" inferior-ess-program "-args"))
+ (switches-symbol (intern-soft symbol-string))
+ (switches
+ (when (and switches-symbol (boundp switches-symbol))
+ (symbol-value switches-symbol))))
+
+ (inferior-ess-mode)
+ (ess-write-to-dribble-buffer
+ (format "(inf-ess 3.0): prog=%s, start-args=%s, echoes=%s\n"
+ inferior-ess-program infargs comint-process-echoes))
+ (setq ess-local-process-name procname)
+ (goto-char (point-max))
+
+ (when ess-history-file
+ ;; Load past history
+ (when (eq t ess-history-file)
+ (setq-local ess-history-file (concat "." ess-dialect "history")))
+ (let ((histfile (expand-file-name ess-history-file
+ (or ess-history-directory cur-dir))))
+ (when (file-readable-p histfile)
+ (setq comint-input-ring-file-name histfile)
+ (comint-read-input-ring))))
+
+ (with-current-buffer buf
+ (rename-buffer buf-name-str t))
+
+ ;; before the start, display the buffer depending on user settings:
+ (cond (inferior-ess-own-frame
+ (progn
+ (make-frame inferior-ess-frame-alist)
+ (switch-to-buffer buf)))
+ (inferior-ess-same-window
+ (switch-to-buffer buf))
+ (t (pop-to-buffer buf)))
+
+ ;; create the process
+ (setq buf
+ (if switches
+ (inferior-ess-make-comint buf-name-str
+ procname
+ infargs
+ switches)
+ (inferior-ess-make-comint buf-name-str
+ procname
+ infargs)))
+
+ (set-buffer buf)
+ (set 'default-directory cur-dir)
+
+ (setq proc (get-buffer-process buf))
+
+ ;; set the process sentinel to save the history
+ (set-process-sentinel proc 'ess-process-sentinel)
+ ;; add this process to ess-process-name-list, if needed
+ (let ((conselt (assoc procname ess-process-name-list)))
+ (unless conselt
+ (setq ess-process-name-list
+ (cons (cons procname nil) ess-process-name-list))))
+ (ess-make-buffer-current)
+ (goto-char (point-max))
+ (setq ess-sl-modtime-alist nil)
+
+ ;; add the process filter to catch certain output
+ (set-process-filter proc 'inferior-ess-output-filter)
+ (inferior-ess-mark-as-busy proc)
+
+ (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" procname))
+
+ ;; don't font-lock strings over process prompt
+ (set (make-local-variable 'syntax-begin-function) ;; fixme: obsolete in emacs 25.1
+ #'inferior-ess-last-prompt-end)
+ (set (make-local-variable 'font-lock-fontify-region-function)
+ #'inferior-ess-fontify-region)
+
+ (when ess-setwd-command
+ (ess-set-working-directory cur-dir))
+
+ (run-hooks 'ess-post-run-hook)
+ (ess-load-extras t)
+
+ ;; 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))))))))
+
+(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 inferior-ess-objects-command nil
+ "The language/dialect specific command for listing objects.
+It is initialized from the corresponding inferior-<lang>-objects-command
+and then made buffer local."); and the *-<lang>-* ones are customized!
+(make-variable-buffer-local 'inferior-ess-objects-command)
+
+(defvar 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")
+(make-variable-buffer-local 'ess-save-lastvalue-command)
+
+(defvar 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")
+(make-variable-buffer-local 'ess-retr-lastvalue-command)
+
+(defun inferior-ess-last-prompt-end (&optional pos limit)
+ "Move to the end of last prompt from POS, but not further than LIMIT."
+ (let ((pos (or pos (point))))
+ (goto-char pos)
+ (end-of-line)
+ (when (re-search-backward inferior-ess-prompt limit t)
+ (goto-char (match-end 0)))))
+
+(defvar compilation--parsed)
+(defvar ess--tb-last-input)
+(defvar compilation--parsed)
+(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)
+ (buff (current-buffer))
+ (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:projectile-or-simple (proc-name)
+ "Function to generate buffer name in the form *PROC-NAME:PROJECTILE-ROOT*.
+PROC-NAME is a string representing an internal process
+name. PROJECTILE-ROOT is directory name returned by
+`projectile-project-p' if defined. If
+`projectile-project-p' is undefined or no project directory
+has been found use `ess-gen-proc-buffer-name:simple'. See
+`ess-gen-proc-buffer-name-function'."
+ (let ((proj (and (fboundp 'projectile-project-p)
+ (projectile-project-p))))
+ (if proj
+ (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:projectile-or-directory (proc-name)
+ "Function to generate buffer name in the form *PROC-NAME:PROJECTILE-ROOT*.
+PROC-NAME is a string representing an internal process
+name. PROJECTILE-ROOT is directory name returned by
+`projectile-project-p' if defined. If
+`projectile-project-p' is undefined, or no project directory
+has been found, use `ess-gen-proc-buffer-name:directory'. See
+`ess-gen-proc-buffer-name-function'."
+ (let ((proj (and (fboundp 'projectile-project-p)
+ (projectile-project-p))))
+ (if proj
+ (format "*%s:%s*" proc-name (file-name-nondirectory
+ (directory-file-name proj)))
+ (ess-gen-proc-buffer-name:directory proc-name))))
+
+(defun inferior-ess-set-status (proc string &optional no-timestamp)
+ "Internal function to set the satus of the PROC.
+If no-timestamp, don't set the last-eval timestamp.
+Return the 'busy state."
+ ;; todo: do it in one search, use starting position, use prog1
+ (let ((busy (not (string-match (concat "\\(" inferior-ess-primary-prompt "\\)\\'") string))))
+ (process-put proc 'busy-end? (and (not busy)
+ (process-get proc 'busy)))
+ (when (not busy)
+ (process-put proc 'running-async? nil))
+ (process-put proc 'busy busy)
+ (process-put proc 'sec-prompt
+ (when inferior-ess-secondary-prompt
+ (string-match (concat "\\(" inferior-ess-secondary-prompt "\\)\\'") string)))
+ (unless no-timestamp
+ (process-put proc 'last-eval (current-time)))
+ busy))
+
+(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 artuments 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 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 surpressing 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."
+ (save-excursion
+ (let ((abuf (process-get proc :accum-buffer)))
+ (when (buffer-live-p abuf)
+ (kill-buffer abuf)))
+ (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)))))
+
+(defun inferior-ess-make-comint (bufname procname infargs &rest switches)
+ "Make an S comint process in buffer BUFNAME with process PROCNAME."
+;;; This function is a modification of make-comint from the comint.el
+;;; code of Olin Shivers.
+ (let* ((buffer (get-buffer-create bufname))
+ (proc (get-process procname)))
+ ;; If no process, or nuked process, crank up a new one and put buffer in
+ ;; comint mode. Otherwise, leave buffer and existing process alone.
+ (cond ((or (not proc) (not (memq (process-status proc) '(run stop))))
+ (with-current-buffer buffer
+ (if (eq (buffer-size) 0) nil
+ (goto-char (point-max))
+ (insert "\^L\n"))) ; page boundaries = Interactive sessions
+ (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)))))
+ (ess-write-to-dribble-buffer "Making Process...")
+ (ess-write-to-dribble-buffer
+ (format "Buf %s, :Proc %s, :Prog %s\n :Args= %s\nStart File=%s\n"
+ buffer
+ procname
+ inferior-ess-program
+ infargs
+ inferior-ess-start-file))
+ (comint-exec buffer
+ procname
+ inferior-ess-program
+ inferior-ess-start-file
+ (ess-line-to-list-of-words
+ infargs)))))
+ buffer))
+
+
+;;*;; Requester functions called at startup
+
+;; FIXME EMACS 25.1:
+;; Deprecate `ess-directory-function' in favour 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"))
+ (alist (make-symbol "alist")))
+ `(let ((,lpn ess-local-process-name)
+ (,alist ess-local-customize-alist))
+ (with-current-buffer ,buffer
+ (ess-setq-vars-local (eval ,alist))
+ (setq ess-local-process-name ,lpn)
+ ,@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))
+ (if (null name) ; should almost never happen at this point
+ (error "No ESS process is associated with this buffer now"))
+ (update-ess-process-name-list)
+ (if (assoc name ess-process-name-list)
+ (get-process name)
+ ;; else :
+ ;; was (error "Process %s is not running" name)
+ (ess-write-to-dribble-buffer
+ (format "ess-get-process: process '%s' not running" name))
+ (if (= 0 (length ess-process-name-list))
+ (save-current-buffer
+ (ess-write-to-dribble-buffer
+ (format " .. restart proc %s for language %s (buf %s)\n"
+ name ess-language (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
+ (if 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))
+ ;; else
+ (ding)
+ (if (y-or-n-p
+ (format "Process %s is not running, but others are. Switch? " name))
+ (progn
+ (ess-force-buffer-current
+ (concat ess-dialect " process to use: ") 'force)
+ (ess-get-process ess-current-process-name))
+ (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-<ESSlang>-program
+;; (how?) in R/S : assign(paste("inferior-",ESSlang,"-p...."), filename))
+
+
+;;*;; Multiple process handling code
+
+(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 ()
+ "Check if the local ess process is alive.
+Return nil if current buffer has no associated process, or
+process was killed."
+ (and ess-local-process-name
+ (let ((proc (get-process ess-local-process-name)))
+ (and (processp proc)
+ (process-live-p proc)))))
+
+(defun ess-process-get (propname)
+ "Return the variable PROPNAME (symbol) from the plist of the current ESS process."
+ (process-get (get-process ess-local-process-name) propname))
+
+(defun ess-process-put (propname value)
+ "Set the variable PROPNAME (symbol) to VALUE in the plist of the current ESS process."
+ (process-put (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)."
+ (unless dialect
+ (error "The value of `dialect' is nil"))
+ (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)))
+ ;; save excursion is not working here !!! bad bad bad !!
+ )))
+
+(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+" (if (boundp 'S+-dialect-name) S+-dialect-name "S+")
+ "stata" (if (boundp 'STA-dialect-name) STA-dialect-name "stata")
+ "julia" "SAS" "XLS" "ViSta")))))
+
+ (let* ((pname-list (delq nil ;; keep only those mathing 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))
+ (inferior-ess-same-window nil) ;; this should produce the inferior process in other window
+ (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 weired, but is necessary
+ (pop-to-buffer (buffer-name (process-buffer (get-process proc))) t))
+ 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."
+ (interactive
+ (list (concat ess-dialect " process to use: ") current-prefix-arg nil))
+ ;; fixme: why the above interactive is not working in emacs 24?
+ (setq prompt (or prompt "Process to use: "))
+ (let ((proc-name (ess-make-buffer-current)))
+ (if (and (not force) proc-name (get-process proc-name))
+ nil ; do nothing
+ ;; Make sure the source buffer is attached to a process
+ (if (and ess-local-process-name (not force) no-autostart)
+ (error "Process %s has died" ess-local-process-name)
+ ;; ess-local-process-name is nil -- which process to attach to
+ (let ((proc (ess-request-a-process prompt 'no-switch ask-if-1))
+ temp-ess-help-filetype dialect)
+ (with-current-buffer (process-buffer (get-process proc))
+ (setq temp-ess-help-filetype inferior-ess-help-filetype))
+ (setq ess-local-process-name proc)
+ (setq inferior-ess-help-filetype temp-ess-help-filetype))))))
+
+(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
+ (not (process-get proc 'busy))))
+ (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.
+This function should follow the description in `ess-show-buffer'
+for showing the iESS buffer, except that the iESS buffer is also
+made current."
+ (interactive "P")
+ (ess-force-buffer-current)
+ (if (and ess-current-process-name (get-process ess-current-process-name))
+ (progn
+ (ess-show-buffer
+ (buffer-name (process-buffer (get-process ess-current-process-name)))
+ t)
+ (if eob-p (goto-char (point-max))))
+ (message "No inferior ESS process")
+ (ding)))
+
+(defun ess-switch-to-ESS-deprecated (eob-p)
+ (interactive "P")
+ (ess-switch-to-ESS eob-p)
+ (message "C-c C-y is deprecated, use C-c C-z instead (ess-switch-to-inferior-or-script-buffer)"))
+
+(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)
+ "If in script, switch to the iESS. If in iESS switch to most recent script 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 ((map (make-sparse-keymap))
+ (EOB (if toggle-eob
+ (not ess-switch-to-end-of-proc-buffer)
+ ess-switch-to-end-of-proc-buffer)))
+ (define-key map (vector last-command-event)
+ (lambda (ev eob) (interactive)
+ (if (not (eq major-mode 'inferior-ess-mode))
+ (ess-switch-to-ESS eob)
+ (let ((dialect ess-dialect)
+ (loc-proc-name ess-local-process-name)
+ (blist (cdr (buffer-list))))
+ (while (and blist
+ (with-current-buffer (car blist)
+ (not (or (and
+ (memq major-mode '(ess-mode ess-julia-mode))
+ (equal dialect ess-dialect)
+ (null ess-local-process-name))
+ (and
+ (memq major-mode '(ess-mode ess-julia-mode))
+ (equal loc-proc-name ess-local-process-name))
+ ))))
+ (pop blist))
+ (if blist
+ (ess-show-buffer (car blist) t)
+ (message "Found no buffers for ess-dialect %s associated with process %s"
+ dialect loc-proc-name))))))
+ (ess--execute-electric-command map nil nil nil EOB)))
+
+
+(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)))
+
+(defcustom ess-show-buffer-action
+ '((display-buffer-pop-up-window display-buffer-use-some-window))
+ "Actions for `ess-show-buffer', passed to `display-buffer'."
+ :group 'ess
+ :type '(list (repeat function)))
+
+(defun ess-show-buffer (buf &optional visit)
+ "Ensure the ESS buffer BUF is visible.
+The buffer, specified as a string, is typically an iESS (e.g.
+*R*) buffer. This handles several cases:
+
+1. If BUF is visible in the current frame, nothing is done.
+2. If BUF is visible in another frame, then we ensure that frame is
+visible (it may have been iconified).
+3. If buffer is not visible in any frame, simply show it in another window
+in the current frame.
+
+If VISIT is non-nil, as well as making BUF visible, we also select it
+as the current buffer."
+ (let ((frame))
+ (if (ess-buffer-visible-this-frame buf)
+ ;;1. Nothing to do, BUF visible in this frame; just return window
+ ;; where this buffer is.
+ t
+ ;; 2. Maybe BUF visible in another frame.
+ (setq frame (ess-buffer-visible-other-frame buf))
+ (if frame
+ ;; BUF is visible in frame, so just check frame is raised.
+ (if (not (eq (frame-visible-p frame) t))
+ ;; frame is not yet visible, so raise it.
+ (raise-frame frame))
+ ;; 3. else BUF not visible in any frame, so show it (but do
+ ;; not select it) in another window in current frame.
+ (display-buffer buf ess-show-buffer-action)))
+ ;; At this stage, the buffer should now be visible on screen,
+ ;; although it won't have been made current.
+ (when visit
+ ;; Need to select the buffer.
+ ;;
+ ;; First of all, check case 2 if buffer is in another frame
+ ;; but that frame may not be selected.
+ (if frame
+ (ess-select-frame-set-input-focus frame))
+ (select-window (get-buffer-window buf 0)))))
+
+(defvar ess-bufs-in-frame nil) ;silence the compiler.
+;; The next few functions are copied from my (SJE) iswitchb library.
+(defun ess-get-bufname (win)
+ "Used by `ess-get-buffers-in-frames' to walk through all windows."
+ (let ((buf (buffer-name (window-buffer win))))
+ (if (not (member buf ess-bufs-in-frame))
+ ;; Only add buf if it is not already in list.
+ ;; This prevents same buf in two different windows being
+ ;; put into the list twice.
+ (setq ess-bufs-in-frame
+ (cons buf ess-bufs-in-frame)))))
+
+(defun ess-get-buffers-in-frames (&optional current)
+ "Return the list of buffers that are visible in the current frame.
+If optional argument CURRENT is given, restrict searching to the
+current frame, rather than all frames."
+ (let ((ess-bufs-in-frame nil))
+ (walk-windows 'ess-get-bufname nil (if current nil 0))
+ ess-bufs-in-frame))
+
+(defun ess-buffer-visible-this-frame (buf)
+ "Return t if BUF is visible in current frame."
+ (member buf (ess-get-buffers-in-frames t)))
+
+(defun ess-buffer-visible-other-frame (buf)
+ "Return t if BUF is visible in another frame.
+Assumes that buffer has not already been in found in current frame."
+ (if (member (buffer-name (get-buffer buf)) (ess-get-buffers-in-frames))
+ (window-frame (get-buffer-window buf 0))
+ nil))
+
+
+\f
+;;; Functions for evaluating code
+
+;;*;; Utils for evaluation
+
+(ess-defgeneric 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 the
+dialect-specific `ess-build-eval-command' function and
+`ess-eval-command', in that order. If none of the above is
+defined, return nil."
+ (setq string (ess-quote-special-chars string))
+ (:override
+ (and ess-eval-command
+ (format-spec ess-eval-command
+ `((?s . ,string)
+ (?f . ,file))))))
+
+(ess-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."
+ (:override
+ (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 excesive 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 t)
+ (ess--if-verbose-write-process-state proc string "ordinary-filter")
+ (inferior-ess-run-callback proc string)
+ (with-current-buffer (process-buffer proc)
+ ;; (princ (format "%s:" string))
+ (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)))))
+
+\f
+;;*;; Evaluation primitives
+
+(ess-defgeneric 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."
+ ;; 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)
+ (:override
+ (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)))))
+
+(ess-defgeneric 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 proc start end visibly message type))
+ (t (:override
+ (ess-send-string process (buffer-substring start end) visibly message type)))))
+
+\f
+;;*;; 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-check-source 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
+(ess-defgeneric ess-load-file (&optional filename)
+ "Load a source file into an inferior ESS process.
+This handles Tramp when working on a remote."
+ (interactive (list (or (and (memq major-mode '(ess-mode ess-julia-mode))
+ (buffer-file-name))
+ (expand-file-name
+ (read-file-name "Load source file: " nil nil t)))))
+ (ess-load-file--normalise-buffer filename)
+ ;; Pop up an inferior window
+ (save-selected-window
+ (ess-switch-to-ESS t))
+ (:override
+ (let ((file (ess-load-file--normalise-file filename)))
+ (let ((command (ess-build-load-command file nil t)))
+ (ess-send-string (ess-get-process) command t)))))
+
+;; C-c C-l *used to* eval code:
+(defun ess-msg-and-comint-dynamic-list-input-ring ()
+ "Display a list of recent inputs entered into the current buffer."
+ (interactive)
+ (message "C-c C-l no longer loads a source file in [iESS], rather use C-c M-l instead")
+ (comint-dynamic-list-input-ring))
+
+;; ;;; 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--normalise-proc (proc no-prompt-check)
+ (let ((proc (cond
+ (proc
+ ;; This lets external functions call this command
+ (unless ess-local-process-name
+ (setq ess-local-process-name (process-name proc)))
+ proc)
+ (t
+ (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))
+
+(ess-defgeneric ess-command (cmd &optional out-buffer sleep no-prompt-check wait proc force-redisplay)
+ "Send the ESS process command 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))
+ ...
+ })"
+ (:override
+ (let ((out-buffer (or out-buffer (get-buffer-create " *ess-command-output*")))
+ (proc (ess-command--normalise-proc proc no-prompt-check)))
+ (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)
+ (ess-mpi-handle-messages (current-buffer))
+ ;; 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."
+ (with-current-buffer (ess-command com buf nil nil wait)
+ (ess-kill-last-line)
+ (buffer-substring (point-min) (point-max))))
+
+;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
+;; (lambda (proc) (message "done")))
+;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
+;; (lambda (proc) (message "done"))
+;; t)
+;; (ess-async-command "{cat(1:5);Sys.sleep(5);cat(2:6)}\n" nil (get-process "R")
+;; (lambda (proc) (message "done"))
+;; (lambda (proc2) (message "name: %s" (process-name proc2))))
+
+(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."
+ (let ((proc (or proc (get-process ess-local-process-name))))
+ (if (not (and proc
+ (eq (process-status proc) 'run)))
+ (error "Process %s is dead" ess-local-process-name)
+ (if (or (process-get proc 'busy)
+ (process-get proc 'running-async?))
+ (error "Process %s is busy or already running an async command" ess-local-process-name)
+ (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 &optional buf proc 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."
+ (unless proc
+ (error "You must provide PROC argument to ess-async-command-delayed"))
+ (let* ((timer (make-symbol "timer"))
+ (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)))
+
+\f
+;;*;; Evaluating lines, paragraphs, regions, and buffers.
+
+(ess-defgeneric 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: ")
+ (:override
+ ;; Use this to evaluate some code, but don't wait for output.
+ (let* ((deactivate-mark) ; keep local {do *not* deactivate wrongly}
+ (cbuffer (current-buffer))
+ (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 (ess-show-buffer (buffer-name sbuffer) nil))
+ (goto-char (marker-position (process-mark sprocess)))
+ (when win
+ (with-selected-window win
+ (goto-char (point))
+ ;; this is crucial to avoid reseting window-point
+ (recenter (- -1 scroll-margin)))))))
+ (if (numberp sleep-sec)
+ (sleep-for sleep-sec)))
+
+\f
+;;;*;;; Evaluate only
+
+(defun ess-eval-region--normalise-region ()
+ "Clean the region 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 toggle &optional message type)
+ "Send the region from START to END to the inferior ESS process.
+TOGGLE 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 (and (bound-and-true-p rectangle-mark-mode)
+ ;; TODO: Remove this check after dropping support for Emacs
+ ;; 24, replace by putting this at the top of this file:
+ ;; (declare-function extract-rectangle-bounds "rect")
+ (fboundp 'extract-rectangle-bounds))
+ ;; 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) toggle message type))
+ reclines))
+ (ess--eval-region start end toggle message type)))
+
+(defun ess--eval-region (start end toggle &optional message type)
+ "Helper function for `ess-eval-region', which see.
+START, END, TOGGLE, MESSAGE, and TYPE described there."
+ (ess-eval-region--normalise-region)
+ (let ((visibly (if toggle (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 (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 (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 (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 (vis &optional no-error)
+ "Send the current function to the inferior ESS process.
+Prefix argument VIS toggles the meaning of `ess-eval-visibly'. If
+NO-ERROR is non-nil and the function was successfully evaluated,
+return '(beg end) representing the beginning and end of the
+current function, otherwise (in case of an error) return nil."
+ (interactive "P")
+ (ess-force-buffer-current "Process to use: ")
+ (save-excursion
+ (ignore-errors
+ ;; Evaluation is forward oriented
+ (forward-line -1)
+ (ess-next-code-line 1))
+ (let ((beg-end (ess-end-of-function nil no-error)))
+ (when beg-end
+ (let* ((beg (nth 0 beg-end))
+ (end (nth 1 beg-end))
+ (proc (get-process ess-local-process-name))
+ ;; FIXME: func names starting with . are not recognized??
+ (name (progn (goto-char beg)
+ (forward-word)
+ (ess-read-object-name-default)))
+ (msg (format "Eval function %s"
+ (propertize (or name "???")
+ 'face 'font-lock-function-name-face)))
+ (visibly (if vis (not ess-eval-visibly) ess-eval-visibly)))
+ (ess-blink-region beg end)
+ (cond
+ ((ess-tracebug-p)
+ (ess-tracebug-send-function proc beg end visibly msg))
+ (t
+ (ess-send-region proc beg end visibly msg)))
+ beg-end)))))
+
+;; This is from Mary Lindstrom <lindstroNOSPAMBiostat.Wisc.Edu>
+;; 31 Aug 1995 14:11:43 To: S-modeNOSPAMstat.math.ethz.ch
+(defun ess-eval-paragraph (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")
+ (save-excursion
+ (forward-paragraph)
+ ;; Skip blank code to avoid sending surrounding comments
+ (ess-skip-blanks-backward 'multiline)
+ (let ((end (point)))
+ (backward-paragraph)
+ (ess-skip-blanks-forward 'multiline)
+ (ess-eval-region (point) end vis "Eval paragraph"))))
+
+;; ;; Experimental - after suggestion from Jenny Brian for an 'eval-multiline'
+;; ;; 'sentence' is too much : almost like 'paragraph'
+;; ;; 'sexp' is close, but too little [when point is inside function call;
+;; ;; it moves all the way to the end - which is fine]
+;; (defun ess-eval-sexp (vis)
+;; "Send the current sexp to the inferior ESS process.
+;; Prefix arg VIS toggles visibility of ess-code as for `ess-eval-region'."
+;; (interactive "P")
+;; (save-excursion
+;; (forward-sexp)
+;; (let ((end (point)))
+;; (backward-sexp)
+;; (ess-eval-region (point) end vis "Eval sexp"))))
+
+(defun ess-eval-function-or-paragraph (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")
+ (let ((beg-end (ess-eval-function vis 'no-error)))
+ (if (null beg-end) ; not a function
+ (ess-eval-paragraph vis))))
+
+(defun ess-eval-function-or-paragraph-and-step (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")
+ (let ((beg-end (ignore-errors (ess-eval-function vis 'no-error)))) ;; ignore-errors is a hack, ess-eval-function gives stupid errors sometimes
+ (if (null beg-end) ; not a function
+ (ess-eval-paragraph-and-step vis)
+ (goto-char (cadr beg-end))
+ (if ess-eval-empty
+ (forward-line 1)
+ (ess-next-code-line 1)))))
+
+(defun ess-eval-region-or-function-or-paragraph (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 (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")
+ (if (use-region-p)
+ (let ((end (region-end)))
+ (ess-eval-region (region-beginning) end vis)
+ (goto-char end))
+ (ess-eval-function-or-paragraph-and-step vis)))
+
+(defun ess-eval-region-or-line-and-step (&optional vis)
+ "Evaluate region if active, otherwise the current line and step.
+Prefix arg VIS toggles visibility of ess-code when evaluating the
+region (as for `ess-eval-region') and has no effect for
+evaluation of the line. 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)
+ (ess-show-buffer (ess-get-process-buffer))
+ (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."
+ (interactive "P")
+ (ess-eval-line vis)
+ (ess-next-code-line 1))
+
+(defun ess-eval-line-visibly-and-step (&optional simple-next even-empty)
+ "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. If 2nd arg EVEN-EMPTY [prefix as
+well], also send empty 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') evaluation of multiline
+input will fail."
+ (interactive "P\nP"); prefix sets BOTH!
+ (ess-force-buffer-current)
+ (ess-show-buffer (ess-get-process-buffer))
+ (let ((ess-eval-visibly t))
+ (ess-eval-line))
+ (if (or simple-next ess-eval-empty even-empty)
+ (forward-line 1)
+ (ess-next-code-line 1)))
+
+(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")
+
+(defun ess-next-code-line (&optional arg skip-to-eob)
+ "Move ARG lines of code forward (backward if ARG is negative).
+Skips past all empty and comment lines. Default for ARG is 1.
+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")
+ (or arg (setq arg 1))
+ (beginning-of-line)
+ (let ((pos (point))
+ (n 0)
+ (inc (if (> arg 0) 1 -1)))
+ (while (and (/= arg 0) (= n 0))
+ (setq n (forward-line inc)); n=0 is success
+ (if (not (fboundp 'comment-beginning))
+ (while (and (= n 0)
+ (looking-at "\\s-*\\($\\|\\s<\\)"))
+ (setq n (forward-line inc)))
+ (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 arg (- arg inc))
+ (goto-char pos)
+ (setq arg 0)
+ (forward-line 1));; stop at next empty line
+ (setq pos (point)))
+ (goto-char pos)
+ n))
+
+\f
+;;;*;;; Evaluate and switch to S
+
+(defun ess-eval-region-and-go (start end 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 (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 (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 (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 (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 (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")
+ (let ((beg-end (ess-eval-paragraph vis)))
+ (goto-char (cadr beg-end))
+ (if ess-eval-empty
+ (forward-line 1)
+ (ess-next-code-line 1))))
+
+\f ; Inferior S 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)))
+ (set-keymap-parent map comint-mode-map)
+ (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 favour 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);; no longer overwrites C-c C-l;
+ ;; but for now the user deserves a message:
+ (define-key map "\C-c\C-l" 'ess-msg-and-comint-dynamic-list-input-ring)
+ (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 "\C-c\t" 'ess-complete-object-name-deprecated)
+ (define-key map "\M-?" 'ess-list-object-completions)
+ (define-key map "\C-c\C-k" 'ess-request-a-process)
+ (define-key map "," 'ess-smart-comma)
+ (define-key map (kbd "C-c C-=") 'ess-cycle-assign)
+ (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)
+ (with-no-warnings ; Obsolete key variable
+ (when ess-smart-S-assign-key
+ (define-key map ess-smart-S-assign-key 'ess-smart-S-assign)))
+ 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"
+ ["What is this? (beta)" ess-mouse-me t]
+ ["Quit" ess-quit 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"
+ ;; need a toggle switch for above, AJR.
+ ["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 and S versions known to ESS" (ess-r-s-versions-creation+menu) t]
+ )
+ "------"
+ ("start-dev" :visible nil); <-- ??
+ ("end-dev" :visible nil)
+ "------"
+ ("Font Lock"
+ :active inferior-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'.")
+
+;;;###autoload
+(defun inferior-ess-mode ()
+ "Major mode for interacting with an inferior ESS process.
+Runs an S interactive job as a subprocess of Emacs, with I/O through an
+Emacs buffer. Variable `inferior-ess-program' controls which S
+is run.
+
+Commands are sent to the ESS process by typing them, and pressing
+\\[inferior-ess-send-input]. Pressing \\[complete-dynamic-complete]
+completes known object names or filenames, as appropriate. Other
+keybindings for this mode are:
+
+\\{inferior-ess-mode-map}
+
+When editing S objects, the use of \\[ess-load-file] is advocated.
+`ess-load-file' keeps source files (if `ess-keep-dump-files' is non-nil) in
+the directory specified by `ess-source-directory', with the
+filename chosen according to `ess-dump-filename-template'. When a file is
+loaded, `ess-mode' parses error messages and jumps to the appropriate file
+if errors occur. The ess-eval- commands do not do this.
+
+Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
+`inferior-ess-mode-hook' (in that order).
+
+You can send text to the inferior ESS process from other buffers
+containing source code. The key bindings of these commands can be
+found by typing \\[describe-mode].
+
+ `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-beginning-of-function' and `ess-end-of-function' move the point to
+ the beginning and end of the current S function.
+ `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-dump-object-into-edit-buffer' moves an S object into a temporary file
+ and buffer for editing
+ `ess-load-file' sources a file of commands to the ESS process.
+
+Commands:
+Return after the end of the process' output sends the text from the
+ end of process to point.
+Return before the end of the process' output copies the sexp ending at point
+ to the end of the process' output, and sends it.
+Delete converts tabs to spaces as it moves back.
+C-M-q does Tab on each line starting within following expression.
+Paragraphs are separated only by blank lines. Crosshatches start comments.
+If you accidentally suspend your process, use \\[comint-continue-subjob]
+to continue it."
+ (interactive)
+ (delay-mode-hooks
+ (comint-mode))
+ (set (make-local-variable 'comint-input-sender) 'inferior-ess-input-sender)
+ (set (make-local-variable 'process-connection-type) t)
+ ;; initialize all custom vars:
+ (ess-setq-vars-local ess-customize-alist) ; (current-buffer))
+
+ ;; If comint-process-echoes is t inferior-ess-input-sender
+ ;; recopies the input, otherwise not. VS[03-09-2012]: should be in customize-alist
+ (set (make-local-variable 'comint-process-echoes)
+ (not (member ess-language '("SAS" "XLS" "OMG" "julia")))) ;; these don't echo
+
+ (when (and (member ess-dialect '("R")) ;; S+ echoes!!
+ (not (eq ess-eval-visibly t)))
+ ;; when 'nowait or nil, don't wait for process
+ (setq comint-process-echoes nil))
+
+ (when comint-use-prompt-regexp ;; why comint is not setting this? bug?
+ (set (make-local-variable '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 comint-get-old-input 'inferior-ess-get-old-input) ;; todo: this is R specific
+ (add-hook 'comint-input-filter-functions 'ess-search-path-tracker nil 'local) ;; R and S specific
+
+ (setq major-mode 'inferior-ess-mode)
+ (setq mode-name "iESS") ;(concat "iESS:" ess-dialect))
+ (setq mode-line-process
+ '(" ["
+ ess--mode-line-process-indicator
+ ess--local-mode-line-process-indicator
+ "]: %s"))
+ (use-local-map inferior-ess-mode-map)
+ (let ((inf-syntax-table (or inferior-ess-mode-syntax-table
+ ess-mode-syntax-table)))
+ (when inf-syntax-table
+ (set-syntax-table inf-syntax-table)))
+
+ (ess-write-to-dribble-buffer
+ (format "(i-ess 1): buf=%s, lang=%s, comint..echo=%s, comint..sender=%s,\n"
+ (current-buffer) ess-language
+ comint-process-echoes comint-input-sender))
+
+ (when (string= ess-language "S") ;; todo: what is this doing here?
+ (local-set-key "\M-\r" 'ess-dirs))
+
+ ;; SJE 2007-06-28: Emacs 22.1 has a bug in that comint-mode will set
+ ;; this variable to t, when we need it to be nil. The Emacs 22
+ ;; solution to this bug is to use define-derived-mode to derive
+ ;; inferior-ess-mode from comint-mode. Not sure if we can go down
+ ;; that route yet. I've used the when condition so that if the var
+ ;; is nil, don't bother setting it -- as setting it will make a new
+ ;; local var.
+ (when font-lock-keywords-only
+ (setq font-lock-keywords-only nil))
+
+ ;;; 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)
+ ;; (setq comint-completion-addsuffix nil) ; To avoid spaces after filenames
+ ;; KH: next 2 lines solve.
+ (set (make-local-variable 'comint-completion-addsuffix)
+ (cons "/" ""))
+ (setq comint-input-autoexpand t) ; Only for completion, not on input.
+ ;; timers
+ ;; (add-hook 'ess-idle-timer-functions 'ess-cache-search-list nil 'local)
+ ;; (add-hook 'ess-idle-timer-functions 'ess-synchronize-dirs nil 'local)
+ ;;; Keep <tabs> out of the code.
+ (set (make-local-variable 'indent-tabs-mode) nil)
+ (set (make-local-variable 'paragraph-start)
+ (concat inferior-ess-primary-prompt "\\|\^L"))
+ (set (make-local-variable 'paragraph-separate) "\^L")
+ (if (featurep 'jit-lock)
+ (setq-local jit-lock-chunk-size inferior-ess-jit-lock-chunk-size))
+ (make-local-variable 'kill-buffer-hook)
+ (add-hook 'kill-buffer-hook 'ess-kill-buffer-function)
+ (run-mode-hooks 'inferior-ess-mode-hook)
+ (ess-write-to-dribble-buffer
+ (format "(i-ess end): buf=%s, lang=%s, comint..echo=%s, comint..sender=%s,\n"
+ (current-buffer) ess-language
+ comint-process-echoes comint-input-sender))
+ (message
+ (concat (substitute-command-keys
+ "Type \\[describe-mode] for help on ESS version ")
+ ess-version)))
+
+\f
+;;*;; 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 twise.
+ (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 begining of input skiping all continuation lines.
+If in the output field, goes to the begining of previous input
+field.
+Note: `inferior-ess-secondary-prompt' should match exactly."
+ (goto-char (field-beginning))
+ ;; move to the begining of non-output field
+ (while (and (not (= (point) (point-min)))
+ (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 skiping all continuation lines.
+If in the output field, goes to the begining 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 begining of input skiping all continuation lines.
+If in the output field, goes to the begining 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 "Beggining 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)
+ (setq ess-temp-point (point)) ;; this is ugly, used by transcript
+ 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)))
+
+\f
+;;;*;;; 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)
+ ;; 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 (if (fboundp 'default-font-width)
+ (floor (/ wwidth (default-font-width)))
+ ;; emacs 24
+ (if (display-graphic-p)
+ (let* ((r (/ (float (frame-char-height)) (frame-char-width)))
+ (charh (aref (font-info (face-font 'default)) 3))
+ (charw (/ charh r)))
+ (- (floor (/ wwidth charw)) 1))
+ ;; e.g., no X11 as in 'emacs -nw'
+ (- (window-width) 2))))
+ (command (format ess-execute-screen-options-command nchars)))
+ (if invisibly
+ (ess-command command)
+ (ess-eval-linewise command nil nil nil 'wait-prompt)))))
+
+(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)
+ (let ((buff (ess-create-temp-buffer buff-name)))
+ (ess-command the-command buff);; sleep?
+ (with-current-buffer buff
+ (goto-char (point-min))
+ (if message (insert message)
+ (if buff nil
+ ;; Print the command in the buffer if it has not been
+ ;; given a special name
+ (insert "> " the-command)))
+ (setq ess-local-process-name ess-current-process-name))
+ (ess-display-temp-buffer buff)))))
+
+\f
+;;;*;;; Quitting
+
+(ess-defgeneric ess-quit (&rest args)
+ "Issue an exiting command to the inferior process, additionally
+also running \\[ess-cleanup]."
+ (interactive)
+ (ess-force-buffer-current "Process to quit: " nil 'no-autostart)
+ (ess-interrupt)
+ (ess-make-buffer-current)
+ (:override
+ (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-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 ()
+ "Possibly kill or offer to kill, depending on the value of
+`ess-S-quit-kill-buffers-p', all buffers associated with this ESS process.
+Leaves you in the ESS process buffer. It's a good idea to run this
+before you quit. It is run automatically by \\[ess-quit]."
+ (interactive)
+ (let ((the-procname (or (ess-make-buffer-current) ess-local-process-name)))
+ (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)))))
+ (ess-switch-to-ESS nil)))
+
+(ess-defgeneric inferior-ess-reload (&optional start-args)
+ "Reload the inferior process."
+ (interactive)
+ (inferior-ess-force)
+ ;; 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 (ess-get-process))
+ (:override
+ (error "Unimplemented for this 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")))))
+
+(defun ess-kill-buffer-function ()
+ "Function run just before an ESS process buffer is killed."
+ ;; This simply deletes the buffers process to avoid an Emacs bug
+ ;; where the sentinel is run *after* the buffer is deleted
+ (let ((proc (get-buffer-process (current-buffer))))
+ (if (processp proc) (delete-process proc))))
+
+\f
+;;;*;;; 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 (ess-uniq-list 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-if-verbose-write
+ (format "(ess-get-words-* command=%s full-word-regexp=%S)\n"
+ command full-word-regexp))
+ (ess-command command tbuffer 'sleep no-prompt-check wait proc)
+ (ess-if-verbose-write " [ok] ..")
+ (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)))))
+ (if 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)
+ (temp-object-name-db-file ess-object-name-db-file))
+
+ (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)
+ (setq ess-object-list nil)
+ (setq ess-object-name-db nil) ; perhaps it would be better to reload?
+ (ess-process-put 'sp-for-help-changed? t)
+ (ess-get-modtime-list))
+
+(defun ess-filename-completion ()
+ ;; > emacs 24
+ "Return completion only within string or comment."
+ (save-restriction ;; explicitely handle inferior-ess
+ (ignore-errors
+ (when (and (eq major-mode 'inferior-ess-mode)
+ (> (point) (process-mark (get-buffer-process (current-buffer)))))
+ (narrow-to-region (process-mark (get-buffer-process (current-buffer)))
+ (point-max))))
+ (when (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 ;; explicitely handle inferior-ess
+ (ignore-errors
+ (when (and (eq major-mode '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)))))))
+
+\f
+;;*;; 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
+defaultst 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))
+ (setq 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)))))))
+ (setq index (1+ index))
+ (setq 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))))
+
+\f
+;;; Miscellaneous routines
+
+;;;*;;; Routines for reading object names
+(ess-defgeneric ess-read-object-name (p-string)
+ "Read an object name from the minibuffer with completion, and return it.
+P-STRING is the prompt string."
+ (:override
+ (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 (eq major-mode 'inferior-ess-mode)
+ (indent-according-to-mode)))
+ (insert ",")))))
+
+\f ; 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 (&optional no-force-current)
+ "Set the current process directory to the directory of this file.
+`default-directory' is used as a fallback. If that buffer has no
+associated *R* process, use \\[ess-force-buffer-current], unless
+prefix argument NO-FORCE-CURRENT is non-nil."
+ (interactive "P")
+ (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)
+ "Retrive 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)
+ (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)))))
+
+\f
+;;*;; Temporary buffer handling
+
+;; (defun ess-create-temp-buffer (name)
+;; "Create an empty buffer called NAME, but doesn't display it."
+;; (let ((buff (get-buffer-create name)))
+;; (save-excursion
+;; (set-buffer buff)
+;; (erase-buffer))
+;; buff))
+
+
+;; Ed Kademan's version:
+;; From: Ed Kademan <kademanNOSPAMphz.com>
+;; Subject: Re: ess-mode 5.1.16; search list
+;; To: rossiniNOSPAMbiostat.washington.edu (A.J. Rossini)
+;; Cc: Martin Maechler <maechlerNOSPAMstat.math.ethz.ch>, ess-bugsNOSPAMstat.math.ethz.ch
+;; Date: 26 Jul 2000 16:12:12 -0400
+
+;; Dear Tony Rossini,
+
+;; I was having trouble looking at the search list under ess. When I
+;; started up multiple inferior processes---each for a different
+;; dialect---ess-mode would issue the wrong variant of the "search"
+;; command when I typed C-c C-s. In case it is useful let me tell you
+;; what I did to get it to work for me.
+
+;; I added the component:
+;; (inferior-ess-search-list-command . "search()\n")
+;; to S+3-customize-alist and ess-r-customize-alist, and then I redefined the
+;; ess-create-temp-buffer function as follows:
+(defun ess-create-temp-buffer (name)
+ "Create an empty buffer called 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))
+;;These two steps seem to insure that the temporary buffer in which the
+;;search results appear has the correct version of the local variables.
+;;I am not that well acquainted with the ess code and don't know whether
+;;this is a good fundamental way of fixing the problem, or even whether
+;;or not this breaks some other feature of ess-mode that I never use.
+;;Thanks for listening.
+;;Ed K.
+;;--
+;;Ed Kademan 508.651.3700
+;;PHZ Capital Partners 508.653.1745 (fax)
+;;321 Commonwealth Road <kademanNOSPAMphz.com>
+;;Wayland, MA 01778
+
+(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)
+ ;; this is different from ess-load-file
+ (let ((content (with-temp-buffer
+ (insert-file-contents file)
+ (buffer-string))))
+ (when (string= ess-dialect "R")
+ ;; don't detect intermediate prompts
+ (setq content (concat "{" content "}\n")))
+ (ess-command content)))
+
+(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"))))))
+
+(defun ess-check-source (fname)
+ "If file FNAME has an unsaved buffer, offer to save it.
+Returns t if the buffer existed and was modified, but was not saved."
+ (let ((buff (get-file-buffer fname)))
+ ;; RMH: Corrections noted below are needed for C-c C-l to work
+ ;; correctly when issued from *S* buffer.
+ ;; The following barfs since
+ ;; 1. `if' does not accept a buffer argument, `not' does.
+ ;; 2. (buffer-file-name) is not necessarily defined for *S*
+ ;;(if buff
+ ;; (let ((deleted (not (file-exists-p (buffer-file-name)))))
+ ;; Next 2 lines are RMH's solution:
+ (if (not (not buff))
+ (let ((deleted (not (file-exists-p fname))))
+ (if (and deleted (not (buffer-modified-p buff)))
+ ;; Buffer has been silently deleted, so silently save
+ (with-current-buffer buff
+ (set-buffer-modified-p t)
+ (save-buffer))
+ (if (and (buffer-modified-p buff)
+ (or ess-mode-silently-save
+ (y-or-n-p
+ (format "Save buffer %s first? "
+ (buffer-name buff)))))
+ (with-current-buffer buff
+ (save-buffer))))
+ (buffer-modified-p buff)))))
+
+\f
+;;*;; Error messages
+
+(defun ess-parse-errors (&optional showerr reset)
+ "Jump to error in last loaded ESS source file.
+With prefix argument, only shows 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
+ (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."
+ (display-buffer (process-buffer (get-process ess-local-process-name)))
+ (error msg))
+
+(make-obsolete 'ess-error nil "18.10")
+
+(provide 'ess-inf)
+;;; ess-inf.el ends here
+
+;; Local Variables:
+;; byte-compile-warnings: (not lexical)
+;; End:
--- /dev/null
+;;; ess-jags-d.el --- ESS[JAGS] dialect
+
+;; Copyright (C) 2008-2011 Rodney Sparapani
+
+;; Author: Rodney Sparapani
+;; Created: 13 March 2008
+;; Maintainer: ESS-help <ess-helpNOSPAMr-project.org>
+
+;; 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)
+
+(setq auto-mode-alist
+ (append '(("\\.[jJ][aA][gG]\\'" . ess-jags-mode)) auto-mode-alist))
+
+(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 "\\<d\\(bern\\|beta\\|bin\\|cat\\|chisq\\|"
+ "dexp\\|dirch\\|exp\\|\\(gen[.]\\)?gamma\\|hyper\\|"
+ "interval\\|lnorm\\|logis\\|mnorm\\|mt\\|multi\\|"
+ "negbin\\|norm\\(mix\\)?\\|par\\|pois\\|sum\\|t\\|"
+ "unif\\|weib\\|wish\\)[ \t\n]*(")
+ font-lock-constant-face)
+
+ (cons (concat "\\<\\(abs\\|cos\\|dim\\|\\(i\\)?cloglog\\|equals\\|"
+ "exp\\|for\\|inprod\\|interp[.]line\\|inverse\\|length\\|"
+ "\\(i\\)?logit\\|logdet\\|logfact\\|loggam\\|max\\|mean\\|"
+ "mexp\\|min\\|phi\\|pow\\|probit\\|prod\\|rank\\|round\\|"
+ "sd\\|sin\\|sort\\|sqrt\\|step\\|sum\\|t\\|trunc\\|T\\)[ \t\n]*(")
+ font-lock-function-name-face)
+
+ ;; .jmd files
+ (cons (concat "\\<\\(adapt\\|cd\\|clear\\|coda\\|data\\|dir\\|"
+ "exit\\|in\\(itialize\\)?\\|load\\|model\\|monitors\\|parameters\\|"
+ "pwd\\|run\\|s\\(amplers\\|ystem\\)\\|to\\|update\\)[ \t\n]")
+ font-lock-keyword-face)
+
+ (cons "\\<\\(compile\\|monitor\\)[, \t\n]"
+ font-lock-keyword-face)
+
+ (cons "[, \t\n]\\(by\\|chain\\|nchains\\|stem\\|thin\\|type\\)[ \t\n]*("
+ font-lock-function-name-face)
+ )
+ "ESS[JAGS]: Font lock keywords."
+ )
+
+(defun ess-jags-switch-to-suffix (suffix &optional jags-chains jags-monitor jags-thin
+ jags-burnin jags-update)
+ "ESS[JAGS]: Switch to file with suffix."
+ (find-file (concat ess-bugs-file-dir ess-bugs-file-root suffix))
+
+ (if (equal 0 (buffer-size)) (progn
+ (if (equal ".jag" suffix) (progn
+ (insert "var ;\n")
+ (insert "model {\n")
+ (insert " for (i in 1:N) {\n \n")
+ (insert " }\n")
+ (insert "}\n")
+ (insert "#Local Variables" ":\n")
+ (insert "#ess-jags-chains:1\n")
+ (insert "#ess-jags-monitor:(\"\")\n")
+ (insert "#ess-jags-thin:1\n")
+ (insert "#ess-jags-burnin:10000\n")
+ (insert "#ess-jags-update:10000\n")
+ (insert "#End:\n")
+ ))
+
+ (if (equal ".jmd" suffix) (let
+ ((ess-jags-temp-chains "") (ess-jags-temp-monitor "") (ess-jags-temp-chain ""))
+
+ (if jags-chains (setq ess-jags-chains jags-chains))
+ (if jags-monitor (setq ess-jags-monitor jags-monitor))
+ (if jags-thin (setq ess-jags-thin jags-thin))
+
+ (setq ess-jags-temp-chains
+ (concat "compile, nchains(" (format "%d" ess-jags-chains) ")\n"))
+
+ (setq jags-chains ess-jags-chains)
+
+ (while (< 0 jags-chains)
+ (setq ess-jags-temp-chains
+ (concat ess-jags-temp-chains
+ "parameters ## \"" ess-bugs-file-root
+ ".##" (format "%d" jags-chains) "\", chain("
+ (format "%d" jags-chains) ")\n"))
+ (setq jags-chains (- jags-chains 1)))
+
+ (setq ess-jags-temp-monitor "")
+
+ (while (and (listp ess-jags-monitor) (consp ess-jags-monitor))
+ (if (not (string-equal "" (car ess-jags-monitor)))
+ (setq ess-jags-temp-monitor
+ (concat ess-jags-temp-monitor "monitor "
+ (car ess-jags-monitor) ", thin(" (format "%d" ess-jags-thin) ")\n")))
+ (setq ess-jags-monitor (cdr ess-jags-monitor)))
+
+ (insert "model in \"" ess-bugs-file-root ".jag\"\n")
+ (insert "data in \"" ess-bugs-file-root ".jdt\"\n")
+ (insert (ess-replace-in-string ess-jags-temp-chains "##" "in"))
+ (insert "initialize\n")
+ ;(insert "update " (format "%d" (* jags-thin jags-burnin)) "\n")
+ (insert "update " (format "%d" jags-burnin) "\n")
+ (insert ess-jags-temp-monitor)
+ (insert "update " (format "%d" (* jags-thin jags-update)) "\n")
+ (insert (ess-replace-in-string
+ (ess-replace-in-string ess-jags-temp-chains
+ "compile, nchains([0-9]+)" "#") "##" "to"))
+ (insert "coda "
+ ;(if ess-microsoft-p (if (w32-shell-dos-semantics) "*" "\\*") "\\*")
+ "*, stem(\"" ess-bugs-file-root "\")\n")
+
+ (if ess-jags-system (progn
+ (insert "system rm -f " ess-bugs-file-root ".ind\n")
+ (insert "system ln -s " ess-bugs-file-root "index.txt " ess-bugs-file-root ".ind\n")
+
+ (setq jags-chains ess-jags-chains)
+
+ (while (< 0 jags-chains)
+ (setq ess-jags-temp-chain (format "%d" jags-chains))
+
+ ;.txt not recognized by BOA and impractical to over-ride
+ (insert "system rm -f " ess-bugs-file-root ess-jags-temp-chain ".out\n")
+ (insert "system ln -s " ess-bugs-file-root "chain" ess-jags-temp-chain ".txt "
+ ess-bugs-file-root ess-jags-temp-chain ".out\n")
+ (setq jags-chains (- jags-chains 1)))))
+
+ (insert "exit\n")
+ (insert "Local Variables" ":\n")
+ (insert "ess-jags-chains:" (format "%d" ess-jags-chains) "\n")
+ (insert "ess-jags-command:\"jags\"\n")
+ (insert "End:\n")
+ ))
+ ))
+ )
+
+(defun ess-jags-na-jmd (jags-command jags-chains)
+ "ESS[JAGS]: Perform the Next-Action for .jmd."
+ ;(ess-save-and-set-local-variables)
+ (if (equal 0 (buffer-size)) (ess-jags-switch-to-suffix ".jmd")
+ ;else
+ (shell)
+ (ess-sleep)
+
+ (if (when (fboundp 'w32-shell-dos-semantics)
+ (w32-shell-dos-semantics))
+ (if (string-equal ":" (substring ess-bugs-file 1 2))
+ (progn
+ (insert (substring ess-bugs-file 0 2))
+ (comint-send-input)
+ )
+ )
+ )
+
+ (insert "cd \"" ess-bugs-file-dir "\"")
+ (comint-send-input)
+
+ ; (let ((ess-jags-temp-chains ""))
+ ;
+ ; (while (< 0 jags-chains)
+ ; (setq ess-jags-temp-chains
+ ; (concat (format "%d " jags-chains) ess-jags-temp-chains))
+ ; (setq jags-chains (- jags-chains 1)))
+
+ (insert ess-bugs-batch-pre-command " " jags-command " "
+ ess-bugs-file-root ".jmd "
+
+ (if (or (equal shell-file-name "/bin/csh")
+ (equal shell-file-name "/bin/tcsh")
+ (equal shell-file-name "/bin/zsh")
+ (equal shell-file-name "/bin/bash"))
+ (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
+(defun ess-jags-mode ()
+ "ESS[JAGS]: Major mode for JAGS."
+ (interactive)
+ (kill-all-local-variables)
+ (ess-setq-vars-local '((comment-start . "#")))
+ (setq major-mode 'ess-jags-mode)
+ (setq mode-name "ESS[JAGS]")
+ (use-local-map ess-bugs-mode-map)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(ess-jags-font-lock-keywords nil t))
+ (setq ess-language "S") ; mimic S for ess-smart-underscore
+ (run-mode-hooks 'ess-bugs-mode-hook)
+
+ (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))
+
+(defvaralias 'ess-jags-mode-hook 'ess-bugs-mode-hook)
+(defvaralias 'ess-jags-mode-map 'ess-bugs-mode-map)
+
+(setq features (delete 'ess-bugs-d features))
+(provide 'ess-jags-d)
+
+;;; ess-jags-d.el ends here
--- /dev/null
+;; ess-julia.el --- ESS julia mode and inferior interaction
+;;
+;; 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:
+;;
+;; Customise 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 'compile)
+(require 'ess-utils)
+(require 'ess-r-mode)
+(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))))
+
+\f
+;;; HELP
+(defun ess-julia-get-help-topics (&optional proc)
+ (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 "toctree.*href=\"\\(.+\\)\">\\(.+\\)</a" nil t)
+ (push (propertize (match-string 2)
+ :manual (concat url (match-string 1)))
+ out))
+ (kill-buffer)
+ (nreverse out))))
+
+(defvar ess-julia--manual-topics nil)
+(defun ess-julia-manual-lookup-function (&rest args) ; args are not used
+ (interactive)
+ "Look up topics at https://docs.julialang.org/en/latest/manual/"
+ ;; <li class="toctree-l1"><a class="reference internal" href="introduction/">Introduction</a></li>
+ (let* ((pages (or ess-julia--manual-topics
+ (setq ess-julia--manual-topics
+ (ess-julia--retrive-topics "https://docs.julialang.org/en/latest/manual/"))))
+ (page (ess-completing-read "Lookup:" pages nil t)))
+ (browse-url (get-text-property 1 :manual page))))
+
+(defun ess-julia-input-sender (proc string)
+ (save-current-buffer
+ (let* ((help-?-regexp "^ *\\(?:\\(?1: *?\\? *\\)\\(?2:.+\\)\\)")
+ (help-?-match (string-match help-?-regexp string)))
+ (cond (help-?-match
+ (ess-display-help-on-object (match-string 2 string))
+ (process-send-string proc "\n"))
+ (t ;; normal command
+ (inferior-ess-input-sender proc string))))))
+
+;; julia 0.3.0 doesn't provide categories. Thus we don't support this anymore.
+;; (defun ess-julia-reference-lookup-function (&rest args) ; args are not used
+;; (interactive)
+;; "Look up reference topics"
+;; ;; <li class="toctree-l1"><a class="reference internal" href="introduction/">Introduction</a></li>
+;; (let* ((pages (ess-get-words-from-vector "ESS.help_categories()\n")))
+;; (ess-display-help-on-object
+;; (ess-completing-read "Category" pages nil t))))
+
+
+\f
+;;; COMPLETION
+(defun ess-julia-latexsub-completion ()
+ "Complete latex input, and returns in a format required by `completion-at-point-functions'."
+ (if (julia-latexsub) ; julia-latexsub returns nil if it performed a completion, the point otherwise
+ nil
+ (lambda () t) ;; bypass other completion methods
+ ))
+
+(defun ess-julia-object-completion ()
+ "Return completions at point in a format required by `completion-at-point-functions'. "
+ (let ((proc (ess-get-next-available-process ess-dialect t))
+ (beg (ess-symbol-start)))
+ (if proc
+ (when beg
+ (let* ((prefix (buffer-substring-no-properties beg (point)))
+ (obj (and (string-match "\\(.*\\)\\..*$" prefix)
+ (match-string 1 prefix)))
+ (beg (if obj
+ (+ beg 1 (length obj))
+ beg)))
+ (list beg (point)
+ (nreverse (mapcar 'car (ess-julia--get-objects proc obj)))
+ :exclusive 'no)))
+ (when (string-match "complet" (symbol-name last-command))
+ (message "No ESS process of dialect %s started" ess-dialect)
+ nil))))
+
+(defun ess-julia-objects (prefix &optional proc)
+ "Given PREFIX get all cached objects from PROC."
+ (when prefix
+ (let ((proc (or proc (ess-get-next-available-process nil t))))
+ (if (string-match "\\(.*\\)\\..*$" prefix)
+ (let ((module (match-string 1 prefix)))
+ (mapcar (lambda (el) (concat module "." (car el)))
+ (ess-julia--get-objects proc module)))
+ (ess-julia--get-objects proc)))))
+
+(defun ess-julia--get-objects (&optional proc obj)
+ "Return all available objects.
+Local caching might be used. If MODULE is givven, return only
+objects from that MODULE."
+ (setq proc (or proc (ess-get-process)))
+ (when (stringp proc)
+ (setq proc (get-process proc)))
+ (when (process-live-p proc)
+ (let ((objects (process-get proc 'objects)))
+ (if (process-get proc 'busy)
+ (if obj
+ (assoc obj objects)
+ (process-get proc 'objects))
+ (if obj
+ (or (cdr (assoc obj objects))
+ ;; don't cache composite objects and datatypes
+ (ess-julia--get-components proc obj))
+ ;; this segment is entered when user completon at top level is
+ ;; requested, either Tab or AC. Hence Main is always updated.
+ (let ((modules (ess-get-words-from-vector
+ "ESS.main_modules()\n" nil nil proc))
+ (loc (process-get proc 'last-objects-cache))
+ (lev (process-get proc 'last-eval)))
+ (prog1
+ (apply #'nconc
+ (mapcar
+ (lambda (mod)
+ ;; we are caching all modules, and reinit Main every
+ ;; time user enters commands
+ (copy-sequence
+ (or (and (or (not (equal mod "Main"))
+ (ignore-errors (time-less-p lev loc)))
+ (cdr (assoc mod objects)))
+ (ess-julia--get-components proc mod t))))
+ modules))
+ (process-put proc 'last-objects-cache (current-time)))))))))
+
+(defun ess-julia--get-components (proc obj &optional cache?)
+ (with-current-buffer (ess-command (format "ESS.components(%s)\n" obj)
+ nil nil nil nil proc)
+ (goto-char (point-min))
+ (let (list)
+ (while (re-search-forward
+ "^\\([^ \t\n]+\\) +\\([^ \t\n]+\\)$" nil t)
+ (push (cons (match-string 1) (match-string 2)) list))
+ (when cache?
+ (let ((objects (process-get proc 'objects)))
+ (push (cons obj list) objects)
+ (process-put proc 'objects objects)))
+ list)))
+
+(defun ess-julia-get-object-help-string (sym)
+ "Help string for ac."
+ (let ((proc (ess-get-next-available-process nil t)))
+ (if (null proc)
+ "No free ESS process found"
+ (let ((buf (get-buffer-create " *ess-command-output*")))
+ (with-current-buffer (process-buffer proc)
+ (ess-with-current-buffer buf
+ (ess--flush-help-into-current-buffer sym nil t)))
+ (with-current-buffer buf
+ (ess-help-underline)
+ (goto-char (point-min))
+ (buffer-string))))))
+
+(defvar ac-source-ess-julia-objects
+ '((prefix . ess-symbol-start)
+ (requires . 2)
+ (candidates . ess-ac-julia-objects)
+ (document . ess-julia-get-object-help-string))
+ "Auto-completion source for julia objects")
+
+(defun ess-ac-julia-objects ()
+ (require 'auto-complete)
+ (ess-julia-objects ac-prefix))
+
+(declare-function company-begin-backend "company.el")
+
+(defun company-ess-julia-objects (command &optional arg &rest ignored)
+ (interactive (list 'interactive))
+ (cl-case command
+ (interactive (company-begin-backend 'company-ess-julia-objects))
+ (prefix (unless (company-in-string-or-comment)
+ (let ((start (ess-symbol-start)))
+ (when start (buffer-substring-no-properties start (point))))))
+ (candidates (let ((proc (ess-get-next-available-process)))
+ (when proc
+ (all-completions arg (mapcar (lambda (x) (or (car-safe x) x))
+ (ess-julia-objects arg proc))))))
+ (doc-buffer (company-doc-buffer (ess-julia-get-object-help-string arg)))))
+
+\f
+;;; ERRORS
+(defvar ess-julia-error-regexp-alist '(ess-julia-in ess-julia-at ess-julia-while-load)
+ "List of symbols which are looked up in `compilation-error-regexp-alist-alist'.")
+
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(ess-julia-in "^\\s-*in [^ \t\n]* \\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1))
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(ess-julia-at "^\\S-+\\s-+\\(at \\(.*\\):\\([0-9]+\\)\\)" 2 3 nil 2 1))
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(ess-julia-while-load "^\\s-*\\(while loading\\s-\\(.*\\), in .* on line +\\([0-9]+\\)\\)" 2 3 nil 2 1))
+
+\f
+;;; ELDOC
+(defun ess-julia-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."
+ (interactive)
+ (when (and ess-can-eval-in-background
+ (ess-process-live-p)
+ (not (ess-process-get 'busy)))
+ (let ((funname (or (and ess-eldoc-show-on-symbol ;; aggressive completion
+ (symbol-name (ess-symbol-at-point)))
+ (car (ess--fn-name-start)))))
+ (when funname
+ (let* ((args (copy-sequence (nth 2 (ess-function-arguments funname))))
+ (W (- (window-width (minibuffer-window)) (+ 4 (length funname))))
+ (doc (concat (propertize funname 'face font-lock-function-name-face) ": ")))
+ (when args
+ (setq args (sort args (lambda (s1 s2)
+ (< (length s1) (length s2)))))
+ (setq doc (concat doc (pop args)))
+ (while (and args (< (+ (length doc) (length (car args))) W))
+ (setq doc (concat doc " "
+ (pop args))))
+ (when (and args (< (length doc) W))
+ (setq doc (concat doc " {--}")))
+ doc))))))
+
+\f
+;;; IMENU
+(defvar ess-julia-imenu-generic-expression
+ ;; don't use syntax classes, screws egrep
+ '(("Function (_)" "[ \t]*function[ \t]+\\(_[^ \t\n]*\\)" 1)
+ ("Function" "^[ \t]*function[ \t]+\\([^_][^\t\n]*\\)" 1)
+ ("Const" "[ \t]*const \\([^ \t\n]*\\)" 1)
+ ("Type" "^[ \t]*[a-zA-Z0-9_]*type[a-zA-Z0-9_]* \\([^ \t\n]*\\)" 1)
+ ("Require" " *\\(\\brequire\\)(\\([^ \t\n)]*\\)" 2)
+ ("Include" " *\\(\\binclude\\)(\\([^ \t\n)]*\\)" 2)
+ ))
+
+\f
+;;; CORE
+(defvar ess-julia-customize-alist
+ '((comint-use-prompt-regexp . t)
+ (ess-eldoc-function . 'ess-julia-eldoc-function)
+ (inferior-ess-primary-prompt . "a> ") ;; from julia>
+ (inferior-ess-secondary-prompt . nil)
+ (inferior-ess-prompt . "\\w*> ")
+ (ess-local-customize-alist . 'ess-julia-customize-alist)
+ (inferior-ess-program . inferior-julia-program)
+ (ess-get-help-topics-function . 'ess-julia-get-help-topics)
+ (ess-help-web-search-command . "https://docs.julialang.org/en/latest/search/?q=%s")
+ (ess-manual-lookup-command . 'ess-julia-manual-lookup-function)
+ ;; (ess-reference-lookup-command . 'ess-julia-reference-lookup-function)
+ (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-imenu-generic-expression . ess-julia-imenu-generic-expression)
+ (ess-mode-syntax-table . julia-mode-syntax-table)
+ (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-ac-sources . '(ac-source-ess-julia-objects))
+ (ess-company-backends . '(company-ess-julia-objects))
+ (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-help-filetype . nil)
+ (inferior-ess-exit-command . "exit()\n")
+ ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
+ (inferior-ess-start-file . nil) ;; "~/.ess-R"
+ (inferior-ess-start-args . "")
+ (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 -- set up later than emacs initialization.")
+
+(defvar ess-julia-completion-syntax-table
+ (let ((table (make-syntax-table ess-r-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.")
+
+;;;###autoload
+(define-derived-mode ess-julia-mode julia-mode "ESS[julia]"
+ "Major mode for editing julia source. See `ess-mode' for more help."
+ (ess-mode ess-julia-customize-alist nil t)
+ ;; 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)
+ (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
+ (set (make-local-variable 'end-of-defun-function) 'ess-end-of-function)
+ (setq imenu-generic-expression ess-julia-imenu-generic-expression)
+ (imenu-add-to-menubar "Imenu-jl")
+ (run-mode-hooks 'ess-julia-mode-hook))
+
+(defvar ess-julia-mode-hook nil)
+(defvar ess-julia-post-run-hook nil
+ "Functions run in process buffer after starting julia process.")
+
+;;;###autoload
+(defun julia (&optional start-args)
+ "Call 'julia'.
+Optional prefix (C-u) allows to set command line arguments, such as
+--load=<file>. 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")
+ (setq ess-customize-alist ess-julia-customize-alist)
+ (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))))
+ (inferior-ess jl-start-args)
+
+ (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)
+
+ (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))
+ (with-ess-process-buffer nil
+ (run-mode-hooks 'ess-julia-post-run-hook)))))
+
+(add-to-list 'auto-mode-alist '("\\.jl\\'" . ess-julia-mode))
+
+(provide 'ess-julia)
+;;; ess-julia.el ends here
--- /dev/null
+;;; ess-lsp-l.el --- Support for editing Lisp source code
+
+;; Copyright (C) 1997 A.J. Rossini.
+;; Copyright (C) 1998--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Created: 1 Sept 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+;; Configurations for editing XLispStat source code. Contains any underlying
+;; changes that need to be made.
+
+;;; Code:
+
+\f ; Requires and autoloads
+
+;; Contents "translated" from lisp-mode.el
+(require 'lisp-mode)
+
+\f ; Configuration variables
+
+
+
+(defvar Lisp-editing-alist
+ '((paragraph-start . (concat "^$\\|" page-delimiter))
+ (paragraph-separate . (concat "^$\\|" page-delimiter))
+ (paragraph-ignore-fill-prefix . t)
+ (fill-paragraph-function . 'lisp-fill-paragraph)
+ (adaptive-fill-mode . nil)
+ (indent-line-function . 'lisp-indent-line)
+ (indent-region-function . 'lisp-indent-region)
+ (require-final-newline . mode-require-final-newline)
+ (comment-start . ";")
+ (comment-start-skip . "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
+ (comment-column . 40)
+ (comment-indent-function . 'lisp-comment-indent)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style)
+ (ess-local-process-name . nil)
+ ;;(ess-keep-dump-files . 'ask)
+ (ess-mode-syntax-table . lisp-mode-syntax-table)
+ (font-lock-defaults . '(lisp-font-lock-keywords)))
+ "General options for editing LispStat, XLispStat, and ViSta source files.")
+
+(provide 'ess-lsp-l)
+
+;;; ess-lsp-l.el ends here
--- /dev/null
+;;; ess-mode.el -- Emacs Speaks Statistics (ESS).
+;;
+;; Copyright (C) 1994-2018 ESS Core Team
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+;;
+;; 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:
+;;
+;; A placeholder required by all other mode files.
+;;
+;;; Code:
+
+(require 'ess)
+
+(provide 'ess-mode)
--- /dev/null
+;;; ess-mouse.el --- Support for mouse- or cursor-sensitive actions
+
+;; Copyright (C) 2001 Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Created: 25 Mar 2001
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+\f ; Requires and autoloads
+
+;;*;; Requires
+(require 'mouseme)
+(require 'ess-dde)
+(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 (ess-ddeclient-p) t))
+(defun ess-mouse-me-summary (string)
+ (ess-mouse-me-eval-expanded string "summary(" ")" nil (ess-ddeclient-p) 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 (ess-ddeclient-p) 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 and not using ddeclient, 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 and using ddeclient, 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))
+
+ (if (ess-ddeclient-p)
+ (progn
+ (setq page-scommand (if page
+ (concat "page(" scommand ")")
+ scommand))
+ (set-buffer-file-coding-system 'undecided-dos)
+ (ess-command page-scommand commands-buffer)
+ (if (not value-returned)
+ nil
+ (sleep-for 2)
+ (switch-to-buffer (car (buffer-list)))))
+ (ess-make-buffer-current)
+ (switch-to-buffer 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) (switch-to-buffer (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 (eval ess-mouse-customize-alist))
+ (setq ess-local-process-name lproc-name)
+ (rename-buffer scommand))))
+
+
+\f ; 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
--- /dev/null
+;;; ess-noweb-font-lock-mode.el --- edit noweb files with GNU Emacs
+
+;; Copyright (C) 1999 by Adnan Yaqub (AYaqubNOSPAMorga.com)
+;; and Mark Lunt (mark.luntNOSPAMmrc-bsu.cam.ac.uk
+;; Copyright (C) 2002 by A.J. Rossini <rossiniNOSPAMu.washington.edu>
+;; Copyright (C) 2003--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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}
+;;
+;; <<warning c comment>>=
+;; /* DO NOT EDIT ME! */
+;; /* This file was automatically generated from %W% (%G%). */
+;; @
+;;
+;; <<warning nroff comment>>=
+;; .\" -*- 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 <<warning c comment>> is highlighted in c-mode (the
+;; default noweb code mode), and the chunk <<warning nroff comment>> 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 syntax-begin-function #'ess-noweb-start-of-syntax)
+ (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 (AYaqubNOSPAMorga.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
--- /dev/null
+;;; 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 <normanNOSPAMbellcore.com>
+;; and Mark Lunt <mark.luntNOSPAMmrc-bsu.cam.ac.uk>
+;; and A.J. Rossini <rossiniNOSPAMbiostat.washington.edu>
+;; 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 <ESS-coreNOSPAMr-project.org>
+
+;; 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 --
+
+\f
+;;; 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
+;;
+;; @
+;; <<foo>>=
+;; int foo;
+;; @ %def foo
+;; Here starts a new documentation chunk!
+;; <<bar>>=
+;; 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
+;;
+\f
+
+;;; 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)
+
+(defvar weave-process)
+
+\f
+;;; Variables
+
+;; (defconst ess-noweb-mode-RCS-Id
+;; "Imported to ESS Subversion repository and RCS ids not maintained.")
+
+;; (defconst ess-noweb-mode-RCS-Name
+;; " ")
+
+(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 ())
+
+\f
+;;; 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))))
+
+\f
+;;; 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...")))
+
+\f
+;;; 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)))
+\f
+;;; 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)))
+
+\f
+;;; 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))))
+
+\f
+;;; 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))))
+
+\f
+;;; 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 \"<<NAME>>\"."
+ (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))))
+
+\f
+;;; 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))))
+
+\f
+;;; 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.")))
+\f
+;;; Misc
+
+(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)))))))
+
+\f
+;;; Debugging
+
+(defun ess-noweb-log (s)
+ (let ((b (current-buffer)))
+ (switch-to-buffer (get-buffer-create "*noweb-log*"))
+ (goto-char (point-max))
+ (setq buffer-read-only nil)
+ (insert s)
+ (setq buffer-read-only t)
+ (switch-to-buffer 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
+
+\f
+;;; Finale
+
+(run-hooks 'ess-noweb-mode-load-hook)
+(provide 'ess-noweb-mode)
+
+;; Changes made by Mark Lunt (mark.luntNOSPAMmrc-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
+;; (AYaqubNOSPAMorga.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
--- /dev/null
+;;; 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 <mark.luntNOSPAMmrc-bsu.cam.ac.uk>
+;; A.J. Rossini <rossiniNOSPAMu.washington.edu>
+;; Created: April 18, 1999
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+\f ; Requires and autoloads
+
+(require 'ess-custom)
+(require 'ess-inf)
+(require 'ess-noweb-mode)
+
+\f ; 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))
+
+\f ; Functions
+
+;;*;; Code Chunk evaluation.
+
+(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-create-temp-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:
+;; <<thing1>>=
+;; code for thing1
+;; @
+;; Documentation
+;; <<thing1>>=
+;; 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-create-temp-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))
+
+\f ; Provide package
+
+(provide 'ess-noweb)
+
+;;; ess-noweb.el ends here
--- /dev/null
+;;; ess-omg-d.el --- Omega customization
+
+;; Copyright (C) 1999 A. J. Rossini
+;; Copyright (C) 2000--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMbiostat.washington.edu>
+;; Created: 15 August 1999
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+;;; Requires and Autoloads:
+
+(require 'ess-omg-l)
+(require 'ess-trns)
+
+(defvar OMG-dialect-name "OMG"
+ "Name of 'dialect' for Omega.") ;easily changeable in a user's .emacs
+
+(defvar OMG-customize-alist
+ '((ess-local-customize-alist . 'OMG-customize-alist)
+ (ess-language . "OMG")
+ (ess-dialect . "omegahat")
+ (ess-suffix . "omg")
+ (ess-loop-timeout . 5000)
+ (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 . OMG-editing-alist)
+ (ess-mode-syntax-table . OMG-syntax-table)
+ (ess-change-sp-regexp . "");fixme (if omegahat ever ..)
+ (ess-help-sec-regex . ess-help-S+-sec-regex)
+ (ess-help-sec-keys-alist . ess-help-S+sec-keys-alist)
+ (ess-object-name-db-file . "ess-omg-namedb.el" )
+ (inferior-ess-program . inferior-OMG-program)
+ (inferior-ess-objects-command . "objects(%d)\n")
+ (inferior-ess-help-command . "help(\"%s\",pager=\"cat\",window=F)\n")
+ (inferior-ess-exit-command . "q()\n")
+ (inferior-ess-primary-prompt . "\\[[0-9]*\\]")
+ (inferior-ess-secondary-prompt . ".. ?")
+ (comint-use-prompt-regexp . t)
+ (inferior-ess-start-file . nil) ;"~/.ess-omg")
+ (inferior-ess-start-args . ""))
+ "Variables to customize for OMG (Omegahat)")
+
+
+(defun OMG (&optional start-args) ; proc-name)
+ "Call Omegahat, from the Omega Group for Statistical Computing."
+ (interactive "P")
+ (setq ess-customize-alist OMG-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(OMG): ess-dialect=%s, buf=%s\n"
+ ess-dialect
+ (current-buffer)))
+ (let ((omg-start-args
+ (concat inferior-ess-start-args
+ (if start-args (read-string
+ "Starting Args [possibly -CORBA] ? ")
+ nil))))
+ (inferior-ess omg-start-args)))
+
+
+
+(fset 'omegahat 'OMG)
+
+;;;###autoload
+(defun OMG-mode (&optional proc-name)
+ "Major mode for editing Omegahat source. NOT EVEN STARTED."
+ (interactive)
+ (setq ess-customize-alist OMG-customize-alist)
+ (ess-mode OMG-customize-alist proc-name)
+ ;;(java-mode)
+ (setq major-mode 'OMG-mode))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.omg\\'" . omegahat-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.hat\\'" . omegahat-mode))
+
+(fset 'omegahat-mode 'OMG-mode)
+
+(defun OMG-transcript-mode ()
+ "Omegahat transcript mode."
+ (interactive)
+ (ess-transcript-mode OMG-customize-alist))
+
+\f ; Provide package
+
+(provide 'ess-omg-d)
+
+;;; ess-omg-d.el ends here
--- /dev/null
+;;; ess-omg-l.el --- Support for editing Omega source code
+
+;; Copyright (C) 1999--2001 A.J. Rossini.
+;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMu.washington.edu>
+;; Created: 15 Aug 1999
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 Omega source code. This is initially
+;; based upon the similarities between Omega and S, but will need to
+;; diverge to incorporate the use of Java-style coding.
+
+;;; Code:
+
+(require 'ess-s-lang)
+
+\f ; Specialized functions
+
+(defun OMG-comment-indent ()
+ "Indentation for Omega comments."
+
+ (if (looking-at "////")
+ (current-column)
+ (if (looking-at "///")
+ (let ((tem (ess-calculate-indent)))
+ (if (listp tem) (car tem) tem))
+ (skip-chars-backward " \t")
+ (max (if (bolp) 0 (1+ (current-column)))
+ comment-column))))
+
+;; (defun OMG-indent-line ()
+;; "Indent current line as Omega code.
+;; Return the amount the indentation changed by."
+;; (let ((indent (ess-calculate-indent nil))
+;; beg shift-amt
+;; (case-fold-search nil)
+;; (pos (- (point-max) (point))))
+;; (beginning-of-line)
+;; (setq beg (point))
+;; (cond ((eq indent nil)
+;; (setq indent (current-indentation)))
+;; (t
+;; (skip-chars-forward " \t")
+;; (if (and ess-indent-with-fancy-comments (looking-at "////"))
+;; (setq indent 0))
+;; (if (and ess-indent-with-fancy-comments
+;; (looking-at "//")
+;; (not (looking-at "///")))
+;; (setq indent comment-column)
+;; (if (eq indent t) (setq indent 0))
+;; (if (listp indent) (setq indent (car indent)))
+;; (cond ((and (looking-at "else\\b")
+;; (not (looking-at "else\\s_")))
+;; (setq indent (save-excursion
+;; (ess-backward-to-start-of-if)
+;; (+ ess-else-offset
+;; (current-indentation)))))
+;; ((= (following-char) ?})
+;; (setq indent
+;; (+ indent
+;; (- ess-close-brace-offset ess-indent-offset))))
+;; ((= (following-char) ?{)
+;; (setq indent (+ indent ess-brace-offset)))))))
+;; (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.
+;; (if (> (- (point-max) pos) (point))
+;; (goto-char (- (point-max) pos))))
+;; shift-amt))
+
+
+;; (defun OMG-calculate-indent (&optional parse-start)
+;; "Return appropriate indentation for current line as Omega 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))
+;; (case-fold-search nil)
+;; state
+;; containing-sexp)
+;; (if parse-start
+;; (goto-char parse-start)
+;; (beginning-of-defun))
+;; (while (< (point) indent-point)
+;; (setq parse-start (point))
+;; (setq state (parse-partial-sexp (point) indent-point 0))
+;; (setq containing-sexp (car (cdr state))))
+;; (cond ((or (nth 3 state) (nth 4 state))
+;; ;; return nil or t if should not change this line
+;; (nth 4 state))
+;; ((null containing-sexp)
+;; ;; Line is at top level. May be data or function definition,
+;; (beginning-of-line)
+;; (if (and (/= (following-char) ?\{)
+;; (save-excursion
+;; (ess-backward-to-noncomment (point-min))
+;; (ess-continued-statement-p)))
+;; ess-continued-statement-offset
+;; 0)) ; Unless it starts a function body
+;; ((/= (char-after containing-sexp) ?{)
+;; ;; line is expression, not statement:
+;; ;; indent to just after the surrounding open.
+;; (goto-char containing-sexp)
+;; (let ((bol (save-excursion (beginning-of-line) (point))))
+
+;; ;; modified by shiba@isac 7.3.1992
+;; (cond ((and (numberp ess-expression-offset)
+;; (re-search-backward "[ \t]*expression[ \t]*" bol t))
+;; ;; This regexp match every "expression".
+;; ;; modified by shiba
+;; ;;(forward-sexp -1)
+;; (beginning-of-line)
+;; (skip-chars-forward " \t")
+;; ;; End
+;; (+ (current-column) ess-expression-offset))
+;; ((and (numberp ess-arg-function-offset)
+;; (re-search-backward
+;; "=[ \t]*\\s\"*\\(\\w\\|\\s_\\)+\\s\"*[ \t]*"
+;; bol
+;; t))
+;; (forward-sexp -1)
+;; (+ (current-column) ess-arg-function-offset))
+;; ;; "expression" is searched before "=".
+;; ;; End
+
+;; (t
+;; (progn (goto-char (1+ containing-sexp))
+;; (current-column))))))
+;; (t
+;; ;; Statement level. Is it a continuation or a new statement?
+;; ;; Find previous non-comment character.
+;; (goto-char indent-point)
+;; (ess-backward-to-noncomment containing-sexp)
+;; ;; Back up over label lines, since they don't
+;; ;; affect whether our line is a continuation.
+;; (while (eq (preceding-char) ?\,)
+;; (ess-backward-to-start-of-continued-exp containing-sexp)
+;; (beginning-of-line)
+;; (ess-backward-to-noncomment containing-sexp))
+;; ;; Now we get the answer.
+;; (if (ess-continued-statement-p)
+;; ;; This line is continuation of preceding line's statement;
+;; ;; indent ess-continued-statement-offset more than the
+;; ;; previous line of the statement.
+;; (progn
+;; (ess-backward-to-start-of-continued-exp containing-sexp)
+;; (+ ess-continued-statement-offset (current-column)
+;; (if (save-excursion (goto-char indent-point)
+;; (skip-chars-forward " \t")
+;; (eq (following-char) ?{))
+;; ess-continued-brace-offset 0)))
+;; ;; This line starts a new statement.
+;; ;; Position following last unclosed open.
+;; (goto-char containing-sexp)
+;; ;; Is line first statement after an open-brace?
+;; (or
+;; ;; If no, find that first statement and indent like it.
+;; (save-excursion
+;; (forward-char 1)
+;; (while (progn (skip-chars-forward " \t\n")
+;; (looking-at "//"))
+;; ;; Skip over comments following openbrace.
+;; (forward-line 1))
+;; ;; The first following code counts
+;; ;; if it is before the line we want to indent.
+;; (and (< (point) indent-point)
+;; (current-column)))
+;; ;; If no previous statement,
+;; ;; indent it relative to line brace is on.
+;; ;; For open brace in column zero, don't let statement
+;; ;; start there too. If ess-indent-offset is zero,
+;; ;; use ess-brace-offset + ess-continued-statement-offset instead.
+;; ;; For open-braces not the first thing in a line,
+;; ;; add in ess-brace-imaginary-offset.
+;; (+ (if (and (bolp) (zerop ess-indent-offset))
+;; (+ ess-brace-offset ess-continued-statement-offset)
+;; ess-indent-offset)
+;; ;; Move back over whitespace before the openbrace.
+;; ;; If openbrace is not first nonwhite thing on the line,
+;; ;; add the ess-brace-imaginary-offset.
+;; (progn (skip-chars-backward " \t")
+;; (if (bolp) 0 ess-brace-imaginary-offset))
+;; ;; If the openbrace is preceded by a parenthesized exp,
+;; ;; move to the beginning of that;
+;; ;; possibly a different line
+;; (progn
+;; (if (eq (preceding-char) ?\))
+;; (forward-sexp -1))
+;; ;; Get initial indentation of the line we are on.
+;; (current-indentation))))))))))
+
+
+
+
+(defvar OMG-syntax-table nil "Syntax table for Omegahat code.")
+(if S-syntax-table
+ nil
+ (setq 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)
+ ;;FIXME: This fails (warning in compilation):
+ ;;F "//" are 2 characters; ?// is invalid
+ ;;F NEXT LINE IS BOGUS IN XEMACS, AJR
+ ;;F (modify-syntax-entry ?// "<" S-syntax-table) ; open comment
+ ;;F (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.bar$hack is 1 symbol
+ (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))
+
+
+(defvar OMG-editing-alist
+ '((paragraph-start . (concat "^$\\|" page-delimiter))
+ (paragraph-separate . (concat "^$\\|" page-delimiter))
+ (paragraph-ignore-fill-prefix . t)
+ (require-final-newline . mode-require-final-newline)
+ (comment-start . "//")
+ (comment-start-skip . "//+ *")
+ (comment-column . 40)
+ ;;(comment-indent-function . 'S-comment-indent)
+ ;;(ess-comment-indent . 'S-comment-indent)
+ ;;(ess-indent-line . 'S-indent-line)
+ ;;(ess-calculate-indent . 'ess-calculate-indent)
+ (indent-line-function . 'ess-indent-line)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style)
+ (ess-local-process-name . nil)
+ ;;(ess-keep-dump-files . 'ask)
+ (ess-mode-syntax-table . S-syntax-table)
+ (font-lock-defaults . '(ess-OMG-font-lock-defaults
+ nil nil ((?\. . "w")))))
+ "General options for Omegahat source files.")
+
+(defvar ess-OMG-font-lock-defaults
+ (append (list
+ (cons "\\b[0-9]+\\b" 'font-lock-type-face) ; numbers
+ (cons (regexp-opt ess-S-keywords 'words) 'font-lock-keyword-face))
+ (list
+ (cons (regexp-opt ess-S-assign-ops)
+ 'font-lock-constant-face) ; assign
+ (cons (regexp-opt ess-S-constants 'words)
+ 'font-lock-type-face) ; constants
+ (cons (regexp-opt ess-S-modifiers 'words)
+ 'font-lock-constant-face) ; modify search list or source
+
+ (cons ess-S-function-name-regexp
+ '(1 font-lock-function-name-face keep))
+ ; function name
+ (cons "\\s.\\|\\s(\\|\\s)" 'font-lock-function-name-face)
+ ;punctuation and parents (same as function not to cause vidual disturbance)
+ )) ; keywords
+ "Font-lock patterns used in `OMG' buffers.")
+
+
+;;; Changes from S to S-PLUS 3.x. (standard S3 should be in ess-s-lang.el !).
+
+(defconst OMG-help-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.
+
+(defconst ess-help-OMG-sec-regex "^[A-Z. ---]+:$"
+ "Reg(ular) Ex(pression) of section headers in help file")
+
+;;; S-mode extras of Martin Maechler, Statistik, ETH Zurich.
+
+;;>> Moved things into --> ./ess-utils.el
+
+(provide 'ess-omg-l)
+
+;;; ess-omg-l.el ends here
--- /dev/null
+(define-package "ess" "20181109.703" "Emacs Speaks Statistics"
+ '((julia-mode "0.3"))
+ :authors
+ '(("David Smith" . "dsmithNOSPAMstats.adelaide.edu.au")
+ ("A.J. Rossini" . "blindglobeNOSPAMgmail.com")
+ ("Richard M. Heiberger" . "rmhNOSPAMtemple.edu")
+ ("Kurt Hornik" . "Kurt.HornikNOSPAMR-project.org")
+ ("Martin Maechler" . "maechlerNOSPAMstat.math.ethz.ch")
+ ("Rodney A. Sparapani" . "rsparapaNOSPAMmcw.edu")
+ ("Stephen Eglen" . "stephenNOSPAMgnu.org")
+ ("Sebastian P. Luque" . "spluqueNOSPAMgmail.com")
+ ("Henning Redestig" . "henning.redNOSPAMgooglemail.com")
+ ("Vitalie Spinu" . "spinuvitNOSPAMgmail.com")
+ ("Lionel Henry" . "lionel.hryNOSPAMgmail.com")
+ ("J. Alexander Branham" . "alex.branhamNOSPAMgmail.com"))
+ :maintainer
+ '("ESS Core Team" . "ESS-coreNOSPAMr-project.org"))
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; ess-r-a.el -- Possible local customizations for R with ESS.
+
+;; Copyright (C) 1997--2005 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <blindglobeNOSPAMgmail.com>
+;; Created: 17 November 1999
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 &optional message)
+ "Send the current region 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))
+
+
+\f ; Provide package
+
+(provide 'ess-r-a)
+
+;;; ess-r-a.el ends here
--- /dev/null
+;;; ess-r-completion.el --- R completion
+;;
+;; 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 <ESS-coreNOSPAMr-project.org>
+;;
+;; 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:
+
+\f
+;;; ElDoc
+
+(require 'cl-lib)
+(require 'ess-utils)
+(require 'ess-inf)
+(require 'ess-help)
+
+(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")
+
+(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."
+ (interactive)
+ (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)))))
+ newdoc)
+ (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))))
+
+\f
+;;; 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 `ess-language' object preceding point.
+Uses \\[ess-r-complete-object-name] when `ess-use-R-completion' is non-nil,
+or \\[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)))
+
+(defun ess-list-object-completions nil
+ "List all possible completions of the object name at point."
+ (interactive)
+ (ess-complete-object-name))
+
+(defun ess-complete-object-name-deprecated ()
+ "Gives a deprecated message."
+ (interactive)
+ (ess-complete-object-name)
+ (message "C-c TAB is deprecated, completions has been moved to [M-TAB] (aka C-M-i)")
+ (sit-for 2 t))
+
+;; 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."
+ (interactive)
+ (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)"
+ (ess-quote-special-chars prefix)
+ (- end start)))
+ (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."
+ (interactive)
+ (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
+ (cddar ess-sl-modtime-alist) ; .GlobalEnv
+ (mapcar 'cddr ess--cached-sp-objects)))))
+
+\f
+;;; ARGUMENTS
+
+(define-obsolete-variable-alias 'ess-ac-R-argument-suffix 'ess-R-argument-suffix "15.3")
+(defcustom ess-R-argument-suffix " = "
+ "Suffix appended by `ac-source-R' and `ac-source-R-args' to candidates."
+ :group 'R
+ :type 'string)
+
+(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.")
+
+\f
+;;; 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 t)))
+ (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)))))))
+
+\f
+;;; 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)))))
+
+(defvar-local ess-r--installed-packages-cache nil)
+
+(defun ess-r-installed-packages ()
+ "Return a list of currently installed R packages.
+The value is cached once per session and is not updated if new
+packages are installed."
+ (let ((proc (ess-get-next-available-process)))
+ (when proc
+ (with-current-buffer (process-buffer proc)
+ (or ess-r--installed-packages-cache
+ (setq ess-r--installed-packages-cache
+ (ess-get-words-from-vector
+ "print(unlist(lapply(.libPaths(), dir)), max=1e6)\n")))))))
+
+;; completion for library names -- only active within 'library(...)'
+(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 'symbol))
+ '("library" "require"))
+ (let ((start (ess-symbol-start)))
+ (and start (buffer-substring start (point))))))
+ (candidates (all-completions arg (ess-r-installed-packages)))
+ (annotation "<pkg>")
+ (duplicates nil)
+ (sorted t)))
+
+\f
+;;; AC SOURCES
+;;; http://cx4a.org/software/auto-complete/index.html
+
+(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 annoing in inferior buffers)
+ (document . ess-ac-help))
+ "Combined ad-completion source for R function arguments and R objects.")
+
+(defun ess-ac-start ()
+ (when (ess-process-live-p)
+ (or (ess-arg-start)
+ (ess-symbol-start))))
+
+(defun ess-ac-candidates ()
+ "OBJECTS + ARGS."
+ (let ((args (ess-ac-args)))
+ ;; sort of intrusive but right
+ (if (and ac-auto-start
+ (< (length ac-prefix) ac-auto-start))
+ args
+ (if args
+ (append args (ess-ac-objects t))
+ (ess-ac-objects)))))
+
+(defun ess-ac-help (sym)
+ (if (string-match-p "= *\\'" sym)
+ (ess-r-get-arg-help-string sym)
+ (ess-r-get-object-help-string sym)))
+
+;; 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.")
+
+(defun ess-ac-objects (&optional no-kill)
+ "Get all cached objects."
+ (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.")
+
+(defun ess-ac-args ()
+ "Get the args of the function when inside parentheses."
+ (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
+ (set (make-local-variable 'ac-use-comphist) nil)
+ (kill-local-variable 'ac-use-comphist))
+ (delete "..." args)
+ (mapcar (lambda (a) (concat a ess-R-argument-suffix))
+ args))))
+
+(defvar ess--ac-help-arg-command
+ "getArgHelp('%s','%s')")
+
+(provide 'ess-r-completion)
+
+;;; ess-r-completion.el ends here
--- /dev/null
+;;; 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 <ESS-coreNOSPAMr-project.org>
+;;
+;; 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 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-custom)
+(require 'ess-inf)
+(require 'flymake)
+;; TODO: When remove support for Emacs 24, remove the nil t:
+(require 'project nil t)
+
+(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.2') {
+ cat('@@error: @@Need `lintr` version > v1.0.2')
+ } 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."
+ (cond (;; current directory
+ (file-readable-p (expand-file-name ".lintr" default-directory))
+ (expand-file-name ".lintr" default-directory))
+ ;; Project root
+ ((and (fboundp 'ess-r-package-project)
+ (ess-r-package-project)) (expand-file-name ".lintr" (cdr (ess-r-package-project))))
+ ((and (fboundp 'project-roots) ; checking that project-roots is defined can be removed when drop Emacs 24
+ (project-current)
+ (project-roots (project-current)))
+ (expand-file-name ".lintr" (car (project-roots (project-current)))))
+ ;; Home directory
+ ((file-readable-p (expand-file-name ".lintr" (getenv "HOME")))
+ (expand-file-name ".lintr" (getenv "HOME")))))
+
+(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 "<text>:"
+ ;; 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-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
--- /dev/null
+;;; ess-r-gui.el --- Run Rgui on Windows as an inferior Emacs process
+
+;; Copyright (C) 2008 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Created: 10 Mar 2008
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+;; In Rgui:
+;; > library(tcltk2) ## >= 1.0-6
+;; > .ess.command <- function() source("c:/temp/ess-tempfile.R", echo=TRUE)
+;; > tclFun(.ess.command)
+;; [1] "R_call 0203A04C"
+
+;;; Code:
+
+(require 'ess-dde) ;; needed here because we override several definitions
+(require 'ess-r-mode)
+
+(defun ess-ddeclient-p ()
+ "Returns the name of the ddeclient iff `ess-local-process-name'
+is associated with an `inferior-ess-ddeclient', and nil if the
+ess-process is running as an ordinary inferior process. Alway
+nil on Unix machines."
+ (interactive)
+ (if ess-microsoft-p
+ (let ((ess-ddeclient (ess-get-process-variable 'inferior-ess-ddeclient)))
+ (if (not (equal ess-ddeclient (default-value 'inferior-ess-ddeclient)))
+ ess-ddeclient))))
+
+(defvar ess-command-file "c:/temp/ess-tempfile.R"
+ "File name for communication with Rgui.")
+(defvar inferior-ess-execdde
+ (concat (getenv "R_HOME") "/site-library/tcltk2/bin/execdde.exe")
+ "Full pathname to execdde executable.")
+(defvar ess-rgui-command " -s TclEval -t R -c .ess.command > NUL"
+ "Command to `inferior-ess-execdde' that will make Rgui read the command file.")
+
+
+(defun ess-eval-region-execdde (start end even-empty)
+ "Loop through lines in region and send them to ESS via execdde."
+ (setq ;; set the following variables for the current ddeESS process.
+ inferior-ess-ddeclient (ess-get-process-variable 'inferior-ess-ddeclient)
+ )
+ (write-region start end ess-command-file nil nil 'no-message)
+ (call-process-shell-command
+ (concat inferior-ess-execdde ess-rgui-command))
+ )
+
+
+(if (not (getenv "R_HOME")) (setenv "R_HOME" "c:/progra~1/R/R-2.6.1"))
+;; ^^^^^^^^^ FIXME! do something better
+(defvar inferior-Rgui-program "cmd" "Rgui program name")
+(defvar Rgui-pager "emacsclientw.exe" "Rgui pager program")
+(defvar inferior-ess-language-start-rgui
+ "options(chmhelp=FALSE, htmlhelp=FALSE, help_type='text'); require(tcltk2)"
+ "additional arguments to rgui")
+
+(defun ess-dde-rgui-send-region (proc start end &optional visibly message)
+ "Loop through lines in region and send them to ESS via ddeclient.
+
+PROC, VISIBLY and MESSAGE are ignored."
+ (setq ;; set the following variables for the current ddeESS process.
+ inferior-ess-ddeclient (ess-get-process-variable 'inferior-ess-ddeclient)
+ inferior-ess-client-name (ess-get-process-variable 'inferior-ess-client-name)
+ inferior-ess-client-command (ess-get-process-variable 'inferior-ess-client-command))
+ (narrow-to-region start end)
+ (goto-char (point-min))
+
+ (if (equal inferior-ess-ddeclient "execdde")
+ (ess-eval-region-execdde start end 'even-empty)
+
+ (let ((beg))
+ (while (or (< (point) (point-max))
+ (= 1 (point-max)))
+ (setq beg (point))
+ (end-of-line)
+ ;; call-process-region won't send over a 0-character line.
+ ;; We go outside the loop to create a 1-character line " " in the
+ ;; *ESS-temporary* buffer
+ (if (= beg (point)) ;; do empty line outside loop
+ (ess-dde-eval-linewise " " nil 'eob t)
+ (call-process-region
+ beg (point)
+ inferior-ess-ddeclient nil nil nil
+ inferior-ess-client-name inferior-ess-client-command))
+ (forward-line 1))))
+ (widen))
+
+
+
+(defvar Rgui-customize-alist
+ (append
+ '((ess-local-customize-alist . 'Rgui-customize-alist)
+ (ess-dialect . "R")
+ (ess-suffix . "R")
+ (ess-dump-filename-template . (replace-regexp-in-string
+ "S$" ess-suffix ; in the one from custom:
+ ess-dump-filename-template-proto))
+ (ess-mode-syntax-table . ess-r-syntax-table)
+ (ess-mode-editing-alist . ess-r-editing-alist)
+ (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-send-region-function . #'ess-dde-rgui-send-region)
+ (ess-load-file-function . #'ess-dde-load-file)
+ (ess-command-function . #'ess-dde-command)
+ (ess-eval-linewise-function . #'ess-dde-eval-linewise)
+ (ess-dump-object-function . #'ess-dde-dump-object)
+ (ess-read-object-name-function . #'ess-dde-read-object-name)
+ (ess-find-help-file-function . #'ess-dde-find-help-file)
+ (ess-display-help-on-object-function . #'ess-dde-display-help-on-object)
+ (inferior-ess-program . inferior-Rgui-program)
+ (inferior-ess-objects-command . inferior-ess-r-objects-command)
+ (inferior-ess-font-lock-keywords . 'inferior-ess-r-font-lock-keywords)
+ (inferior-ess-search-list-command . "search()\n")
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . nil) ;; "chm") ;;?
+ (inferior-ess-exit-command . "q()")
+ (inferior-ess-exit-prompt . "Save workspace image? [y/n/c]: ")
+ (inferior-ess-primary-prompt . "\\([A-Z/][][A-Za-z0-9./]*\\)*[>$] ")
+ (inferior-ess-secondary-prompt . "+ ?")
+ ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
+ (inferior-ess-start-file . nil) ;; "~/.ess-R"
+ (inferior-ess-start-args . "")
+ (inferior-ess-ddeclient . "execdde")
+ (ess-STERM . "ddeSS")
+ (ess-editor . ess-r-editor)
+ (ess-pager . Rgui-pager)
+ )
+ S-common-cust-alist)
+ "Variables to customize for Rgui")
+
+
+(defun Rgui (&optional proc-name)
+ "Call 'Rgui for Windows'. Put R in an independent MS-Window (R
+persists even if the '(ddeESS [R])' window is killed in emacs).
+Do this by creating a comint process that calls cmd. This is a
+placeholder buffer with mode '(ddeESS [R])'. Commands sent from
+an (ESS[S] [R]) buffer to this process will be sourced into the
+independent Rgui R Console."
+ (interactive)
+ (save-excursion
+ (setq ess-customize-alist Rgui-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(Rgui): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (when
+ ;; Silence byte compiler warns about this function
+ (fboundp 'w32-short-file-name)
+ (let ((default-ddeclient (default-value 'inferior-ess-ddeclient)))
+ (cd (w32-short-file-name (directory-file-name default-directory)))
+ ;; (setenv "S_PROJ" default-directory)
+ (setq-default inferior-ess-ddeclient "execdde")
+ (inferior-ess)
+ (setq-default inferior-ess-ddeclient default-ddeclient)
+ (sleep-for 2) ; need to wait, else working too fast!
+ ))
+ (setq comint-process-echoes nil)
+
+ ;; *R* buffer
+ (goto-char (point-min))
+ (insert
+ "This is a placeholder buffer. You can't type anything here.\n
+You may ignore the 'options' error in this buffer.\n\n")
+ (goto-char (point-max))
+ (set-process-coding-system (get-process ess-local-process-name) 'raw-text-dos 'raw-text-unix)
+ (setq buffer-read-only t) ; force buffer to be read-only
+ (setq mode-name "ddeESS")
+
+ ;; initialization
+ (set-buffer (find-file-noselect ess-command-file 'nowarn))
+ (erase-buffer)
+ (setq ;; set the following variables for the current ddeESS process.
+ inferior-ess-language-start (ess-get-process-variable 'inferior-ess-language-start))
+ (if inferior-ess-language-start
+ (insert inferior-ess-language-start))
+ (if inferior-ess-language-start-rgui
+ (insert (concat "\n" inferior-ess-language-start-rgui)))
+ (save-buffer 0)
+ (call-process-shell-command
+ (concat inferior-ess-execdde ess-rgui-command))
+ ))
+
+;;; ess-r-gui.el ends here
--- /dev/null
+;;; 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 <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+(require 'cl-lib)
+(require 'compile)
+(require 'easymenu)
+(require 'eldoc)
+(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)
+(when (>= emacs-major-version 25) (require 'ess-r-xref)) ;; Xref API was added in Emacs 25.1
+;; TODO: Remove when we drop support for Emacs 24:
+(declare-function ess-r-xref-backend "ess-r-xref")
+(when (>= emacs-major-version 26) (require 'ess-r-flymake)) ; Flymake rewrite in Emacs 26
+
+;; 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)
+(defvar start-pos)
+(defvar style)
+(defvar type)
+
+
+\f
+;;*;; Mode definition
+
+;;;*;;; UI (Keymaps / Menus)
+;;;###autoload
+(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 [(control ?D)] '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 [(control ?B)] '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-package-set-package)
+ (define-key ess-r-package-dev-map "s" 'ess-r-package-set-package)
+ (define-key ess-r-package-dev-map "\C-a" 'ess-r-devtools-ask)
+ (define-key ess-r-package-dev-map "a" 'ess-r-devtools-ask)
+ (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")
+
+
+;; Inherit from the S syntax table:
+(defvar ess-r-syntax-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 ?` "\"" ess-r-syntax-table)
+(modify-syntax-entry ?% "\"" ess-r-syntax-table)
+
+;; Underscore is valid in R symbols
+(modify-syntax-entry ?_ "_" ess-r-syntax-table)
+(modify-syntax-entry ?: "." ess-r-syntax-table)
+(modify-syntax-entry ?@ "." ess-r-syntax-table)
+(modify-syntax-entry ?$ "." ess-r-syntax-table)
+
+;; TOTHINK: Prevent string delimiting characters from messing up output in the
+;; inferior buffer
+(defvar inferior-ess-r-syntax-table (copy-syntax-table ess-r-syntax-table))
+(modify-syntax-entry ?\' "." inferior-ess-r-syntax-table)
+;; (modify-syntax-entry ?\" "." inferior-ess-r-syntax-table)
+;; (modify-syntax-entry ?` "." inferior-ess-r-syntax-table)
+(modify-syntax-entry ?% "." inferior-ess-r-syntax-table)
+
+(defvar ess-r-completion-syntax-table
+ (let ((table (make-syntax-table ess-r-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)
+ (let ((string-end (save-excursion
+ (and (nth 3 state)
+ (ess-goto-char (nth 8 state))
+ (ess-forward-sexp)
+ (point)))))
+ (when (eq (nth 3 state) ?`)
+ (put-text-property (nth 8 state) string-end 'ess-r-backquoted t))
+ (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)
+ ((nth 3 state)
+ font-lock-string-face)
+ (t
+ 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-ac-sources . ess-r-ac-sources)
+ (ess-company-backends . ess-r-company-backends)
+ (ess-build-tags-command . ess-r-build-tags-command)
+ (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-format-eval-command-function . #'ess-r-format-eval-command)
+ (ess-format-load-command-function . #'ess-r-format-load-command)
+ (ess-send-region-function . #'ess-r-send-region)
+ (ess-load-file-function . #'ess-r-load-file)
+ (ess-make-source-refd-command-function . #'ess-r-make-source-refd-command)
+ (ess-format-eval-message-function . #'ess-r-format-eval-message)
+ (ess-install-library-function . #'ess-r-install-library)
+ (ess-eldoc-function . #'ess-r-eldoc-function)
+ (ess-help-web-search-command . #'ess-r-sos)
+ (ess-build-help-command-function . #'ess-r-build-help-command)
+ (ess-dump-filename-template . ess-r-dump-filename-template)
+ (ess-mode-editing-alist . ess-r-editing-alist)
+ (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-help-filetype . nil)
+ (inferior-ess-exit-command . "q()")
+ (inferior-ess-exit-prompt . "Save workspace image? [y/n/c]: ")
+ (inferior-ess-start-file . nil)
+ (inferior-ess-start-args . "")
+ (inferior-ess-mode-syntax-table . inferior-ess-r-syntax-table)
+ (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)
+ (ess-mode-syntax-table . ess-r-syntax-table)
+ (font-lock-syntactic-face-function . #'ess-r-font-lock-syntactic-face-function)
+ (prettify-symbols-alist . ess-r-prettify-symbols))
+ S-common-cust-alist)
+ "Variables to customize for R -- set up later than Emacs initialization.")
+
+;; VS[24-08-2018]: FIXME: make initialization of custom-alist tail-to-top and
+;; put this into the above alist
+(setcdr (assoc 'ess-font-lock-keywords ess-r-customize-alist)
+ (quote 'ess-R-font-lock-keywords))
+(setcdr (assoc 'inferior-ess-font-lock-keywords ess-r-customize-alist)
+ (quote 'inferior-ess-r-font-lock-keywords))
+
+(defvar ess-r-build-tags-command
+ "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)))
+
+(defvar ess-r-editing-alist
+ ;; copy the S-alist and modify :
+ (let ((S-alist (copy-alist S-editing-alist)))
+ (setcdr (assoc 'ess-mode-syntax-table S-alist)
+ (quote ess-r-syntax-table))
+ S-alist)
+ "General options for editing R source files.")
+
+(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'.")
+
+;; Takes precidence over R1 below in english locales, and allows spaces in file path
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(R "\\(\\(?: at \\|(@\\)\\([^#()\n]+\\)[#:]\\([0-9]+\\)\\)" 2 3 nil 2 1))
+
+(add-to-list 'compilation-error-regexp-alist-alist
+ ;; valgrind style (stl_numeric.h:183)
+ '(R1 "(\\([^ ):\n]+\\):\\([0-9]+\\)?)" 1 2 nil 2))
+
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(R2 "(\\(\\w+ \\([^())\n]+\\)#\\([0-9]+\\)\\))" 2 3 nil 2 1))
+
+;; Precedes R4 and allows spaces in file path
+(add-to-list 'compilation-error-regexp-alist-alist
+ ;; 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))
+
+(add-to-list 'compilation-error-regexp-alist-alist
+ ;; Don't start with digit; no spaces
+ '(R4 "\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1))
+
+(add-to-list 'compilation-error-regexp-alist-alist
+ '(R-recover " *[0-9]+: +\\([^:\n\t]+?\\)#\\([0-9]+:\\)" 1 2 nil 2 1))
+
+;; gnu C errors
+;; (add-to-list 'compilation-error-regexp-alist-alist
+;; '(R_C "^\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 2 3 nil 2 1))
+
+
+(defvar ess-r-versions
+ (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 `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 `M-x 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 `exec-path' more than once), they are
+ignored by calling `ess-uniq-list'.
+Set this variable to nil to disable searching for other versions of R.
+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-r-versions-created 'ess-r-created-runners "ESS 18.10")
+(defvar ess-r-created-runners nil
+ "List of R-versions found from `ess-r-versions' 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.")
+
+(defun ess-r-mode-p ()
+ "Check whether we have a buffer running in R mode.
+
+This is to get around the lack of proper derived modes in ESS."
+ (and (eq major-mode 'ess-mode)
+ (string= ess-dialect "R")))
+
+;;;###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))
+ (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))
+ (cust-alist (copy-alist ess-r-customize-alist))
+ (gdbp (string-match-p "gdb" r-start-args))
+ use-dialog-box)
+
+ (when gdbp
+ (setcdr (assoc 'inferior-ess-secondary-prompt cust-alist)
+ (format "\\(%s\\)\\|\\((gdb) \\)"
+ (cdr (assoc 'inferior-ess-secondary-prompt cust-alist)))))
+
+ (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))))
+
+ (inferior-ess r-start-args cust-alist gdbp)
+
+ (ess-process-put 'funargs-pre-cache ess-r--funargs-pre-cache)
+
+ (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)
+ (when (>= emacs-major-version 25)
+ (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local))
+ (setq comint-input-sender 'inferior-ess-r-input-sender)
+
+ (if gdbp
+ (progn
+ ;; We need to use callback, because R might start with a gdb process
+ (ess-process-put 'callbacks '(R-initialize-on-start))
+ ;; trigger the callback
+ (process-send-string (get-process ess-local-process-name) "\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))))
+
+;;;###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 R-initialize-on-start (&optional proc string)
+ "This function is run after the first R prompt.
+Executed in process buffer."
+ (interactive)
+ ;; sometimes needed (MM w/ Emacs 25.1, on F24 where PAGER is 'more'):
+ ;; carefully set "pager" option "when needed":
+ (let ((pager-cmd (format
+ "if(identical(getOption('pager'),
+ file.path(R.home(), 'bin', 'pager')))
+ options(pager='%s')\n"
+ inferior-ess-pager)))
+ (ess-command pager-cmd))
+ (inferior-ess-r-load-ESSR)
+ (when inferior-ess-language-start
+ (ess-command (concat inferior-ess-language-start "\n")))
+ (with-ess-process-buffer nil
+ (add-hook 'ess-presend-filter-functions 'ess-R-scan-for-library-call nil 'local)
+ (run-mode-hooks 'ess-r-post-run-hook)))
+
+;;;###autoload
+(defun R-mode (&optional proc-name)
+ "Major mode for editing R source. See `ess-mode' for more help."
+ (interactive "P")
+ (setq ess-customize-alist ess-r-customize-alist)
+ ;;(setq imenu-generic-expression R-imenu-generic-expression)
+ (ess-mode ess-r-customize-alist proc-name)
+ ;; for emacs >= 24
+ (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)
+ (when (>= emacs-major-version 25)
+ (add-hook 'xref-backend-functions #'ess-r-xref-backend nil 'local))
+
+ (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
+ (when ess-imenu-use-S
+ (setq imenu-generic-expression ess-imenu-S-generic-expression)
+ (imenu-add-to-menubar "Imenu-R"))
+
+ ;; useful for swankr/slime:
+ (set (make-local-variable 'beginning-of-defun-function)
+ (lambda (&optional arg)
+ (skip-chars-backward " \t\n")
+ (ess-beginning-of-function 'no-error)))
+ (set (make-local-variable 'end-of-defun-function)
+ 'ess-end-of-function)
+
+ (ess-roxy-mode t)
+ (ad-activate 'fill-paragraph)
+ (ad-activate 'move-beginning-of-line)
+ (ad-activate 'back-to-indentation)
+ (ad-activate 'ess-eval-line-and-step)
+
+ ;; FIXME: Why advice our own function?
+ (when ess-roxy-hide-show-p
+ (ad-activate 'ess-indent-command))
+
+ (run-mode-hooks 'R-mode-hook))
+
+;;;###autoload
+(defalias 'r-mode #'R-mode)
+;;;###autoload
+(defalias 'ess-r-mode #'R-mode)
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("/R/.*\\.q\\'" . R-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . R-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.[rR]profile\\'" . R-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("NAMESPACE\\'" . R-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("CITATION\\'" . R-mode))
+
+\f
+;;*;; 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 ()
+ "Generate functions for starting other versions of R.
+See `ess-r-versions' 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-versions
+ ;; try to find R versions in ess-r-versions.
+ (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)
+ (ess-uniq-list
+ (mapcar #'file-name-nondirectory
+ (apply #'nconc
+ (mapcar #'ess-find-exec-completions
+ ess-r-versions)))))))
+ ;; Iterate over each string in VERSIONS, creating a new defun each time.
+ (setq ess-r-created-runners 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)))))))
+(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 `R-newest'.
+Return the list of candidates for being `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 ess-find-newest-R ()
+ "Find the newest version of R on the system.
+Once the value is found, cache it in the variable `ess-newest-R'
+for future use as finding the newest version of R can be
+potentially time-consuming."
+ (or ess-newest-R
+ (progn (message "Finding all versions of R on your system...")
+ ;;(sleep-for 3)
+ nil)
+ (setq ess-newest-R
+ (ess-newest-r
+ (if ess-microsoft-p
+ (ess-rterm-prefer-higher-bit)
+ (add-to-list 'ess-r-created-runners
+ inferior-ess-r-program))))))
+
+(defun ess-check-R-program ()
+ "Check if `inferior-ess-r-program' points to an executable version of R.
+If not, try to find the newest version of R elsewhere on the system, and
+update `inferior-ess-r-program' accordingly."
+ (unless (executable-find inferior-ess-r-program)
+ ;; need to check if we can find another name.
+ (let ((newest (ess-find-newest-R)))
+ (if newest
+ (setq inferior-ess-r-program newest)
+ (message "Sorry, no version of R could be found on your system.")))))
+
+(defun R-newest (&optional start-args)
+ "Find the newest version of R available, and run it.
+Subsequent calls to `R-newest' will run that version, rather than searching
+again for the newest version. Providing an optional prefix START-ARGS (\\[universal-argument]) will
+prompt for command line arguments."
+ (interactive "P")
+ (let ((rnewest (ess-find-newest-R)))
+ (if (not rnewest)
+ (error "No version of R could be found")
+ ;; Else: we have a working version of R.
+ ;; Have to be careful to avoid recursion...
+ (message (concat "Newest version of R is " rnewest))
+ (fset 'R-newest
+ (intern
+ (if ess-microsoft-p
+ (ess-rterm-arch-version rnewest)
+ rnewest)))
+ ;;(fset 'R-newest (intern rnewest))
+ (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 "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)))))
+
+(defvar ess-temp-newest nil)
+
+(defun ess-newest-r (rvers)
+ "Check all the versions of RVERS to see which is the newest.
+Return the name of the newest version of R."
+ (let ((rtimes (mapcar 'ess-r-version-date rvers)))
+ ;; SJE: 2007-07-13 -- following line is a temp var to check that
+ ;; the newest version of R is found correctly.
+ ;; (nowadays gives a compile warning)
+ (setq ess-temp-newest rtimes)
+ (ess-find-newest-date rtimes)))
+
+(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 occurences of Rterm.exe under the ESS-R-ROOT-DIR.
+If ESS-R-ROOT-DIR is nil, construct it by looking for an
+occurence of Rterm.exe in the `exec-path'. If there are no
+occurences 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-versions))))))
+ (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
+(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))
+
+;;;###autoload
+(defun R-transcript-mode ()
+ "Does the right thing."
+ (interactive)
+ (ess-transcript-mode ess-r-customize-alist))
+
+(fset 'r-transcript-mode 'R-transcript-mode)
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.[Rr]out" . R-transcript-mode))
+;;;###autoload
+(add-to-list 'interpreter-mode-alist '("Rscript" . R-mode))
+;;;###autoload
+(add-to-list 'interpreter-mode-alist '("r" . 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.")
+
+(defun ess-r-install-library (&optional update pack)
+ "Prompt and install R package PACK.
+With argument UPDATE, update cached packages list."
+ (interactive "P")
+ (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 pack (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)
+ (pack (or pack
+ (ess-completing-read "Package to install" ess--packages-cache))))
+ (process-send-string (get-process ess-current-process-name)
+ (format "install.packages('%s')\n" pack))
+ (display-buffer (buffer-name (process-buffer (get-process ess-current-process-name))))))
+
+(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))
+ (let* ((M1 (ess-get-words-from-vector "local({out <- getCRANmirrors(local.only=TRUE); print(paste(out$Name,'[',out$URL,']', sep=''))})\n"))
+ (M2 (mapcar (lambda (el)
+ (string-match "\\(.*\\)\\[\\(.*\\)\\]$" el)
+ (propertize (match-string 1 el) 'URL (match-string 2 el)))
+ M1))
+ (mirror (ess-completing-read "Choose CRAN mirror" M2 nil t)))
+ (when mirror
+ (setq mirror (get-text-property 0 'URL mirror))
+ (setq ess--CRAN-mirror mirror)
+ (ess-command (format mirror-cmd 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))
+ (message nil)))
+
+(defun ess-r-sos (cmd)
+ "Interface to findFn in the library sos."
+ (interactive "sfindFn: ")
+ (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)
+
+(defun ess-load-library ()
+ "Prompt and load dialect specific library/package/module.
+
+Note that add-ons in R 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)
+ (if (not (string-match "^R" ess-dialect))
+ (message "Sorry, not available for %s" ess-dialect)
+ (let ((ess-eval-visibly-p t)
+;;; FIXME? .packages() does not cache; installed.packages() does but is slower first time
+ (packs (ess-get-words-from-vector "print(.packages(T), max=1e6)\n"))
+ pack)
+ (setq pack (ess-completing-read "Load" packs))
+ (ess-eval-linewise (format "library('%s')\n" pack))
+ (ess--mark-search-list-as-changed)
+ (display-buffer (buffer-name (process-buffer (get-process ess-current-process-name)))))))
+
+(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"))
+
+\f
+;;*;; 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)))
+
+(ess-defmethod R ess-build-eval-command (string &optional visibly output file namespace)
+ (let* ((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)))
+ (args (ess-r-build-args visibly output namespace)))
+ (concat cmd "(\"" string "\"" args file ")\n")))
+
+(ess-defmethod R ess-build-load-command (file &optional visibly output namespace)
+ (let* ((namespace (or namespace (ess-r-get-evaluation-env)))
+ (cmd (if namespace ".ess.ns_source" ".ess.source"))
+ (args (ess-r-build-args visibly output namespace)))
+ (concat cmd "('" file "'" args ")\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.")
+
+(ess-defmethod R ess-load-file (file)
+ (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')."
+ (interactive)
+ (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)))
+
+(ess-defmethod R ess-send-region (proc start end visibly message type)
+ (cond
+ ;; Namespaced evaluation
+ ((ess-r-get-evaluation-env)
+ (ess-r-send-region-namespaced proc start end visibly message))
+ ;; Evaluation into current env
+ (t
+ (ess-send-string proc (buffer-substring start end) visibly message type))))
+
+(defun ess-r-send-region-namespaced (proc beg end &optional visibly message)
+ "Ask for for the package and devSource region into it."
+ (let* ((pkg-name (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 dont-ask)
+ ;; 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)
+ (if dont-ask
+ (car pkgs)
+ (ess-completing-read "Choose location" pkgs nil t)))))
+
+(defun ess-r-build-help-command--unqualified (object dont-ask)
+ (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 dont-ask))
+ (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))))
+
+(defun ess-r-build-help-command (object &optional dont-ask)
+ (or (ess-r-build-help-command--qualified object)
+ (ess-r-build-help-command--unqualified object dont-ask)))
+
+(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))
+
+(defvar ess-help-r--last-help-type nil
+ "Variable holding the last known help type.
+If it changes, we flush the cache.")
+
+(defun ess-help-r--check-last-help-type ()
+ (let ((help-type (ess-string-command "getOption('help_type')\n")))
+ (when (not (string= help-type ess-help-r--last-help-type))
+ (let ((help-buffers (ess-help-get-local-help-buffers)))
+ (mapc #'kill-buffer help-buffers))
+ (setq ess-help-r--last-help-type help-type))))
+
+(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)
+ (ess-help-r--check-last-help-type)
+ (cond (help-match
+ (ess-display-help-on-object help-match)
+ (process-send-string proc "\n"))
+ (help-?-match
+ (ess-help-r--display-help-? proc 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"))))
+ (R-transcript-mode)
+ (process-send-string proc "\n")))
+ t)))
+
+(defun ess-help-r--display-help-? (proc 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 corectly
+ (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 inferior-ess-r-load-ESSR ()
+ "Load/INSTALL/Update ESSR."
+ (let* ((pkg-dir (expand-file-name "ESSR" ess-etc-directory))
+ (src-dir (expand-file-name "R" pkg-dir)))
+ (if (not (or (and (boundp 'ess-remote) ess-remote)
+ (file-remote-p (ess-get-process-variable 'default-directory))))
+ (inferior-ess-r-load-ESSR--local pkg-dir src-dir)
+ (inferior-ess-r-load-ESSR--remote pkg-dir src-dir))))
+
+(defun inferior-ess-r-load-ESSR--local (pkg-dir src-dir)
+ (let ((cmd (format "local({
+ source('%s/.load.R', local=TRUE) #define load.ESSR
+ load.ESSR('%s')
+ })\n"
+ src-dir src-dir)))
+ (ess-write-to-dribble-buffer (format "load-ESSR cmd:\n%s\n" cmd))
+ (with-current-buffer (ess-command cmd)
+ (let ((msg (buffer-string)))
+ (when (> (length msg) 1)
+ (message (format "load ESSR: %s" msg)))))))
+
+(defun inferior-ess-r-load-ESSR--remote (pkg-dir src-dir)
+ (let* ((verfile (expand-file-name "VERSION" pkg-dir))
+ (loadremote (expand-file-name "LOADREMOTE" pkg-dir))
+ (version (if (file-exists-p verfile)
+ (with-temp-buffer
+ (insert-file-contents verfile)
+ (buffer-string))
+ (error "Cannot find ESSR source code")))
+ (r-load-code (with-temp-buffer
+ (insert-file-contents loadremote)
+ (buffer-string))))
+ (ess-write-to-dribble-buffer (format "version file: %s\nloadremote file: %s\n"
+ verfile loadremote))
+ (unless (ess-boolean-command (format r-load-code version) nil 0.1)
+ (let ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string)))
+ (files (directory-files src-dir t "\\.R$")))
+ (ess-write-to-dribble-buffer (format "error loading ESSR.rda: \n%s\n" errmsg))
+ ;; should not happen, unless extrem conditions (ancient R or failed download))
+ (message "Failed to download ESSR.rda (see *ESS* buffer). Injecting ESSR code from local machine")
+ (ess-command (format ".ess.ESSRversion <- '%s'\n" version)) ; cannot do this at R level
+ (mapc #'ess--inject-code-from-file files)))))
+
+(ess-defmethod R ess-quit (&optional no-save)
+ (let (cmd
+ (sprocess (ess-get-process ess-current-process-name)))
+ (when (not sprocess) (error "No ESS process running"))
+ (ess-cleanup)
+ (setq cmd (format "base::q('%s')\n" (if no-save "no" "default")))
+ (goto-char (marker-position (process-mark sprocess)))
+ (process-send-string sprocess cmd)))
+
+(defcustom inferior-ess-r-reload-hook nil
+ "Hook run when reloading the R inferior buffer."
+ :type 'hook
+ :group 'ess-R)
+
+(ess-defmethod R inferior-ess-reload (&optional start-args)
+ (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 ess-dialect "R")
+ (ess-force-buffer-current prompt force no-autostart ask-if-1))
+
+\f
+;;*;; 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."
+ (let ((indent (ess-calculate-indent nil))
+ beg shift-amt
+ (case-fold-search nil)
+ (pos (- (point-max) (point))))
+ (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 (&optional parse-start)
+ "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))))))
+ (ess-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 skiped 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)
+ (ess-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
+ (ess-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)))
+ (prev-pos (1- (point)))
+ max-col)
+ (while (< (line-number-at-pos) to-line)
+ (forward-line)
+ (ess-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)
+ (ess-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* ((start-line (line-number-at-pos))
+ (prev-pos 0)
+ (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)
+ (ess-indent-line))
+ (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))
+ (orig-col (current-column))
+ (orig-line (line-number-at-pos))
+ (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)
+ (ess-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)))
+ (ess-indent-line)
+ (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)
+ (ess-indent-line)
+ (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))))
+
+\f
+
+;; 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
+ (ess-uniq-list
+ (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))
+
+(provide 'ess-r-mode)
+
+;;; Local variables:
+;;; mode: emacs-lisp
+;;; byte-compile-warnings: (not lexical)
+;;; End:
+
+;;; ess-r-mode.el ends here
--- /dev/null
+;;; ess-r-package.el --- Package development mode for R.
+
+;; 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 <ESS-coreNOSPAMr-project.org>
+
+;; 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 apropriate documentation section of ESS user manual
+
+;;; Code:
+
+(require 'ess-custom)
+(require 'ess-inf)
+(require 'ess-utils)
+;; 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")
+
+(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--project-cache nil
+ "Current package info cache.
+
+Cons cell of two strings. CAR is the package name active in the
+current buffer. CDR is the path to its source directory.")
+
+(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.")
+
+\f
+;;;*;;; 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 name as symbol
+and the project path as string. If DIR is provided, the package
+is searched from that directory instead of `default-directory'."
+ (if (car ess-r-package--project-cache)
+ ess-r-package--project-cache
+ (let* ((pkg-path (ess-r-package--find-package-path (or dir default-directory)))
+ (project (when pkg-path
+ (cons (ess-r-package--find-package-name pkg-path) pkg-path))))
+ ;; Cache info for better performance on remotes
+ (setq-local ess-r-package--project-cache (or project (list nil)))
+ (when (car project)
+ (cons 'r-package (cdr project))))))
+
+(defun ess-r-package-name (&optional dir)
+ "Return the name of the current package as a string."
+ (let ((project (ess-r-package-project dir)))
+ (when project
+ (symbol-name (car ess-r-package--project-cache)))))
+
+(defun ess-r-package-get-info ()
+ "Deprecated function to get package info.
+Please use `ess-r-package-project' instead."
+ (let ((project (ess-r-package-project)))
+ (if project
+ (cons (ess-r-package-name) (cdr project))
+ (list nil))))
+(make-obsolete 'ess-r-package-get-info 'ess-r-package-project "17.11")
+
+(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 (cdr (ess-r-package-project))))
+ (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 that contains current directory.
+Root is determined by locating `ess-r-package-root-file'."
+ (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)))))
+ (when 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 file)
+ (goto-char (point-min))
+ (when (re-search-forward "package: \\(.*\\)" nil t)
+ (intern (match-string 1)))))))
+
+\f
+;;;*;;; UI
+
+(defun ess-r-package-use-dir ()
+ "Set process directory to current package directory."
+ (interactive)
+ (let ((dir (cdr (ess-r-package-project))))
+ (ess-set-working-directory (abbreviate-file-name dir))))
+
+(defun ess-r-package-set-package ()
+ "Set a package for ESS r-package commands."
+ (interactive)
+ (let* ((pkg-path (read-directory-name
+ "Path: " (or (ess-r-package--find-package-path)
+ (if (stringp ess-r-package-library-paths)
+ ess-r-package-library-paths
+ (car ess-r-package-library-paths)))
+ nil t))
+ (pkg-name (ess-r-package--find-package-name pkg-path))
+ (pkg-info (cons pkg-name pkg-path)))
+ (unless (and pkg-name pkg-path
+ (file-exists-p (expand-file-name ess-r-package-root-file pkg-path)))
+ (error "Not a valid package. No '%s' found in `%s'" ess-r-package-root-file pkg-path))
+ (message (format "%s selected and added to file-local variables" pkg-name))
+ (save-excursion
+ (add-file-local-variable 'ess-r-package--project-cache pkg-info))
+ (setq ess-r-package--project-cache pkg-info)))
+
+\f
+;;;*;;; 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 ((path (cdr (ess-r-package-project))))
+ ;; Check that we are in a file within R/
+ (when (and path
+ default-directory
+ (> (length default-directory) (1+ (length path)))
+ (let ((subpath (substring default-directory
+ (1+ (length path))
+ (length default-directory))))
+ (string= (directory-file-name subpath) "R")))
+ (ess-r-set-evaluation-env (ess-r-package-name))))))
+
+(add-hook 'R-mode-hook 'ess-r-package-enable-namespaced-evaluation)
+
+(defun ess-r-package-eval-linewise (command &optional msg p actions pkg-path)
+ "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 (or (ess-r-package-project)
+ (ess-r-package-set-package)))
+ (pkg-name (ess-r-package-name))
+ (pkg-path (or pkg-path (concat "'" (abbreviate-file-name (cdr pkg-info)) "'")))
+ (args (ess-r-command--build-args p actions)))
+ (message msg pkg-name)
+ (with-ess-process-buffer nil
+ (setq ess-r-package--project-cache ess-r-package--project-cache))
+ (ess-show-buffer (ess-get-process-buffer))
+ (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))))
+
+\f
+;;;*;;; 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-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 instalation 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)
+ (ess-show-buffer (ess-get-process-buffer))
+ (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: ")))))
+
+\f
+;;;*;;; 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)
+
+\f
+;;;*;;; 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)))
+ (let ((pkg-info (ess-r-package-project)))
+ (when pkg-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--project-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))
+
+\f
+;;;*;;; 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")
+
+\f
+(provide 'ess-r-package)
+
+;;; ess-r-package.el ends here
--- /dev/null
+;;; ess-r-syntax.el --- Utils to work with R code
+
+;; Copyright (C) 2015 Lionel Henry
+
+;; Author: Lionel Henry <lionel.hryNOSPAMgmail.com>
+;; Created: 12 Oct 2015
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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))
+
+\f
+;;*;; 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 (= (point) (point-min))
+ (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)))
+
+(defun ess-back-to-indentation ()
+ "Move point to the first non-whitespace character on this line.
+This non-interactive version of (back-to-indentation) should not
+be advised"
+ (beginning-of-line 1)
+ (skip-syntax-forward " " (line-end-position))
+ ;; Move back over chars that have whitespace syntax but have the p flag.
+ (backward-prefix-chars))
+
+(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)
+ (ess-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))))
+
+\f
+;;*;; 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 (= (point) (point-min))
+ "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))
+
+\f
+;;*;; 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)))
+
+\f
+;;*;; 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 (/= (point) (point-min))
+ (= (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 (/= (point) (point-min))
+ (/= 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)
+ (ess-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))))))
+
+\f
+;;;*;;; 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))))))
+
+\f
+;;;*;;; 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))))
+
+\f
+;;;*;;; 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 ((orig-point (point))
+ (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))
+
+\f
+;;;*;;; 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)))))
+
+\f
+;;;*;;; 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)))))
+
+\f
+;;;*;;; 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
+ (when (memq (char-before) '(?$ ?@))
+ (forward-char -1)
+ (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 quote-char)
+ (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
--- /dev/null
+;;; ess-r-xref.el --- An xref backend for R. -*- lexical-binding: t -*-
+;;
+;; Author: Aaron Jacobs
+;; Created: 21 January 2018
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+;;
+;; Keywords: languages, statistics, xref
+;; Package-Requires: ((emacs "25"))
+;;
+;; 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 `R-mode'.
+
+;;; Code:
+
+(when (>= emacs-major-version 25)
+ (require 'subr-x)
+ (require 'xref))
+;; Cludge to silence the byte compiler until we drop support for Emacs 24.
+(declare-function xref-make "xref")
+(declare-function xref-make-buffer-location "xref")
+(declare-function xref-make-file-location "xref")
+(require 'ess-inf)
+(require 'ess-utils)
+(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 `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 "")
+ (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 (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)
+ (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
--- /dev/null
+;; ess-rd.el --- Support for editing R documentation (Rd) source
+
+;; Copyright (C) 1997--2005 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: KH <Kurt.HornikNOSPAMci.tuwien.ac.at>
+;; Created: 25 July 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+(require 'ess-custom)
+(require 'ess-utils)
+(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)
+
+(defvar essddr-version "0.9-1"
+ "Current version of ess-rd.el.")
+
+(defvar essddr-maintainer-address
+ "ESS Core Team <ess-coreNOSPAMr-project.org>"
+ "Current maintainer of ess-rd.el.")
+
+(defvar Rd-mode-abbrev-table nil
+ "Abbrev table for R documentation keywords.
+All Rd mode abbrevs start with a grave accent (`).")
+(if Rd-mode-abbrev-table
+ ()
+ (define-abbrev-table 'Rd-mode-abbrev-table ())
+ (define-abbrev Rd-mode-abbrev-table "`ag" "\\arguments")
+ (define-abbrev Rd-mode-abbrev-table "`al" "\\alias")
+ (define-abbrev Rd-mode-abbrev-table "`au" "\\author")
+ (define-abbrev Rd-mode-abbrev-table "`bf" "\\bold")
+ (define-abbrev Rd-mode-abbrev-table "`co" "\\code")
+ (define-abbrev Rd-mode-abbrev-table "`de" "\\describe")
+ (define-abbrev Rd-mode-abbrev-table "`dn" "\\description")
+ (define-abbrev Rd-mode-abbrev-table "`dt" "\\details")
+ (define-abbrev Rd-mode-abbrev-table "`em" "\\emph")
+ (define-abbrev Rd-mode-abbrev-table "`en" "\\enumerate")
+ (define-abbrev Rd-mode-abbrev-table "`ex" "\\examples")
+ (define-abbrev Rd-mode-abbrev-table "`fi" "\\file")
+ (define-abbrev Rd-mode-abbrev-table "`fo" "\\format")
+ (define-abbrev Rd-mode-abbrev-table "`it" "\\item")
+ (define-abbrev Rd-mode-abbrev-table "`iz" "\\itemize")
+ (define-abbrev Rd-mode-abbrev-table "`kw" "\\keyword")
+ (define-abbrev Rd-mode-abbrev-table "`li" "\\link")
+ (define-abbrev Rd-mode-abbrev-table "`me" "\\method")
+ (define-abbrev Rd-mode-abbrev-table "`na" "\\name")
+ (define-abbrev Rd-mode-abbrev-table "`no" "\\note")
+ (define-abbrev Rd-mode-abbrev-table "`re" "\\references")
+ (define-abbrev Rd-mode-abbrev-table "`sa" "\\seealso")
+ (define-abbrev Rd-mode-abbrev-table "`se" "\\section")
+ (define-abbrev Rd-mode-abbrev-table "`so" "\\source")
+ (define-abbrev Rd-mode-abbrev-table "`ss" "\\subsection")
+ (define-abbrev Rd-mode-abbrev-table "`sy" "\\synopsis")
+ (define-abbrev Rd-mode-abbrev-table "`ta" "\\tabular")
+ (define-abbrev Rd-mode-abbrev-table "`ti" "\\title")
+ (define-abbrev Rd-mode-abbrev-table "`us" "\\usage")
+ (define-abbrev Rd-mode-abbrev-table "`va" "\\value"))
+
+(defvar Rd-mode-syntax-table nil
+ "Syntax table for Rd mode.")
+(if Rd-mode-syntax-table
+ ()
+ (setq Rd-mode-syntax-table (copy-syntax-table text-mode-syntax-table))
+ (modify-syntax-entry ?\\ "\\" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(}" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\} "){" Rd-mode-syntax-table)
+ ;; Nice for editing, not for parsing ...
+ (modify-syntax-entry ?\( "()" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\) ")(" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" Rd-mode-syntax-table)
+ ;; To get strings right
+ ;; (modify-syntax-entry ?\' "\"" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\" "\"" Rd-mode-syntax-table)
+ ;; To make abbrevs starting with a grave accent work ...
+ (modify-syntax-entry ?\` "w" Rd-mode-syntax-table)
+ ;; Comments
+ (modify-syntax-entry ?\% "<" Rd-mode-syntax-table)
+ (modify-syntax-entry ?\n ">" Rd-mode-syntax-table))
+
+(defvar Rd-mode-parse-syntax-table nil
+ "Syntax table for parsing Rd mode.")
+(if Rd-mode-parse-syntax-table
+ ()
+ (setq Rd-mode-parse-syntax-table
+ (copy-syntax-table Rd-mode-syntax-table))
+ ;; To make parse-partial-sexps do the thing we want for computing
+ ;; indentations
+ (modify-syntax-entry ?\( "_" Rd-mode-parse-syntax-table)
+ (modify-syntax-entry ?\) "_" Rd-mode-parse-syntax-table)
+ (modify-syntax-entry ?\[ "_" Rd-mode-parse-syntax-table)
+ (modify-syntax-entry ?\] "_" Rd-mode-parse-syntax-table))
+
+(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 <R>/share/Rd/macros/system.Rd ):
+ "CRANpkg" "PR" "sspace" "doi"
+ "packageTitle" "packageDescription" "packageAuthor"
+ "packageMaintainer" "packageDESCRIPTION" "packageIndices"
+ ))
+
+;; Need to fix Rd-bold-face problem.
+;;
+;; (defvar Rd-bold-face 'bold)
+ ;(defvar Rd-bold-face nil)
+ ;(make-face Rd-bold-face "R documentation bold face")
+ ;(make-face-bold Rd-bold-face
+
+(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)
+ ;; ^C^F ^E : \emph{ . }
+ ;; ^C^F ^C : \code{ . }
+ ;; ^C^F ^L : \link{ . }
+ ;; ^C^F L : \code{\link{ . }} etc
+ (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); is on C-c C-s in ess-mode..
+ (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" Rd-submit-bug-report t]
+ "-"
+ ["Describe Rd Mode" Rd-describe-major-mode t])
+ "Menu used in Rd mode.")
+
+(defvar Rd-mode-hook nil
+ "Hook to be run when Rd mode is entered.")
+
+(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
+(defun Rd-mode ()
+ "Major mode for editing R documentation source files.
+
+This mode makes it easier to write R documentation by helping with
+indentation, doing some of the typing for you (with Abbrev mode) and by
+showing keywords, strings, etc. in different faces (with Font Lock mode
+on terminals that support it).
+
+Type \\[list-abbrevs] to display the built-in abbrevs for Rd keywords.
+
+Keybindings
+===========
+
+\\{Rd-mode-map}
+
+Variables you can use to customize Rd mode
+==========================================
+
+`Rd-indent-level'
+ Indentation of Rd code with respect to containing blocks.
+ Default is 2.
+
+Turning on Rd mode runs the hook `Rd-mode-hook'.
+
+To automatically turn on the abbrev(iate) features, add the
+following lines to your `.emacs' file:
+
+ (add-hook 'Rd-mode-hook
+ (lambda ()
+ (abbrev-mode 1)))"
+
+ (interactive)
+ (text-mode)
+ (kill-all-local-variables)
+ (ess-setq-vars-local ess-r-customize-alist) ;same functionality is available as in R buffers
+ (use-local-map Rd-mode-map)
+ (setq mode-name "Rd")
+ (setq major-mode 'Rd-mode)
+ (setq local-abbrev-table Rd-mode-abbrev-table)
+ (set-syntax-table Rd-mode-syntax-table)
+
+ (set (make-local-variable 'indent-line-function) 'Rd-mode-indent-line)
+ (set (make-local-variable 'fill-column) 72)
+ (set (make-local-variable 'comment-start-skip) "\\s<+\\s-*")
+ (set (make-local-variable 'comment-start) "% ")
+ (set (make-local-variable 'comment-end) "")
+ (set (make-local-variable 'font-lock-defaults)
+ '(Rd-font-lock-keywords nil nil))
+ ;; (set (make-local-variable 'parse-sexp-ignore-comments) t)
+
+ ;; 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
+ (make-local-variable 'create-lockfiles)
+ (setq create-lockfiles nil)
+
+ (require 'easymenu)
+ (easy-menu-define Rd-mode-menu-map Rd-mode-map
+ "Menu keymap for Rd mode." Rd-mode-menu)
+
+ (turn-on-auto-fill)
+ (message "Rd mode version %s" essddr-version)
+ (setq ess-language "S" ess-dialect "R"); (buffer local)
+ (run-mode-hooks 'Rd-mode-hook))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.Rd\\'" . Rd-mode))
+
+;; FIXME: The following should be moved to ess-utils.el, no? (MM thinks)
+(defun ess-point (position)
+ "Return the value of point at a certain POSITION."
+ (save-excursion
+ (cond
+ ((eq position 'bol) (beginning-of-line))
+ ((eq position 'eol) (end-of-line))
+ ((eq position 'boi) (back-to-indentation))
+ ((eq position 'bonl) (forward-line 1))
+ ((eq position 'bopl) (forward-line -1))
+ (t (error "Unknown buffer position requested: %s" position)))
+ (point)))
+
+(defun Rd-describe-major-mode ()
+ "Describe the current major mode."
+ (interactive)
+ (describe-function major-mode))
+
+(defun Rd-mode-in-verbatim-p ()
+ (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 ()
+ (save-excursion
+ (beginning-of-line)
+ (looking-at "[ \t]*#\\(ifdef\\|endif\\)")))
+
+(defun Rd-mode-calculate-indent ()
+ "Return appropriate indentation for current line in Rd mode."
+ (interactive)
+ (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)*" (ess-point '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)*" (ess-point '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."
+ (interactive)
+ (let ((ic (Rd-mode-calculate-indent))
+ (rp (- (current-column) (current-indentation))))
+ (if ic ; Not inside a verbatim
+ (if (< ic 0)
+ (error "Unmatched parenthesis")
+ (indent-line-to ic)
+ (if (> rp 0)
+ (move-to-column (+ ic rp)))))))
+
+(defun Rd-mode-insert-item ()
+ (interactive)
+ (reindent-then-newline-and-indent)
+ (insert "\\item{")
+ )
+
+(defun Rd-mode-insert-section ()
+ (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 ()
+ (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))))))
+;;;###autoload
+(defun Rd-preview-help (&optional via-shell)
+ "Preview the current Rd buffer contents as help.
+If optional VIA-SHELL is set, using `Rd-to-help-command'.
+If the current buffer is not associated with a file, create a
+temporary one in `temporary-file-directory'."
+ (interactive "P")
+ (require 'ess-help)
+ (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)
+ ;; 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)
+ ;; mostly cut'n'paste from ess--flush-help* (see FIXME(2)):
+ (ess-help-underline)
+ (ess-help-mode)
+ (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))))
+
+;; Bug reporting
+(defun Rd-submit-bug-report ()
+ "Submit a bug report on Rd mode via mail."
+ (interactive)
+ (require 'reporter)
+ (and
+ (y-or-n-p "Do you want to submit a bug report? ")
+ (reporter-submit-bug-report
+ essddr-maintainer-address
+ (concat "Emacs version " emacs-version)
+ (list
+ 'essddr-version
+ 'Rd-indent-level))))
+
+
+;; Legacy feature
+(provide 'essddr)
+(provide 'ess-rd)
+
+;;; ess-rd.el ends here
--- /dev/null
+;;; ess-rdired.el --- prototype object browser for R, looks like dired mode.
+
+;; Copyright (C) 2002--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Stephen Eglen <stephenNOSPAManc.ed.ac.uk>
+;; Created: Thu 24 Oct 2002
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+;; Installation and usage.
+;;
+;; After loading this file, 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*:
+;; mode length
+;; s numeric 100
+;; x numeric 3
+;; y numeric 20
+;; z logical 1
+
+;; 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 mark it for deletion.
+
+;; How it works.
+
+;; Most of the hardwork 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',
+;; and can be altered to provide other information if you so need it.
+;; (Martin Maechler suggested providing output from str() here.)
+
+;; Todo - compare functionality with ess-mouse-me (ess-mous.el).
+
+;; 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-custom)
+(require 'ess-inf)
+
+(defvar ess-rdired-objects "{.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=\"auto\")', 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()))}\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-mode-map
+ (let ((ess-rdired-mode-map (make-sparse-keymap)))
+ (if (require 'hide-lines nil t)
+ (define-key ess-rdired-mode-map "/" 'hide-lines))
+ (define-key ess-rdired-mode-map "?" 'ess-rdired-help)
+ (define-key ess-rdired-mode-map "d" 'ess-rdired-delete)
+ (define-key ess-rdired-mode-map "u" 'ess-rdired-undelete)
+ (define-key ess-rdired-mode-map "x" 'ess-rdired-expunge)
+ ;; editing requires a little more work.
+ ;;(define-key ess-rdired-mode-map "e" 'ess-rdired-edit)
+ (define-key ess-rdired-mode-map "v" 'ess-rdired-view)
+ (define-key ess-rdired-mode-map "V" 'ess-rdired-View)
+ (define-key ess-rdired-mode-map "p" 'ess-rdired-plot)
+ (define-key ess-rdired-mode-map "s" 'ess-rdired-sort)
+ (define-key ess-rdired-mode-map "r" 'ess-rdired-reverse)
+ (define-key ess-rdired-mode-map "q" 'ess-rdired-quit)
+ (define-key ess-rdired-mode-map "y" 'ess-rdired-type) ;what type?
+ (define-key ess-rdired-mode-map " " 'ess-rdired-next-line)
+ (define-key ess-rdired-mode-map [backspace] 'ess-rdired-previous-line)
+ (define-key ess-rdired-mode-map "\C-n" 'ess-rdired-next-line)
+ (define-key ess-rdired-mode-map "\C-p" 'ess-rdired-previous-line)
+ ;; (define-key ess-rdired-mode-map "n" 'ess-rdired-next-line)
+ ;; (define-key ess-rdired-mode-map "p" 'ess-rdired-previous-line)
+
+ ;; R mode keybindings.
+ (define-key ess-rdired-mode-map "\C-c\C-s" 'ess-rdired-switch-process)
+ (define-key ess-rdired-mode-map "\C-c\C-y" 'ess-switch-to-ESS)
+ (define-key ess-rdired-mode-map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
+
+ (define-key ess-rdired-mode-map [down] 'ess-rdired-next-line)
+ (define-key ess-rdired-mode-map [up] 'ess-rdired-previous-line)
+ (define-key ess-rdired-mode-map "g" 'revert-buffer)
+ (define-key ess-rdired-mode-map [mouse-2] 'ess-rdired-mouse-view)
+ ess-rdired-mode-map))
+
+(defun ess-rdired-mode ()
+ "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.
+\\{ess-rdired-mode-map}"
+ ;; (kill-all-local-variables)
+ (make-local-variable 'revert-buffer-function)
+ (setq revert-buffer-function 'ess-rdired-revert-buffer)
+ (use-local-map ess-rdired-mode-map)
+ (setq major-mode 'ess-rdired-mode)
+ (setq mode-name (concat "RDired " ess-local-process-name))
+ (run-mode-hooks 'ess-rdired-mode-hook))
+
+(defun ess-rdired-mode-hook nil
+ "Run upon entering `ess-rdired-mode'.")
+
+(defvar ess-rdired-sort-num nil) ;silence the compiler.
+;; but see following defun -- maybe it should be buffer local.
+
+;;;###autoload
+(defun ess-rdired ()
+ "Run dired-like mode on R objects.
+This is the main function. See documentation for `ess-rdired-mode' though
+for more information!"
+ (interactive)
+ (let ((proc ess-local-process-name)
+ (buff (get-buffer-create ess-rdired-buffer)))
+
+ (ess-command ess-rdired-objects buff)
+ (ess-setq-vars-local (symbol-value ess-local-customize-alist) buff)
+
+ (with-current-buffer buff
+ (setq ess-local-process-name proc)
+ (ess-rdired-mode)
+
+ ;; When definiting the function .rdired.objects(), a "+ " is printed
+ ;; for every line of the function definition; these are deleted
+ ;; here.
+ (goto-char (point-min))
+ (delete-region (point-min) (1+ (point-at-eol)))
+
+ ;; todo: not sure how to make ess-rdired-sort-num buffer local?
+ ;;(set (make-local-variable 'ess-rdired-sort-num) 2)
+ ;;(make-variable-buffer-local 'ess-rdired-sort-num)
+ (setq ess-rdired-sort-num 1)
+ (ess-rdired-insert-set-properties (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (point))
+ (point-max))
+ (setq buffer-read-only t)
+ )
+
+ (pop-to-buffer buff)
+ ))
+
+
+(defun ess-rdired-object ()
+ "Return name of object on current line.
+Handle special case when object contains spaces."
+ (save-excursion
+ (beginning-of-line)
+ (forward-char 2)
+
+ (cond ((looking-at " ") ; First line?
+ nil)
+ ((looking-at "\"") ; Object name contains spaces?
+ (let (beg)
+ (setq beg (point))
+ (forward-char 1)
+ (search-forward "\"")
+ (buffer-substring-no-properties beg (point))))
+ (t ;should be a regular object.
+ (let (beg)
+ (setq beg (point))
+ (search-forward " ") ;assume space follows object name.
+ (buffer-substring-no-properties beg (1- (point))))))))
+
+(defun ess-rdired-edit ()
+ "Edit (fix) the object at point."
+ (interactive)
+ (let ((objname (ess-rdired-object)))
+ (ess-command (concat "edit(" objname ")\n"))))
+
+(defun ess-rdired-view ()
+ "View the object at point."
+ (interactive)
+ (let ((objname (ess-rdired-object)))
+ (ess-execute (ess-rdired-get objname)
+ 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 (ess-rdired-object)))
+ (ess-execute (ess-rdired-get objname)
+ nil (concat "R view " objname ))))
+
+(defun ess-rdired-plot ()
+ "Plot the object on current line."
+ (interactive)
+ (let ((objname (ess-rdired-object)))
+ (ess-eval-linewise (format "plot(%s)" (ess-rdired-get objname)))))
+
+(defun ess-rdired-type ()
+ "Run the mode() on command at point.
+Named type because of similarity with the dired command bound to
+y key."
+ (interactive)
+ (let ((objname (ess-rdired-object))
+ ;; 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 (concat
+ objname ": "
+ (buffer-substring (+ 4 (point-min)) (1- (point-max)))))
+ (kill-buffer tmpbuf)))))
+
+(defun ess-rdired-delete (arg)
+ "Mark the current (or next ARG) objects for deletion.
+If point is on first line, all objects are marked for deletion."
+ (interactive "p")
+ (ess-rdired-mark "D" arg))
+
+(defun ess-rdired-undelete (arg)
+ "Unmark the current (or next ARG) objects.
+If point is on first line, all objects will be unmarked."
+ (interactive "p")
+ (ess-rdired-mark " " arg))
+
+(defun ess-rdired-mark (mark-char arg)
+ "Mark the object, using MARK-CHAR, on current line (or next ARG lines)."
+ ;; If we are on first line, mark all lines.
+ (let ((buffer-read-only nil)
+ move)
+ (if (eq (point-min)
+ (save-excursion (beginning-of-line) (point)))
+ (progn
+ ;; we are on first line, so make a note of point, and count
+ ;; how many objects we want to delete. Then at end of defun,
+ ;; restore point.
+ (setq move (point))
+ (forward-line 1)
+ (setq arg (count-lines (point) (point-max)))))
+ (while (and (> arg 0) (not (eobp)))
+ (setq arg (1- arg))
+ (beginning-of-line)
+ (progn
+ (insert mark-char)
+ (delete-char 1)
+ (forward-line 1)))
+ (if move
+ (goto-char move))))
+
+
+(defun ess-rdired-expunge ()
+ "Delete the marked objects.
+User is queried first to check that objects should really be deleted."
+ (interactive)
+ (let ((objs "rm(")
+ (count 0))
+ (save-excursion
+ (goto-char (point-min)) (forward-line 1)
+ (while (< (count-lines (point-min) (point))
+ (count-lines (point-min) (point-max)))
+ (beginning-of-line)
+ (if (looking-at "^D ")
+ (setq count (1+ count)
+ objs (concat objs (ess-rdired-object) ", " )))
+ (forward-line 1)
+ ))
+ (if (> count 0)
+ ;; found objects to delete
+ (progn
+ (setq objs (concat
+ (substring objs 0 (- (length objs) 2))
+ ")\n"))
+ (if (yes-or-no-p (format "Delete %d %s " count
+ (if (> count 1) "objects" "object")))
+ (progn
+ (ess-eval-linewise objs nil nil nil 'wait)
+ (ess-rdired)
+ )))
+ ;; else nothing to delete
+ (message "no objects set to delete")
+ )))
+
+;; Fancy delete method, based on dired. Bit too much for our needs?
+;; (defun ess-rdired-expunge ()
+;; "Delete the marked objects.
+;; User is queried first to check that objects should really be deleted."
+;; (interactive)
+;; (let ((objs)
+;; (cmd "rm("))
+;; (save-excursion
+;; (goto-line 2)
+;; (while (< (count-lines (point-min) (point))
+;; (count-lines (point-min) (point-max)))
+;; (beginning-of-line)
+;; (if (looking-at "^D ")
+;; (progn
+;; (setq objs (cons (ess-rdired-object) objs ))
+;; (setq cmd (concat cmd (ess-rdired-object) ", "))
+;; ))
+;; (forward-line 1)
+;; ))
+;; (if (> (length objs) 0)
+;; ;; found objects to delete
+;; (if
+;; (dired-mark-pop-up "*RDired deletions*" 'delete
+;; objs dired-deletion-confirmer
+;; (format "delete %s "
+;; (dired-mark-prompt nil objs)))
+;; ;; should delete the objects.
+;; (progn
+;; (setq cmd (concat (substring cmd 0 (- (length cmd) 2))
+;; ")\n"))
+;; (ess-command cmd)
+;; (ess-rdired)))
+;; ;; else nothing to delete
+;; (message "no objects set to delete")
+;; )))
+
+(defun ess-rdired-quit ()
+ "Quit the R dired buffer."
+ (interactive)
+ (kill-buffer ess-rdired-buffer))
+
+(defun ess-rdired-revert-buffer (ignore noconfirm)
+ "Update the buffer list (in case object list has changed).
+Arguments IGNORE and NOCONFIRM currently not used."
+ (ess-rdired))
+
+(defun ess-rdired-help ()
+ "Show help for `ess-rdired-mode'."
+ (interactive)
+ (describe-function 'ess-rdired-mode))
+
+(defun ess-rdired-sort ()
+ "Sort the rdired output according to one of the columns.
+Rotate between the alternative sorting methods."
+ (interactive)
+ (setq ess-rdired-sort-num (1+ ess-rdired-sort-num))
+ (let ((buffer-read-only nil)
+ (beg (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (point)))
+ (end (point-max)))
+ (if (> ess-rdired-sort-num 4)
+ (setq ess-rdired-sort-num 1))
+ (cond ((eq ess-rdired-sort-num 1)
+ (sort-fields 1 beg end))
+ ((eq ess-rdired-sort-num 2)
+ (sort-fields 2 beg end))
+ ((eq ess-rdired-sort-num 3)
+ (sort-numeric-fields 3 beg end))
+ ((eq ess-rdired-sort-num 4)
+ (sort-numeric-fields 4 beg end)))))
+
+(defun ess-rdired-reverse ()
+ "Reverse the current sort order."
+ (interactive)
+ (let ((buffer-read-only nil)
+ (beg (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (point)))
+ (end (point-max)))
+ (reverse-region beg end)))
+
+(defun ess-rdired-next-line (arg)
+ "Move down lines then position at object.
+Optional prefix ARG says how many lines to move; default is one line."
+ (interactive "p")
+ (forward-line arg)
+ (ess-rdired-move-to-object))
+
+(defun ess-rdired-previous-line (arg)
+ "Move up lines then position at object.
+Optional prefix ARG says how many lines to move; default is one line."
+ (interactive "p")
+ (forward-line (- (or arg 1))) ; -1 if arg was nil
+ (ess-rdired-move-to-object))
+
+(defun ess-rdired-move-to-object ()
+ "Put point at start of object."
+ (beginning-of-line)
+ (forward-char 2)
+ )
+
+(defun ess-rdired-mouse-view (event)
+ "In rdired, visit the object on the line you click on."
+ (interactive "e")
+ (let (window pos)
+ (save-excursion
+ (setq window (posn-window (event-end event))
+ pos (posn-point (event-end event)))
+ (if (not (windowp window))
+ (error "No file chosen"))
+ (set-buffer (window-buffer window))
+ (goto-char pos)
+ (ess-rdired-view))))
+
+(defun ess-rdired-insert-set-properties (beg end)
+ "Add mouse highlighting to each object name in the R dired buffer."
+ (save-excursion
+ (goto-char beg)
+ (while (< (point) end)
+ (ess-rdired-move-to-object)
+ (add-text-properties
+ (point)
+ (save-excursion
+ (search-forward " ")
+ (1- (point)))
+ '(mouse-face highlight
+ help-echo "mouse-2: view object in other window"))
+ (forward-line 1))))
+
+(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))
+
+(provide 'ess-rdired)
+
+;;; ess-rdired.el ends here
--- /dev/null
+;;; ess-roxy.el --- convenient editing of in-code roxygen documentation
+;;
+;; Copyright (C) 2009--2017 Henning Redestig, A.J. Rossini, Richard
+;; M. Heiberger, Martin Maechler, Kurt Hornik, Rodney Sparapani, Stephen
+;; Eglen and Vitalie Spinu.
+;;
+;; Author: Henning Redestig <henning.red * go0glemail c-m>
+;; 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
+;; <https://www.gnu.org/licenses/>.
+
+
+;;; 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,
+;; 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-ident-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.
+
+;; this *is* enabled now via ess-mode-hook in ./ess-site.el
+
+;;; Code:
+
+(require 'ess-utils)
+(require 'ess-custom)
+(require 'ess-utils)
+(require 'hideshow)
+(require 'outline)
+(eval-when-compile
+ (require 'cl-lib))
+(require 'essddr "ess-rd.el")
+
+(defvar roxy-str)
+
+\f
+;;*;; Roxy Minor Mode
+
+(defvar ess-roxy-mode-map
+ (let ((map (make-sparse-keymap)))
+ (if ess-roxy-hide-show-p
+ (define-key map (kbd "C-c C-o h") 'ess-roxy-hide-all))
+ ;; short version (*first*: -> key binding shown in menu):
+ (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)
+ ;; For consistency (e.g. C-c C-o C-h !): kept here *in* addition to above
+ (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)
+ map))
+
+(defvar 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")
+ '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.")
+
+(define-minor-mode ess-roxy-mode
+ "Minor mode for editing ROxygen documentation."
+ :keymap ess-roxy-mode-map
+ (if ess-roxy-mode
+ (progn
+ (font-lock-add-keywords nil ess-roxy-font-lock-keywords)
+ (add-hook 'completion-at-point-functions #'ess-roxy-complete-tag 'local) ;; should be first
+ ;; Hideshow Integration
+ (when (and ess-roxy-hide-show-p (featurep 'hideshow))
+ (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)))
+ (when (and ess-roxy-hide-show-p
+ (bound-and-true-p hs-minor-mode))
+ (hs-show-all)
+ (hs-minor-mode))
+ (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))
+ (when font-lock-mode
+ (if (fboundp 'font-lock-flush)
+ (font-lock-flush)
+ ;; font-lock-fontify-buffer call can be removed when we drop
+ ;; support for Emacs older than 25.1
+ (with-no-warnings (font-lock-fontify-buffer))))
+ ;; 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))
+
+
+\f
+;;*;; 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)
+
+\f
+;;*;; Function definitions
+
+(defun ess-back-to-roxy ()
+ "Go to roxy prefix."
+ (progn
+ (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)
+ "True if point is in a roxy entry."
+ (and (save-excursion
+ (beginning-of-line)
+ (looking-at 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)))
+ (with-temp-buffer
+ (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))
+ (goto-char (car (ess-end-of-function)))))
+
+(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* ((arg-des nil)
+ (roxy-str (ess-roxy-guess-str)))
+ (if (or (not here) (< here 1))
+ (progn
+ (ess-roxy-goto-end-of-entry)
+ (beginning-of-line)
+ (if (not (looking-at "\="))
+ (progn
+ (end-of-line))))
+ (goto-char here))
+ (while (stringp (car (car args)))
+ (setq arg-des (pop args))
+ (unless (string= (car arg-des) "")
+ (progn
+ (insert (concat "\n"
+ roxy-str " @param " (car arg-des) " "))
+ (insert
+ (ess-replace-in-string (concat (car (cdr arg-des))) "\n"
+ (concat "\n" roxy-str)))
+ (if 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 (car (car 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 (car (car 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)
+ (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 "")
+ here key template tag-def)
+ (ess-roxy-goto-func-def)
+ (if (not (= (forward-line -1) 0))
+ (progn
+ (insert "\n")
+ (forward-line -1)))
+ (if (and (not (looking-at "^\n")) (not (ess-roxy-entry-p)))
+ (progn
+ (end-of-line)
+ (insert "\n")))
+ (if (ess-roxy-entry-p)
+ (progn
+ (setq here (1- (ess-roxy-delete-args)))
+ (ess-roxy-insert-args args here))
+ (setq template (copy-sequence ess-roxy-template-alist))
+ (while (stringp (car (car 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 top 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."
+ (if (not (ess-roxy-entry-p))
+ (progn
+ (goto-char (nth 0 (ess-end-of-function)))
+ (forward-line -1)))
+ (if (ess-roxy-entry-p)
+ (progn
+ (goto-char (ess-roxy-end-of-entry))
+ t)
+ (forward-line) nil))
+
+(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 (ess-end-of-function)))
+ (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* ((args nil)
+ (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)
+ "Remove prefix roxy string in this region if point is in a roxy
+region, otherwise prefix all lines with the roxy
+string. Convenient for editing example fields."
+ (interactive "r")
+ (unless (use-region-p)
+ (error "Region is not active"))
+ (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 ()
+ "Use a (possibly newly) connected R session and the roxygen package
+`ess-roxy-package' to generate the Rd code for entry at point, place it
+in a temporary buffer and return that buffer."
+ (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)))))
+ (if (= beg 0)
+ (error "Point is not in a Roxygen entry"))
+ (save-excursion
+ (goto-char (ess-roxy-end-of-entry))
+ (forward-line 1)
+ (if (ess-end-of-function nil t)
+ (append-to-file beg (point) tmpf)
+ (while (and (forward-line 1) (not (looking-at "^$"))
+ (not (looking-at ess-roxy-re))))
+ (append-to-file beg (point) tmpf))
+ (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
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ ;; emacs <= 24.x.y:
+ (with-no-warnings (font-lock-fontify-buffer)))))
+
+
+(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)
+ ess-roxy-str)))
+
+(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)
+ (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."
+ (save-excursion
+ (let ((args-txt
+ (progn
+ (ess-beginning-of-function)
+ (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 ((token (match-string-no-properties 1))
+ (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
+ ;; behaviour for evaluation of regions.
+ (if (and (ess-roxy-entry-p "examples")
+ (with-temp-buffer
+ (insert string)
+ (ess-roxy-entry-p)))
+ (replace-regexp-in-string (concat ess-roxy-re "\\s-*") "" string)
+ string))
+(add-hook 'ess-presend-filter-functions 'ess-roxy-remove-roxy-re nil)
+
+(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)))
+
+\f
+;;*;; Advices
+
+(defmacro ess-roxy-with-filling-context (examples &rest body)
+ (declare (indent 0) (debug (&rest form)))
+ `(let ((comment-start "#+'[ \t]+#")
+ (comment-start-skip "#+'[ \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 S-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))
+ ;; Neutralise (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))))
+
+(defadvice ess-eval-line-and-step (around ess-eval-line-and-step-roxy)
+ "Evaluate line but do not skip over comment (roxy) lines."
+ (if (ess-roxy-entry-p)
+ (let ((simple-next t))
+ ad-do-it)
+ ad-do-it))
+
+(defadvice ess-indent-command (around ess-roxy-toggle-hiding)
+ "Hide this block if we are at the beginning of the line."
+ (if (and (= (point) (point-at-bol)) (ess-roxy-entry-p) 'ess-roxy-hide-show-p)
+ (progn (ess-roxy-toggle-hiding))
+ ad-do-it))
+
+(defadvice fill-paragraph (around ess-roxy-fill-advise)
+ "Fill roxygen paragraphs."
+ (cond
+ ;; Regular case
+ ((not (and (eq major-mode 'ess-mode)
+ (string= ess-dialect "R")))
+ ad-do-it)
+ ;; Filling of code comments in @examples roxy field
+ ((and (ess-roxy-entry-p)
+ (save-excursion
+ (back-to-indentation)
+ (looking-at "#")))
+ (ess-roxy-with-filling-context t
+ ad-do-it))
+ ((and (not (ess-roxy-entry-p))
+ (ess-inside-comment-p))
+ ad-do-it)
+ ;; 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)
+ (save-excursion
+ (let* ((saved-pos (point))
+ (saved-line (line-number-at-pos))
+ (saved-col (current-column))
+ (buffer (current-buffer))
+ (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 0)
+ (while (< (point) (point-max))
+ (ess-roxy-maybe-indent-line)
+ ad-do-it
+ (forward-paragraph))))))))
+ (t
+ ad-do-it)))
+
+(defadvice move-beginning-of-line (around ess-roxy-beginning-of-line)
+ "Move to start."
+ (if (ess-roxy-entry-p)
+ (let ((new-pos (save-excursion
+ (end-of-line)
+ (and (re-search-backward (concat ess-roxy-re " ?") (point-at-bol) t)
+ (match-end 0)))))
+ (if (or (bolp)
+ (< new-pos (point)))
+ (goto-char new-pos)
+ ad-do-it))
+ ad-do-it))
+
+(defadvice back-to-indentation (around ess-roxy-back-to-indentation)
+ "Handle `back-to-indentation' in roxygen doc."
+ (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)))
+ ad-do-it))
+
+(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 ()
+ (if (or (not (ess-roxy-entry-p))
+ (not ess-roxy-insert-prefix-on-newline))
+ (newline-and-indent)
+ (ess-roxy-indent-on-newline)))
+
+(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) " ")))))
+
+(provide 'ess-roxy)
+
+;;; ess-roxy.el ends here
--- /dev/null
+;;; ess-rutils.el --- R functions and keybindings to use in iESS.
+
+;; Author: Sebastian Luque <sluqueNOSPAMgmail.com>
+;; Created: Thu Nov 10 02:20:36 2004 (UTC)
+;; Last-Updated: 2013-09-22T16:08:47+0000
+;; By: Sebastian P. Luque
+;; Version: $Id$
+
+;; 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, 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:
+
+;; This library provides key bindings for performing basic R functions,
+;; such as loading and managing packages, as well as object manipulation
+;; (listing, viewing, and deleting), and an alternative to RSiteSearch()
+;; that uses the browse-url function. Load the library with the method you
+;; prefer (e.g. M-x load-file), but the easiest is probably to: a) make
+;; sure your load-path variable includes the directory where ess-rutils.el
+;; resides, and b) include (require 'ess-rutils) statement in your
+;; ~/.emacs.
+;;
+;; Usage:
+;;
+;; Once R is started with M-x R, you should have the key bindings defined
+;; at the end of this file working in your iESS process buffers. Simply
+;; type the desired key binding.
+;;
+;; Acknowledgements:
+;;
+;; I am grateful to John Fox for having written his init.el file for
+;; XEmacs, which motivated this Emacs alternative. I wanted to add some
+;; object management comforts and came across Stephen Eglen's
+;; ess-rdired.el, which provides a lot of these. ess-rutils.el builds upon
+;; on a *lot* of ideas from ess-rdired.el.
+
+;; TODO: Refactor and remove byte-compile-warnings file-local variable.
+;; TODO: This should be more tightly integrated with ess-r-mode and ESSR.
+;; TODO: Should be active in ess-r-mode not only ess-inf
+;; TODO: Both S level Utils and this package's Rutils are in the menu; confusing and inconvenient.
+(defvar pkg)
+
+;;; Code:
+
+;; Autoloads and requires
+(require 'ess-r-mode)
+(require 'ess-rdired)
+
+(defvar ess-rutils-buf "*R temp*"
+ "Name of temporary R buffer.")
+
+(defvar ess-rutils-mode-map nil
+ "Keymap for the *R temp* buffer.")
+
+(unless ess-rutils-mode-map
+ (setq ess-rutils-mode-map (make-sparse-keymap))
+ (define-key ess-rutils-mode-map "l" 'ess-rutils-loadpkg)
+ (define-key ess-rutils-mode-map "i" 'ess-rutils-mark-install)
+ (define-key ess-rutils-mode-map "I" 'ess-rutils-install)
+ (define-key ess-rutils-mode-map "u" 'ess-rutils-unmark)
+ (define-key ess-rutils-mode-map "q" 'ess-rutils-quit)
+ (define-key ess-rutils-mode-map "?" 'ess-rutils-help))
+
+(defun ess-rutils-mode ()
+ "Major mode for output from `ess-rutils-local-pkgs' and `ess-rutils-repos-pkgs'.
+Useful bindings to handle package loading and installing.
+\\{ess-rutils-mode-map}"
+ (kill-all-local-variables)
+ (use-local-map ess-rutils-mode-map)
+ (setq major-mode 'ess-rutils-mode)
+ (setq mode-name (concat "R utils " ess-local-process-name)))
+
+(defun ess-rutils-local-pkgs ()
+ "List all packages in all libraries."
+ (interactive)
+ (if (get-buffer ess-rutils-buf)
+ (progn
+ (set-buffer ess-rutils-buf)
+ (setq buffer-read-only nil)))
+ (ess-execute
+ "writeLines(paste(' ', sort(.packages(all.available=TRUE)), sep=''))"
+ nil
+ (substring ess-rutils-buf 1 (- (length ess-rutils-buf) 1)))
+ (pop-to-buffer ess-rutils-buf)
+ (save-excursion
+ (beginning-of-line) (open-line 1)
+ (insert "**Available packages in all local R libraries**"))
+ (setq buffer-read-only t)
+ (ess-rutils-mode)
+ (if (fboundp 'fit-frame)
+ (fit-frame)))
+
+(defun ess-rutils-namepkg ()
+ "Return name of the package on current line."
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at "*")
+ nil
+ (forward-char 2)
+ (let (beg)
+ (setq beg (point))
+ (end-of-line) ;assume package names are separated by newlines.
+ (buffer-substring-no-properties beg (point))))))
+
+(defun ess-rutils-loadpkg ()
+ "Load package from a library."
+ (interactive)
+ (let ((oklocal nil))
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "libraries**" nil t)
+ (setq oklocal t)))
+ (if oklocal
+ (progn
+ (setq pkg (ess-rutils-namepkg))
+ (ess-execute (concat "library('" pkg "', character.only=TRUE)")
+ 'buffer))
+ nil)))
+
+(defun ess-rutils-repos-pkgs ()
+ "List available packages.
+Use the repositories as listed by getOptions(\"repos\") in the
+current R session."
+ (interactive)
+ (if (get-buffer ess-rutils-buf)
+ (progn
+ (set-buffer ess-rutils-buf)
+ (setq buffer-read-only nil)))
+ (ess-execute (concat "writeLines(paste(' \"', "
+ "rownames(available.packages()), '\"', sep=''))")
+ nil
+ (substring ess-rutils-buf 1 (- (length ess-rutils-buf) 1)))
+ (pop-to-buffer ess-rutils-buf)
+ (save-excursion
+ (kill-line 5)
+ (insert "**packages available to install**\n"))
+ (setq buffer-read-only t)
+ (ess-rutils-mode)
+ (if (fboundp 'fit-frame)
+ (fit-frame)))
+
+(defun ess-rutils-mark-install (arg)
+ "Mark the current package for installing.
+ARG lines to mark is passed to `ess-rutils-mark'."
+ (interactive "p")
+ ;; if this is not an install package buffer return nil.
+ (let ((okmark nil))
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "install**" nil t)
+ (setq okmark t)))
+ (if okmark
+ (ess-rutils-mark "I" arg)
+ nil)))
+
+(defun ess-rutils-unmark (arg)
+ "Unmark the packages, passing ARG lines to unmark to `ess-rutils-mark'."
+ (interactive "p")
+ (ess-rutils-mark " " arg))
+
+;; The next two functions almost verbatim from ess-rdired.el.
+(defun ess-rutils-mark (mark-char arg)
+ "Use MARK-CHAR to mark package on current line, or next ARG lines."
+ ;; If we are on first line, mark all lines.
+ (let ((buffer-read-only nil)
+ move)
+ (if (eq (point-min)
+ (save-excursion (beginning-of-line) (point)))
+ (progn
+ ;; we are on first line, so make a note of point, and count
+ ;; how many objects we want to delete. Then at end of defun,
+ ;; restore point.
+ (setq move (point))
+ (forward-line 1)
+ (setq arg (count-lines (point) (point-max)))))
+ (while (and (> arg 0) (not (eobp)))
+ (setq arg (1- arg))
+ (beginning-of-line)
+ (progn
+ (insert mark-char)
+ (delete-char 1)
+ (forward-line 1)))
+ (if move
+ (goto-char move))))
+
+(defun ess-rutils-install ()
+ "Install all packages flagged for installation, and return to the iESS buffer.
+User is asked for confirmation."
+ (interactive)
+ (let ((inst "install.packages(c(")
+ (count 0))
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line)
+ ;; as long as number of lines between buffer start and point is smaller
+ ;; than the total number of lines in buffer, go to the beginning of the
+ ;; line, check if line is flagged, and if it is, advance the counter by
+ ;; one, create the root of install function, add the package name,
+ ;; insert a comma, and move forward a line.
+ (while (< (count-lines (point-min) (point))
+ (count-lines (point-min) (point-max)))
+ (beginning-of-line)
+ (if (looking-at "^I ")
+ (setq count (1+ count)
+ inst (concat inst (ess-rutils-namepkg) ", " )))
+ (forward-line 1)))
+ (if (> count 0) ;found packages to install
+ (progn
+ ;; Fix the install function created before and close it.
+ (setq inst (concat
+ (substring inst 0 (- (length inst) 2)) "))"))
+ ;;
+ (if (yes-or-no-p (format "Install %d %s " count
+ (if (> count 1) "packages" "package")))
+ (progn
+ (ess-execute inst 'buffer)
+ (ess-rutils-quit))))
+ ;; else nothing to install
+ (message "no packages flagged to install"))))
+
+(defun ess-rutils-update-pkgs (lib repos)
+ "Update packages in library LIB and repos REPOS.
+Defaults are the first element returned by .libPaths() for LIB,
+and the repository named CRAN returned by getOption(\"repos\")
+for REPOS. This also uses checkBuilt=TRUE to rebuild installed
+packages if needed."
+ (interactive "DPath to library to update: \nsrepos: ")
+ (if (string= "" lib)
+ (setq lib
+ (car (ess-get-words-from-vector
+ "as.character(.libPaths())\n"))))
+ (if (string= "" repos)
+ (setq repos
+ (car (ess-get-words-from-vector
+ "as.character(getOption(\"repos\")[\"CRAN\"])\n"))))
+ (ess-execute (concat "update.packages(lib.loc='"
+ lib "', repos='" repos
+ "', ask=FALSE, checkBuilt=TRUE)") 'buffer))
+
+(defun ess-rutils-apropos (string)
+ "Search for STRING using apropos."
+ (interactive "sApropos search for? ")
+ (if (get-buffer ess-rutils-buf)
+ (progn
+ (set-buffer ess-rutils-buf)
+ (setq buffer-read-only nil)))
+ (ess-execute (concat "apropos('" string "')")
+ nil
+ (substring ess-rutils-buf 1 (- (length ess-rutils-buf) 1)))
+ (pop-to-buffer ess-rutils-buf)
+ (setq buffer-read-only t)
+ (ess-rutils-mode))
+
+(defun ess-rutils-rm-all ()
+ "Remove all R objects."
+ (interactive)
+ (if (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.
+File extension not required."
+ (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"))
+ (rhtml (format ".ess_help_start(%s, %s)\n" update remote))
+ (tmpbuf (get-buffer-create "**ess-rutils-mode**")))
+ (ess-command rhtml tmpbuf)
+ (set-buffer tmpbuf)
+ (let* ((begurl (search-backward "http://"))
+ (endurl (search-forward "index.html"))
+ (url (buffer-substring-no-properties begurl endurl)))
+ (browse-url url))
+ (kill-buffer tmpbuf)))
+
+(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 ()
+ "Show help on `ess-rutils-mode'."
+ (interactive)
+ (describe-function 'ess-rutils-mode))
+
+(defun ess-rutils-help-search (string)
+ "Search for STRING using help.search()."
+ (interactive "sString to search for? ")
+ (if (get-buffer ess-rutils-buf)
+ (progn
+ (set-buffer ess-rutils-buf)
+ (setq buffer-read-only nil)))
+ (ess-execute (concat "help.search('" string "')")
+ nil
+ (substring ess-rutils-buf 1 (- (length ess-rutils-buf) 1)))
+ (pop-to-buffer ess-rutils-buf)
+ (setq buffer-read-only t)
+ (ess-rutils-mode))
+
+;; Customizable variable to allow ess-rutils-keys to activate default key bindings.
+;; Suggested by Richard M. Heiberger.
+(defcustom ess-rutils-keys t
+ "Non-nil means activate ess-rutils keybindings and menu."
+ :group 'ess-R
+ :type 'boolean)
+
+;; Keybindings
+(defun ess-rutils-keys ()
+ "Provide key bindings."
+ (interactive)
+ (when ess-rutils-keys
+ (define-key inferior-ess-mode-map [(control c) (control \.) (l)]
+ 'ess-rutils-local-pkgs)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (r)]
+ 'ess-rutils-repos-pkgs)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (u)]
+ 'ess-rutils-update-pkgs)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (a)]
+ 'ess-rutils-apropos)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (m)]
+ 'ess-rutils-rm-all)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (o)]
+ 'ess-rdired)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (w)]
+ 'ess-rutils-load-wkspc)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (s)]
+ 'ess-rutils-save-wkspc)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (d)]
+ 'ess-change-directory)
+ (define-key inferior-ess-mode-map [(control c) (control \.) (H)]
+ 'ess-rutils-html-docs)))
+
+(easy-menu-define ess-rutils-mode-menu inferior-ess-mode-menu
+ "Submenu of `inferior-ess-mode' to use with RUtils."
+ '("RUtils"
+ ["Manage objects" ess-rdired t]
+ ["Remove objects" ess-rutils-rm-all t]
+ "------"
+ ["Local packages" ess-rutils-local-pkgs t]
+ ["Packages in repositories" ess-rutils-repos-pkgs t]
+ ["Update packages" ess-rutils-update-pkgs t]
+ "------"
+ ["Load workspace" ess-rutils-load-wkspc t]
+ ["Save workspace" ess-rutils-save-wkspc t]
+ ["Change directory" ess-change-directory t]
+ "------"
+ ["Browse HTML" ess-rutils-html-docs t]
+ ["Apropos" ess-rutils-apropos t]))
+
+(easy-menu-add-item inferior-ess-mode-menu nil ess-rutils-mode-menu "Utils")
+(add-hook 'inferior-ess-mode-hook 'ess-rutils-keys)
+
+(make-obsolete 'ess-rutils-rhtml-fn "overwrite .ess_help_start instead." "ESS 18.10")
+
+(provide 'ess-rutils)
+
+;;; ess-rutils.el ends here
+
+;; Local Variables:
+;; byte-compile-warnings: (not lexical)
+;; End:
--- /dev/null
+;;; ess-s-lang.el --- Support for editing S source code
+
+;; 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 <rossiniNOSPAMbiostat.washington.edu>
+;; Created: 26 Aug 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+\f ; Requires and autoloads
+
+(require 'ess-mode)
+(require 'ess-help)
+(require 'ess-utils)
+(require 'ess-inf)
+
+(autoload 'speedbar-add-supported-extension "speedbar.el")
+
+\f ; 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)
+ (require-final-newline . mode-require-final-newline)
+ ;;(comment-indent-function . 'S-comment-indent)
+ ;;(ess-comment-indent . 'S-comment-indent)
+ ;;(ess-indent-line . 'S-indent-line)
+ ;;(ess-calculate-indent . 'ess-calculate-indent)
+ (indent-line-function . 'ess-indent-line)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style)
+ ;;(ess-keep-dump-files . 'ask)
+ (ess-mode-syntax-table . S-syntax-table)
+ ;; 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 . "#")
+ (ess-imenu-generic-expression . ess-imenu-S-generic-expression)
+ (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-get-help-topics-function . #'ess-s-get-help-topics-function)
+ (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)
+ (normal-auto-fill-function . 'ess-do-auto-fill)
+ (ess-execute-screen-options-command . "options(width=%d, length=99999)\n")
+ (inferior-ess-font-lock-keywords . 'inferior-S-font-lock-keywords)
+ (ess-font-lock-keywords . 'ess-S-font-lock-keywords)
+ (font-lock-defaults . '(ess-build-font-lock-keywords
+ nil nil ((?\. . "w") (?\_ . "w")))))
+ "S-language common settings for all <dialect>-customize-alist s")
+
+(defconst S+common-cust-alist
+ (append
+ '((ess-suffix . "S")
+ (ess-mode-syntax-table . S-syntax-table)
+ (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 s"
+ )
+
+;;; 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.")
+
+\f ; 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))))
+
+;; VS: these are ess-indent-line and ess-calculate-indent from 2004 already,so
+;; commented out to avoid confusion:
+
+;; (defun S-indent-line ()
+;; "Indent current line as S code.
+;; Return the amount the indentation changed by."
+;; (let ((indent (S-calculate-indent nil))
+;; beg shift-amt
+;; (case-fold-search nil)
+;; (pos (- (point-max) (point))))
+;; (beginning-of-line)
+;; (setq beg (point))
+;; (cond ((eq indent nil)
+;; (setq indent (current-indentation)))
+;; (t
+;; (skip-chars-forward " \t")
+;; (cond ((and ess-indent-with-fancy-comments ;; ### or #!
+;; (or (looking-at "###")
+;; (and (looking-at "#!") (= 1 (line-number-at-pos)))))
+;; (setq indent 0))
+;; ;; Single # comment
+;; ((and ess-indent-with-fancy-comments
+;; (looking-at "#") (not (looking-at "##")))
+;; (setq indent comment-column))
+;; (t
+;; (if (eq indent t) (setq indent 0))
+;; (if (listp indent) (setq indent (car indent)))
+;; (cond ((and (looking-at "else\\b")
+;; (not (looking-at "else\\s_")))
+;; (setq indent (save-excursion
+;; (ess-backward-to-start-of-if)
+;; (+ ess-else-offset (current-indentation)))))
+;; ((= (following-char) ?})
+;; (setq indent
+;; (+ indent
+;; (- ess-close-brace-offset ess-indent-offset))))
+;; ((= (following-char) ?{)
+;; (setq indent (+ indent ess-brace-offset))))))))
+;; (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.
+;; (if (> (- (point-max) pos) (point))
+;; (goto-char (- (point-max) pos))))
+;; shift-amt))
+
+;; (defun S-calculate-indent (&optional parse-start)
+;; "Return appropriate indentation for current line as S 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))
+;; (beginning-of-defun-function nil) ;; don't call ess-beginning-of-function
+;; (case-fold-search nil)
+;; state
+;; containing-sexp)
+;; (if parse-start
+;; (goto-char parse-start)
+;; (beginning-of-defun))
+;; (while (< (point) indent-point)
+;; (setq parse-start (point))
+;; (setq state (parse-partial-sexp (point) indent-point 0))
+;; (setq containing-sexp (car (cdr state))))
+;; (cond ((or (nth 3 state) (nth 4 state))
+;; ;; return nil or t if should not change this line
+;; (nth 4 state))
+;; ((null containing-sexp)
+;; ;; Line is at top level. May be data or function definition,
+;; (beginning-of-line)
+;; (if (and (/= (following-char) ?\{)
+;; (save-excursion
+;; (ess-backward-to-noncomment (point-min))
+;; (ess-continued-statement-p)))
+;; ess-continued-statement-offset
+;; 0)) ; Unless it starts a function body
+;; ((/= (char-after containing-sexp) ?{)
+;; ;; line is expression, not statement:
+;; ;; indent to just after the surrounding open.
+;; (goto-char containing-sexp)
+;; (let ((bol (save-excursion (beginning-of-line) (point))))
+
+;; ;; modified by shiba@isac 7.3.1992
+;; (cond ((and (numberp ess-expression-offset)
+;; (re-search-backward "[ \t]*expression[ \t]*" bol t))
+;; ;; This regexp match every "expression".
+;; ;; modified by shiba
+;; ;;(forward-sexp -1)
+;; (beginning-of-line)
+;; (skip-chars-forward " \t")
+;; ;; End
+;; (+ (current-column) ess-expression-offset))
+;; ((and (numberp ess-arg-function-offset)
+;; (re-search-backward
+;; "=[ \t]*\\s\"?\\(\\w\\|\\s_\\)+\\s\"?[ \t]*"
+;; bol
+;; t))
+;; (forward-sexp -1)
+;; (+ (current-column) ess-arg-function-offset))
+;; ;; "expression" is searched before "=".
+;; ;; End
+
+;; (t
+;; (progn (goto-char (1+ containing-sexp))
+;; (current-column))))))
+;; (t
+;; ;; Statement level. Is it a continuation or a new statement?
+;; ;; Find previous non-comment character.
+;; (goto-char indent-point)
+;; (ess-backward-to-noncomment containing-sexp)
+;; ;; Back up over label lines, since they don't
+;; ;; affect whether our line is a continuation.
+;; (while (eq (preceding-char) ?\,)
+;; (ess-backward-to-start-of-continued-exp containing-sexp)
+;; (beginning-of-line)
+;; (ess-backward-to-noncomment containing-sexp))
+;; ;; Now we get the answer.
+;; (if (ess-continued-statement-p)
+;; ;; This line is continuation of preceding line's statement;
+;; ;; indent ess-continued-statement-offset more than the
+;; ;; previous line of the statement.
+;; (progn
+;; (ess-backward-to-start-of-continued-exp containing-sexp)
+;; (+ ess-continued-statement-offset (current-column)
+;; (if (save-excursion (goto-char indent-point)
+;; (skip-chars-forward " \t")
+;; (eq (following-char) ?{))
+;; ess-continued-brace-offset 0)))
+;; ;; This line starts a new statement.
+;; ;; Position following last unclosed open.
+;; (goto-char containing-sexp)
+;; ;; Is line first statement after an open-brace?
+;; (or
+;; ;; If no, find that first statement and indent like it.
+;; (save-excursion
+;; (forward-char 1)
+;; (while (progn (skip-chars-forward " \t\n")
+;; (looking-at "#"))
+;; ;; Skip over comments following openbrace.
+;; (forward-line 1))
+;; ;; The first following code counts
+;; ;; if it is before the line we want to indent.
+;; (and (< (point) indent-point)
+;; (current-column)))
+;; ;; If no previous statement,
+;; ;; indent it relative to line brace is on.
+;; ;; For open brace in column zero, don't let statement
+;; ;; start there too. If ess-indent-offset is zero, use
+;; ;; ess-brace-offset + ess-continued-statement-offset
+;; ;; instead.
+;; ;; For open-braces not the first thing in a line,
+;; ;; add in ess-brace-imaginary-offset.
+;; (+ (if (and (bolp) (zerop ess-indent-offset))
+;; (+ ess-brace-offset ess-continued-statement-offset)
+;; ess-indent-offset)
+;; ;; Move back over whitespace before the openbrace.
+;; ;; If openbrace is not first nonwhite thing on the line,
+;; ;; add the ess-brace-imaginary-offset.
+;; (progn (skip-chars-backward " \t")
+;; (if (bolp) 0 ess-brace-imaginary-offset))
+;; ;; If the openbrace is preceded by a parenthesized exp,
+;; ;; move to the beginning of that;
+;; ;; possibly a different line
+;; (progn
+;; (if (eq (preceding-char) ?\))
+;; (forward-sexp -1))
+;; ;; Get initial indentation of the line we are on.
+;; (current-indentation))))))))))
+
+;;*;; S/R Pretty-Editing
+
+(defun ess-fix-comments (&optional dont-query verbose)
+ "Fix ess-mode 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 changes in an S - dump() file to improve human readability."
+ (interactive "P")
+ (ess-mode)
+ (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)
+ "Is VERY useful for dump(.)'ed numeric variables; ROUND some of them by
+ replacing endings of 000000*.. and 999999*. Martin Maechler"
+ (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; typically from S-plus"
+ ;; 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]\\)\\(<<?-\\)" "\\1 \\2" nil nil verbose)
+ (goto-char from)(ess-rep-regexp "<-\\([^ \t\n]\\)" "<- \\1" nil nil verbose)
+ ;; ensure space around "<" (not in "<-","<=","<<-") and ">" (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-smart-S-assign-key' is nil, do `self-insert-command' using
+ARG as the number of times to insert."
+ (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)))
+
+(defun ess-smart-S-assign (arg)
+ "Insert `ess-smart-S-assign-key'.
+Please use `ess-insert-assign'."
+ (interactive "p")
+ (with-no-warnings ; Obsolete key variable
+ (if ess-smart-S-assign-key
+ (ess-insert-assign arg)
+ (self-insert-command arg))))
+
+(make-obsolete 'ess-smart-S-assign 'ess-insert-assign "ESS 18.10")
+
+(defun ess-disable-smart-S-assign (&rest _ignore)
+ "Disable `ess-insert-assign'."
+ (declare (obsolete "Use ess-smart-S-assign-key instead." "ESS 18.10"))
+ (with-no-warnings ; Obsolete key variable
+ (setq ess-smart-S-assign-key nil)))
+
+(defun ess-add-MM-keys ()
+ "Define MM's user keys, currently \\<ess-mode-map>\\[ess-insert-function-outline], and
+ \\<inferior-ess-mode-map>\\[ess-execute-screen-options]."
+ (interactive)
+ (require 'ess-mode); typically unnecessary
+ (require 'ess-inf); dito
+ (define-key inferior-ess-mode-map "\C-cw" 'ess-execute-screen-options)
+
+ ;; Make M-- : [Alt] + [-] (in addition to / instead of "_" = (on US-keyboard) [Shift]+ [-]
+ ;; Note this overwrites 'M--' as "negative argument" (still on 'C--'):
+ (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) ; &optional buff)
+ "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 ? ")
+ (let* ((buffname "ess-complete.R")
+ (buf (ess-execute (format "args(%s)" Sfunc) t buffname)))
+ (pop-to-buffer buf)
+ (message "here yet?")
+ (while (search-forward "function" nil t)
+ (replace-match Sfunc nil t))
+ (ess-setq-vars-local ess-customize-alist); (current-buffer))
+ (setq major-mode 'ess-mode)
+ (use-local-map ess-mode-map)
+ (set-syntax-table ess-mode-syntax-table)
+ ))
+
+(defun ess-chm-display-help-on-object (object &rest args)
+ (ess-eval-linewise (concat "help(" object ")")))
+
+
+;;; S imenu support
+
+;; don't use syntax classes, bad for etags
+(defvar ess-imenu-S-generic-expression
+ '(("Functions" "^\\(.+\\)[ \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)
+ ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1)
+ ;;
+ ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1)
+ ("Package" "^.*\\(library\\|require\\)(\\(.*\\)" 2)
+ ("Data" "^\\(.+\\)[ \t\n]-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1)))
+
+(defun ess-imenu-S (&optional arg)
+ "S Language Imenu support for ESS."
+ (interactive)
+ (setq imenu-generic-expression ess-imenu-generic-expression)
+ (imenu-add-to-menubar "Imenu-S"))
+
+(defalias 'ess-imenu-R 'ess-imenu-S)
+
+
+\f ;;; Speedbar stuff.
+(defun ess-S-initialize-speedbar ()
+ "Extend to all extensions; see initialization, and edit."
+ (speedbar-add-supported-extension ".R")
+ (speedbar-add-supported-extension ".S")
+ (speedbar-add-supported-extension ".s")
+ (speedbar-add-supported-extension ".q"))
+
+ ;(if (featurep 'speedbar)
+ ; (progn
+ ; (message "enabling speedbar support")
+ ; (require 'speedbar)
+ ; (ess-S-initialize-speedbar)))
+
+(eval-when-compile
+ (condition-case nil
+ (progn
+ (require 'speedbar)
+ (when (featurep 'speedbar)
+
+ (defun S-speedbar-buttons (buffer)
+ "attempted hack."
+
+ ;;(speedbar-make-tag-line)
+ ;;(speedbar-insert-button)
+ (speedbar-with-writable))
+
+ (fset 'R-speedbar-buttons 'S-speedbar-buttons)
+
+ (defun S-speedbar-menu-items ( )
+ "Need to write.")
+
+ (ess-S-initialize-speedbar)))
+ (error nil)))
+
+(defun ess-s-get-help-topics-function (name)
+ "Return a list of current S help topics associated with process NAME.
+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
+ (ess-write-to-dribble-buffer
+ (format "(ess-get-help-topics-list %s) .." name))
+ (when (fboundp 'ess-help-r--check-last-help-type)
+ (ess-help-r--check-last-help-type))
+ (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
+ (ess-uniq-list
+ (append (ess-get-object-list name 'exclude-1st)
+ (ess-get-help-files-list)
+ (ess-get-help-aliases-list)))))
+ (t
+ ess-help-topics-list))))
+
+;;; On a PC, the default is S+.
+;; Elsewhere (unix and linux) the default is S+
+(cond (ess-microsoft-p
+ ;; MS-Windows-------------------------------------------------
+
+ ;; (fset 'S
+ ;; (if (equal (file-name-nondirectory shell-file-name) "cmdproxy.exe")
+ ;; 'S+-msdos
+ ;; 'S+))
+ (defun S-by-icon (&rest x)
+ (interactive)
+ (message "Please start S+ from the icon.
+ Then you can connect emacs to it with `M-x S-existing'.")
+ )
+ (fset 'S 'S-by-icon)
+ (fset 'S-existing
+ (if (equal (file-name-nondirectory shell-file-name) "cmdproxy.exe")
+ 'S+-msdos-existing
+ 'S+-existing))
+ (fset 'Sqpe 'Sqpe+)
+ (fset 's-mode 'S+-mode)
+ (fset 's-transcript-mode 'S+-transcript-mode))
+
+ (t ;;((eq system-type 'gnu/linux)
+ ;; Linux etc (including Mac OSX !?) --------------------------
+ (fset 'S 'S+)
+ (fset 's-mode 'S+-mode)
+ (fset 's-transcript-mode 'S+-transcript-mode)))
+
+;;;;* Alias S-mode to s-mode
+;;; Emacs will set the mode for a file based on the file's header.
+;;; The mode name is indicated by putting it between -*- on the top line.
+;;; (Other commands can go here too, see an Emacs manual.)
+;;; For a file you also load, you will want a leading # (comment to S)
+;;; Emacs will downcase the name of the mode, e.g., S, so we must provide
+;;; s-mode in lower case too. That is, "#-*- S-*-" invokes s-mode and
+;;; not S-mode.
+(fset 'S-transcript-mode 's-transcript-mode)
+(fset '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
--- /dev/null
+;;; ess-s3-d.el --- S 3 (AT&T version) customization
+
+;; Copyright (C) 1997 A. J. Rossini
+;; Copyright (C) 1998--2005 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Created: 12 Jun 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 3 customizations for ess-mode.
+
+;;; Code:
+
+(require 'ess-s-lang)
+
+(defvar S3-customize-alist
+ (append
+ '((ess-local-customize-alist . 'S3-customize-alist)
+ (ess-dialect . "S3")
+ (ess-change-sp-regexp . ess-S-change-sp-regexp)
+ (ess-help-sec-keys-alist . ess-help-S3-sec-keys-alist)
+ (ess-object-name-db-file . "ess-s3-namedb.el" )
+ (inferior-ess-program . inferior-S3-program) ; "S")
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . nil)
+ (inferior-ess-search-list-command . "search()\n")
+ (inferior-ess-objects-command . "objects(%d)\n")
+ (inferior-ess-start-file . nil) ;"~/.ess-S3")
+ (inferior-ess-start-args . "")
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist); use S+ ones here; partly overwritten above!!
+
+ "Variables to customize for S3")
+
+(defun S3 (&optional proc-name)
+ "Call 'S 3.x', the version from AT&T."
+ (interactive)
+ (setq ess-customize-alist S3-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S3): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer)))
+ (inferior-ess)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start)))
+
+
+(defun S3-mode (&optional proc-name)
+ "Major mode for editing S3 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S3-customize-alist)
+ (ess-mode S3-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+
+\f ; Provide package
+
+(provide 'ess-s3-d)
+
+;;; ess-s3-d.el ends here
--- /dev/null
+;;; ess-s4-d.el --- S4 customization
+
+;; Copyright (C) 1997--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Created: 12 Jun 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+;; DB contributed the changes from ess-s3-d.el to
+;; ess-s4-d.el (removed the old ugly approach).
+;; This file defines S4 customizations for ess-mode. Lots of thanks
+;; to RMH and JMC for code and suggestions
+
+;;; Code:
+
+(require 'ess-s-lang)
+
+;; Some of this is based on files from:
+;; Copyright (C) 1996, John M. Chambers.
+
+(defvar S4-customize-alist
+ (append
+ '((ess-local-customize-alist . 'S4-customize-alist)
+ (ess-dialect . "S4")
+ (ess-change-sp-regexp . ess-S-change-sp-regexp)
+ (ess-help-sec-keys-alist . ess-help-S3-sec-keys-alist)
+ (ess-object-name-db-file . "ess-s4-namedb.el")
+ (inferior-ess-program . inferior-S4-program)
+ (inferior-ess-objects-command . ".SmodeObs(%d, pattern=\"%s\")\n")
+ ;;(inferior-ess-objects-pattern . ".*") ; for new s4 stuff
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . nil)
+ (inferior-ess-search-list-command . ".SmodePaths()\n")
+ (ess-load-command . ".SmodeLoad(\"%s\")\n")
+ (inferior-ess-dump-command . ".SmodeDump(\"%s\", \"%s\")\n")
+
+ (inferior-ess-start-file . nil) ;"~/.ess-S3")
+ (inferior-ess-start-args . "")
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist); use S+ ones here; partly overwritten above!!
+
+ "Variables to customize for S4.")
+
+;; For loading up the S code required for the above.
+;;(add-hook 'ess-post-run-hook
+;; (lambda ()
+;; (ess-command
+;; (concat
+;; "if(exists(\"Sversion\")) library(emacs) else source(\""
+;; ess-mode-run-file
+;; "\")\n"))
+;; (if ess-mode-run-file2
+;; (ess-command
+;; (concat "source(\"" ess-mode-run-file2 "\")\n")))))
+
+
+(defun S4 ()
+ "Call 'S version 4', from Bell Labs. New way to do it."
+ (interactive)
+ (setq ess-customize-alist S4-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S4): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer)))
+ (inferior-ess)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start)))
+
+
+(defun S4-mode (&optional proc-name)
+ "Major mode for editing S4 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S4-customize-alist)
+ (ess-mode S4-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+
+;; From RMH: ALL THIS SHOULD BE INCORPORATED BY 5.0!
+
+;;; s4.el startup file
+;;; Richard M. Heiberger
+;;; rmhNOSPAMtemple.edu
+;;
+;;(load "S")
+;;(setq inferior-S-program "/disk05/s4/betaJun96/S")
+;;(setq S-plus nil) ;; needed for non S-plus
+;;(add-to-list 'load-path "/disk05/s4/betaJun96") ;; S-namedb.el is here
+;;(S)
+;;(load-file "/disk05/s4/betaJun96/library/emacs/S-modeadds.el") ;; must come after (S)
+;;
+;;
+;;;;; S4 __Help, no longer S3 .Help
+;;(load "S-help")
+;; ;; Must follow S-help
+;;; S-help.file line 270
+;;(defun S-get-help-files-list nil
+;; (mapcar 'list
+;; (apply 'append
+;; (mapcar (lambda (dirname)
+;; (if (file-directory-p dirname)
+;; (directory-files dirname)))
+;; (mapcar (lambda (str) (concat str "/__Help"))
+;; (S-search-list))))))
+;;
+;;
+;;;;; additional font-lock-keywords for S4
+;;
+;;;;*;; based on S-inf.el line 107
+;;;;(add-to-list 'S-inf-font-lock-keywords
+;;;; '("\\<\\(^Problem\\|^Warning\\|^Error\\|Debug ?\\|Browsing in frame of\\|Local Variables\\)\\>" . font-lock-reference-face) ; S-inf problems
+;;;;)
+;;;;(add-to-list 'S-inf-font-lock-keywords
+;;;; '("^R>" . font-lock-keyword-face) ; debug prompt
+;;;;)
+;;(inferior-S-mode)
+;;
+;;; S-inf.el line 150
+;;(setq inferior-S-search-list-command "searchPaths()\n")
+;;
+;;;; fontify S-transcript-mode
+;;;; overwrites S-trans.el lines 60-69
+;;;;(setq S-trans-font-lock-keywords S-inf-font-lock-keywords)
+;;
+;;(load "S-mode")
+;; ;; Must follow S-mode
+;;;;*;; based on S-mode.el line 219
+;;(add-to-list 'S-mode-font-lock-keywords
+;; '("\\<\\(setGeneric\\|removeGeneric\\|setMethod\\|unsetMethod\\|setReplaceGeneric\\|setReplaceMethod\\|standardGeneric\\|setIs\\|setClass\\|representation\\)\\>" . font-lock-function-name-face) ; S4 method functions
+;;)
+;;
+;;
+;;
+;;;;; fix to S-load-file to make C-c C-l work with S4
+;;
+;;;When a file sourced into S4 by C-c C-l has a syntax error
+;;;without the following changes, the system
+;;;freezes until it is released with ^G. The reason is that the error
+;;;messages, including the `Debug ?' request, go to the *S-errors*
+;;;buffer. The *S-errors* buffer is not switched to, and couldn't accept
+;;;a response if it were.
+;;;
+;;;The fix requires three modification to S-inf.el and two to S-mode.el.
+;;;The correction to S-check-source noted in smode.cmt is also necessary.
+;;;
+;;
+;;; S-inf.el line 92 NEW variable
+;;(defvar inferior-S-debug-prompt "Debug \\? (y|n): "
+;; "The expression S uses to offer to initiate debug tracing.")
+;;
+;;; S-inf.el line 458
+;;(defun inferior-S-wait-for-prompt ()
+;; "Wait until the S process is ready for input."
+;; (let* ((cbuffer (current-buffer))
+;; (sprocess (get-S-process S-current-process-name))
+;; (sbuffer (process-buffer sprocess))
+;; r
+;; (timeout 0))
+;; (set-buffer sbuffer)
+;; (while (progn
+;; (if (not (eq (process-status sprocess) 'run))
+;; (S-error "S process has died unexpectedly.")
+;; (if (> (setq timeout (1+ timeout)) S-loop-timeout)
+;; (S-error "Timeout waiting for prompt. Check inferior-S-prompt or S-loop-timeout."))
+;; (accept-process-output)
+;; (goto-char (point-max))
+;;(setq end (point))
+;; (beginning-of-line)
+;;(setq e (buffer-substring (point) end))
+;;(if (equal e inferior-S-debug-prompt)
+;; (S-error "Debug prompt"))
+;; (setq r (looking-at inferior-S-prompt))
+;; (not (or r (looking-at ".*\\?\\s *"))))))
+;; (goto-char (point-max))
+;; (set-buffer cbuffer)
+;; (symbol-value r)))
+;;
+;;
+;;
+;;; S-mode.el line 204
+;;(setq S-dump-error-re "Problem")
+;;
+;;;; S-mode.el line 655
+;;(defun S-parse-errors (showerr)
+;; "Jump to error in last loaded S source file.
+;;With prefix argument, only shows the errors S reported."
+;; (interactive "P")
+;; (S-make-buffer-current)
+;; (let ((errbuff (get-buffer S-error-buffer-name)))
+;; (if (not errbuff)
+;; (error "You need to do a load first!")
+;; (set-buffer errbuff)
+;; (goto-char (point-max))
+;; (if
+;; (re-search-backward ", file \"" nil t)
+;; (let* ((beg-pos (progn (re-search-forward "\"" nil t) (point)))
+;; (end-pos (progn (re-search-forward "\"" nil t) (- (point) 1)))
+;; (filename (buffer-substring beg-pos end-pos))
+;; (fbuffer (get-file-buffer filename))
+;; (linenum (string-to-number
+;; (progn (re-search-backward "," nil t)
+;; (current-word))))
+;; (end-pos (point))
+;; (beg-pos (progn (goto-char (point-min))
+;; (re-search-forward ":" nil t)
+;; (1+ (point))))
+;; (errmess (buffer-substring beg-pos end-pos))
+;; )
+;; (if showerr
+;; (S-display-temp-buffer errbuff)
+;; (if fbuffer nil
+;; (setq fbuffer (find-file-noselect filename))
+;; (save-excursion
+;; (set-buffer fbuffer)
+;; (S-mode)))
+;; (pop-to-buffer fbuffer)
+;; (goto-line linenum))
+;; (princ errmess t))
+;; (message "Not a syntax error.")
+;; (S-display-temp-buffer errbuff)))))
+;;
+;;
+;;
+;;;; S-inf.el line 584
+;;(defun S-prompt-wait (proc &optional start-of-output)
+;; "Wait for a prompt to appear at BOL of current buffer
+;;PROC is the S 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 500)
+;; (goto-char (marker-position (process-mark proc)))
+;; (beginning-of-line)
+;;
+;; (if (re-search-forward inferior-S-debug-prompt nil t)
+;; (if (equal (get-buffer S-error-buffer-name)
+;; (get-buffer S-error-buffer-name))
+;; (let* ((sprocess (get-S-process S-current-process-name))
+;; (sbuffer (process-buffer sprocess)))
+;; (set-buffer sbuffer)
+;; (process-send-string sprocess "n\n")
+;; (accept-process-output sprocess)
+;; (beginning-of-line); delete inferior-S-debug-prompt
+;; (kill-line)
+;; (insert "> ")))
+;;
+;; (if (< (point) start-of-output) (goto-char start-of-output))
+;; (not (looking-at inferior-S-primary-prompt)))))))
+;;
+
+
+
+\f ; Provide package
+
+(provide 'ess-s4-d)
+
+;;; ess-s4-d.el ends here
--- /dev/null
+;;; 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-coreNOSPAMr-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-smart-back-tab nil
+;; "*Set to t to make C-TAB insert an end/%end; statement to close a block."
+;; :group 'ess-sas
+;;)
+
+(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 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).")
+
+(make-variable-buffer-local 'ess-sas-submit-method)
+
+(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 `ess-uniq-list'.
+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\\).*$")
+ (let* ((exit-done "\\[[0-9]+\\]\\ *\\+*\\ *\\(Exit\\|Done\\)[^\r\n]*") ; GNU Emacs needs this
+ (beg (string-match exit-done string)))
+ (if beg
+ (message (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."
+ (if file-or-buffer (set-buffer (ess-get-file-or-buffer 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 (boundp 'auto-image-file-mode) 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-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-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\\|\f\\|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.
+ (ess-uniq-list
+ (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
--- /dev/null
+;;; 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 <rmhNOSPAMtemple.edu>
+;; Created: 20 Aug 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 'comint)
+(require 'shell)
+(require 'executable)
+(require 'ess-sas-l)
+
+(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).")
+
+(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")
+ (ess-mode-editing-alist . SAS-editing-alist) ; from ess-sas-l.el
+ (ess-mode-syntax-table . SAS-syntax-table)
+ (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-file . nil) ;"~/.ess-SAS")
+ (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
+(defun SAS-mode (&optional proc-name)
+ "Major mode for editing SAS source. See ess-mode for more help."
+ (interactive)
+ (setq ess-customize-alist SAS-customize-alist)
+ (ess-mode SAS-customize-alist proc-name)
+
+ ;; Local map settings, AFTER initialization (only if not yet defined)
+ (if sas-mode-local-map
+ nil
+ (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)
+
+ ;; 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)
+
+ (set (make-local-variable 'font-lock-defaults)
+ ;; KEYWORDS KEYWORDS-ONLY CASE-FOLD .....
+ '(SAS-mode-font-lock-defaults nil t))
+ ;; ^^ this *should* set
+ ;; font-lock-keywords-case-fold-search, but it fails for Emacs 22.[23]
+ ;; hence :
+ (setq font-lock-keywords-case-fold-search t)
+ (run-mode-hooks 'SAS-mode-hook))
+
+
+;;;###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)
+ (ess-indent-line)
+ (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))))))
+
+;;;###autoload
+(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)
+ (setq-default ess-customize-alist SAS-customize-alist)
+ (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)
+ (inferior-ess)
+ (with-current-buffer "*SAS*"
+ (use-local-map sas-mode-local-map))))
+
+
+(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)))
+
+
+(add-hook 'ess-mode-hook
+ (lambda ()
+ (when (string= ess-language "SAS") ;; e.g. not for R-only users
+ (local-set-key "\C-c\C-w" 'ess-multi-frame-SAS))))
+
+(defun ess-num-or-zero (arg)
+ "*If a number, then return that number, otherwise return 0."
+ (or (and (numberp arg) arg) 0))
+
+\f ; Provide package
+
+(provide 'ess-sas-d)
+
+;;; ess-sas-d.el ends here
--- /dev/null
+;;; 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 <ESS-coreNOSPAMr-project.org>
+
+;; 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
+;;; cookNOSPAMbiostat.wisc.edu
+;;;
+;;; Acknowledgements:
+;;; Menu code for XEmacs/Lucid emacs and startup mods
+;;; contributed by arossiniNOSPAMbiostats.hmc.psu.edu
+;;;
+;;; Last change: 2/1/95
+;;; Last change: 01/15/02
+
+;;; Code:
+
+(require 'ess-mode)
+(require 'ess-custom)
+(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))
+
+(defun SAS-log-mode ()
+"`ess-transcript-mode' for SAS."
+(interactive)
+(SAS-mode)
+(setq mode-name "ESS[LOG]")
+(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")
+(defun SAS-listing-mode()
+"Fundamental mode with `ess-listing-minor-mode' and read-only."
+(interactive)
+(fundamental-mode)
+(setq mode-name "ESS[LST]")
+(ess-listing-minor-mode 1)
+(use-local-map sas-mode-local-map)
+(setq buffer-read-only t) ;; to protect the buffer.
+(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 string 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)
+
+ ;never used--see ess-sas-submit-command-options in ess-sas-a.el
+ ;(defcustom sas-options-string ""
+ ; "*Options to be passed to sas as if typed on the command line."
+ ; :group 'ess-sas
+ ; :type 'string)
+
+(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-syntax-table nil "Syntax table for SAS code.")
+
+(if SAS-syntax-table nil
+ (setq SAS-syntax-table (make-syntax-table))
+
+ ;; (if (equal system-type 'windows-nt)
+ ;; ;; backslash is punctuation (used in MS file names)
+ ;; (modify-syntax-entry ?\\ "." SAS-syntax-table)
+ ;; ;; backslash is an escape character
+ ;; (modify-syntax-entry ?\\ "\\" SAS-syntax-table))
+ (modify-syntax-entry ?\\ "." SAS-syntax-table) ;; backslash is punctuation
+ (modify-syntax-entry ?+ "." SAS-syntax-table)
+ (modify-syntax-entry ?- "." SAS-syntax-table)
+ (modify-syntax-entry ?= "." SAS-syntax-table)
+ (modify-syntax-entry ?% "w" SAS-syntax-table)
+ (modify-syntax-entry ?< "." SAS-syntax-table)
+ (modify-syntax-entry ?> "." SAS-syntax-table)
+ (modify-syntax-entry ?& "w" SAS-syntax-table)
+ (modify-syntax-entry ?| "." SAS-syntax-table)
+ (modify-syntax-entry ?\' "\"" SAS-syntax-table)
+ (modify-syntax-entry ?* ". 23" SAS-syntax-table) ; comment character
+ (modify-syntax-entry ?\; "." SAS-syntax-table)
+ (modify-syntax-entry ?_ "w" SAS-syntax-table)
+ (modify-syntax-entry ?< "." SAS-syntax-table)
+ (modify-syntax-entry ?> "." SAS-syntax-table)
+ (modify-syntax-entry ?/ ". 14" SAS-syntax-table) ; comment character
+ (modify-syntax-entry ?. "w" SAS-syntax-table))
+
+(require 'font-lock); fontification also works in terminals!
+;; (if (or window-system
+;; noninteractive) ; compilation!
+;;; ...
+
+
+(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 "\\<and(" font-lock-function-name-face)
+ (cons "\\<data=" font-lock-keyword-face)
+ (cons "\\<in:(" font-lock-function-name-face)
+ (cons "\\<index(" font-lock-function-name-face)
+ (cons "\\<input(" font-lock-function-name-face)
+ (cons "\\<libname(" font-lock-function-name-face)
+ (cons "\\<not(" font-lock-function-name-face)
+ (cons "\\<or(" font-lock-function-name-face)
+ (cons "\\<put(" font-lock-function-name-face)
+ (cons "\\<sum(" font-lock-function-name-face)
+
+ ; other idiosyncratic keywords
+ ;(cons "key=" font-lock-keyword-face)
+ ;(cons "/unique" font-lock-keyword-face)
+
+ ;; SAS execution blocks: DATA, %MACRO/%MEND, %DO/%END, etc.
+ (cons (regexp-opt '(
+ "data" "start" "return" ;"proc"
+ "%macro" "%mend"
+ "%do" "%to" "%by" "%end"
+ "%goto" "%go to"
+ "%if" "%then" "%else"
+ "%global" "%inc" "%include" "%input" "%local" "%let" "%put" "%sysexec"
+ ) 'words) font-lock-constant-face)
+
+ ;; SAS execution blocks that must be followed by a semi-colon
+ (cons (concat "\\<"
+ (regexp-opt
+ '(
+ "run;" "quit;" "endsas;" "finish;"
+ "cards;" "cards4;" "datalines;" "datalines4;" "lines;" "lines4;"
+ )))
+ font-lock-constant-face)
+
+ ;; SAS statements that must be followed by a semi-colon
+ (cons (concat "\\<"
+ (regexp-opt
+ '(
+ "end;" "list;" "lostcard;" "page;" "stop;" ;"return;"
+ )))
+ font-lock-keyword-face)
+
+ ;; SAS statements that must be followed by an equal sign
+ (cons (concat "\\<"
+ (regexp-opt
+ '(
+ "compress=" "in=" "out=" "sortedby="
+ )))
+ font-lock-keyword-face)
+
+;;; ;; SAS procedure names
+ (cons (concat "\\<proc[ ]+"
+ (regexp-opt '(
+ ;; SAS base and SAS/Graph
+ "append"
+ "calendar" "catalog" "chart" "cimport" "cport" "compare" "contents" "copy" "corr"
+ "datasets" "dbcstab" "display"
+ "explode" "export"
+ "fcmp" "format" "forms" "freq" "fsbrowse" "fsedit" "fsletter" "fslist" "fsview"
+ "ganno" "gchart" "gcontour" "gdevice" "geocode" "gfont" "gimport" "ginside"
+ "gkeymap" "gmap" "goptions" "gplot" "gprint" "gproject" "greduce" "gremove"
+ "greplay" "gslide" "gtestit" "g3d" "g3grid"
+ "iml" "import" "insight"
+ "mapimport" "means"
+ "options"
+ "plot" "pmenu" "print" "printto"
+ "rank" "registry" "report"
+ "setinit" "sgdesign" "sgmap"
+ "sgpanel" "sgplot" "sgrender" "sgscatter" "sort" "sql" "standard" "summary"
+ "tabulate" "template" "timeplot" "transpose" "trantab"
+ "univariate"
+
+ ;;SAS/Stat and SAS/ETS
+ "aceclus" "anova" "arima" "autoreg"
+ "bgenmod" "blifereg" "boxplot" "bphreg"
+ "calis" "cancorr" "candisc" "catmod" "citibase" "cluster" "computab" "corresp" "countreg"
+ "discrim" "distance"
+ "entropy" "expand"
+ "factor" "fastclus" "forecast"
+ "gam" "gee" "genmod" "glimmix" "glm" "glmmod" "glmpower" "glmselect"
+ "hpmixed"
+ "inbreed"
+ "kde" "krige2d"
+ "lattice" "lifereg" "lifetest" "loess" "logistic"
+ "mcmc" "mdc" "mds" "mi" "mianalyze" "mixed" "modeclus" "model" "mortgage" "multtest"
+ "nested" "nlin" "nlmixed" "npar1way"
+ "orthoreg"
+ "panel" "pdlreg" "phreg" "plan" "plm" "pls" "power" "princomp" "prinqual" "probit"
+ "qlim" "quantreg"
+ "reg" "risk" "robustreg" "rsreg"
+ "score" "seqdesign" "seqtest" "severity" "sim2d" "similarity" "simlin" "simnormal"
+ "spectra" "statespace" "stdize" "stepdisc"
+ "surveyfreq" "surveylogistic" "surveymeans" "surveyphreg" "surveyreg" "surveyselect" "syslin"
+ "tcalis" "timeid" "timeseries" "tphreg" "tpspline" "transreg" "tree" "ttest"
+ "ucm"
+ "varclus" "varcomp" "variogram" "varmax"
+ "x11" "x12"
+ ) 'words)) font-lock-constant-face)
+
+ ; (cons (concat
+ ; "\\<"
+ ; "do[ \t]*" (regexp-opt '("over" "until" "while") t) "?"
+ ; "\\>")
+ ; 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 "\\<call[ \t]+[a-z]+(" font-lock-function-name-face)
+
+ (cons (concat ;"\\<"
+ (regexp-opt
+ '(
+ "abs" "arcos" "arsin" "atan"
+ "betainv" "byte"
+ "call execute" "call label" "call module" "call modulei"
+ "call poke" "call ranbin" "call rancau" "call ranexp"
+ "call rangam" "call rannor" "call ranpoi" "call rantbl"
+ "call rantri" "call ranuni" "call rxchange" "call rxfree"
+ "call rxsubstr" "call set" "call streaminit" "call symput" "call system"
+ "cdf" "ceil" "cinv" "collate" "compress" "convx" "convxp" "cos" "cosh" "css" "cv"
+ "daccdb" "daccdbsl" "daccsl" "daccsyd" "dacctab"
+ "depdb" "depdbsl" "depsl" "depsyd" "deptab"
+ "date" "datejul" "datepart" "datetime" "day" "dhms" "dif" "digamma" "dim"
+ "erf" "erfc" "exp"
+ "finv" "fipname" "fipnamel" "fipstate" "floor" "fuzz"
+ "gaminv" "gamma"
+ "hbound" "hms" "hour"
+ "in" "index" "indexc" "input" "int" "intck" "intnx" "intrr" "irr"
+ "juldate"
+ "kurtosis"
+ "lag" "lbound" "left" "length" "lgamma" "log" "log10" "log2"
+ "logcdf" "logpdf" "logsdf"
+ "max" "mdy" "mean" "min" "minute" "mod" "month" "mort"
+ "n" "netpv" "nmiss" "normal" "npv"
+ "ordinal"
+ "pdf"
+ "probbeta" "probbnml" "probchi" "probf" "probgam" "probhypr" "probit" "probnegb" "probnorm" "probt"
+ "poisson" "put"
+ "qtr" "quantile"
+ "rand" "range" "rank" "repeat" "reverse" "right" "round" "rxmatch" "rxparse"
+ "ranbin" "rancau" "ranexp" "rangam" "rannor" "ranpoi" "rantbl" "rantri" "ranuni"
+ "saving" "scan" "sdf" "second" "sign" "sin" "sinh" "sqrt" "squantile"
+ "std" "stderr" "stfips" "stname" "stnamel" "substr" "sum" "symget"
+ "tan" "tanh" "time" "timepart" "tinv" "today" "translate" "trigamma" "trim" "trunc"
+ "uniform" "until" "upcase" "uss"
+ "var" "verify"
+ "weekday" "when" "while"
+ "year" "yyq"
+ "zipfips" "zipname" "zipnamel" "zipstate"
+
+;;; ;; SAS/IML functions
+ "all" "allcomb" "allperm" "any" "apply" "armasim"
+ "bin" "blankstr" "block" "branks" "bspline" "btran" "byte"
+ "char" "choose" "col" "colvec" "concat" "contents" "convexit" "corr" "corr2cov"
+ "countmiss" "countn" "countunique" "cov" "cov2corr" "covlag" "cshape" "cusum"
+ "cuprod" "cv" "cvexhull"
+ "datasets" "design" "designf" "det" "diag" "dimension" "distance" "do" "duration"
+ "echelon" "eigval" "eigvec" "expmatrix" "expandgrid"
+ "fft" "fftc" "forward" "froot" "full"
+ "gasetup" "geomean" "ginv"
+ "hadamard" "half" "hankel" "harmean" "hdir" "hermite" "homogen"
+ "i" "ifft" "ifftc" "importtablefromr" "insert" "inv" "invupdt" "isempty" "isskipped"
+ "j" "jroot"
+ "kurtosis"
+ "lambertw" "listgetallnames" "listgetitem" "listgetname" "listgetsubitem" "listindex"
+ "listlen" "loc" "logabsdet"
+ "mad" "magic" "mahalanobis" "moduleic" "modulein"
+ "name" "ncol" "nrow" "ndx2sub" "nleng" "norm" "num"
+ "opscal" "orpol"
+ "parentname" "palette" "polyroot" "prod" "product" "pv"
+ "quartile"
+ "rancomb" "randdirichlet" "randfun" "randmultinomial" "randmvt" "randnormal" "randwishart"
+ "ranperk" "ranperm" "ranktie" "rates" "ratio" "remove" "repeat" "root" "row"
+ "rowcat" "rowcatc" "rowvec" "rsubstr"
+ "sample" "setdif" "shape" "shapecol" "skewness" "solve" "sparse" "splinev" "spot"
+ "sqrsym" "sqrvech" "ssq" "standard" "storage" "sub2ndx" "sweep" "symsqr"
+ "t" "tablecreate" "tablecreatefromdataset" "tablegetvardata" "tablegetvarformat"
+ "tablegetvarindex" "tablegetvarinformat" "tablegetvarlabel" "tablegetvarname"
+ "tablegetvartype" "tableisexistingvar" "tableisvarnumeric" "tfhilbert" "tfpwv"
+ "tfstft" "tfwindow" "toeplitz" "trace" "trisolv" "type"
+ "union" "unique" "uniqueby"
+ "value" "vecdiag" "vech"
+ "xmult" "xsect"
+ "yield"
+
+;;; ;; SAS functions introduced in Technical Report P-222
+ "airy"
+ "band" "blshift" "brshift" "bnot" "bor" "bxor"
+ "cnonct" "compbl"
+ "dairy" "dequote"
+ "fnonct"
+ "ibessel" "indexw" "inputc" "inputn"
+ "jbessel"
+ "lowcase"
+ "putc" "putn"
+ "quote"
+ "resolve"
+ "soundex" "sysprod"
+ "tnonct" "tranwrd" "trimn"
+
+;;; ;; SCL functions that are known to work with SAS macro function %sysfunc
+ "attrc" "attrn"
+ "cexist" "close"
+ "dclose" "dnum" "dopen" "dread"
+ "exist"
+ "fclose" "fetchobs" "fileexist" "finfo" "fopen" "fput" "fwrite"
+ "getoption" "getvarc" "getvarn"
+ "libname" "libref"
+ "open" "optgetn" "optsetn"
+ "pathname"
+ "sysmsg"
+ "varfmt" "varlabel" "varnum" "vartype"
+ ) 'words) ;"\\>"
+ "("); "[ \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 "\\<call[ \t]+[a-z_][a-z_0-9]*[ \t]*("
+ font-lock-function-name-face)
+
+ (cons (concat
+ "\\<"
+ "\\(a\\(bs\\|r\\(cos\\|sin\\)\\|tan\\)\\|b\\(etainv\\|yte\\)"
+ "\\|c\\(eil\\|inv\\|o\\(llate\\|mpress\\|sh?\\)\\|ss\\|v\\)"
+ "\\|dacc\\(db\\(\\|sl\\)\\|s\\(l\\|yd\\)\\|tab\\)"
+ "\\|dep\\(db\\(\\|sl\\)\\|s\\(l\\|yd\\)\\|tab\\)"
+ "\\|d\\(a\\(te\\(\\|jul\\|part\\|time\\)\\|y\\)\\|hms\\|i\\(f[0-9]*\\|m\\|gamma\\)\\)"
+ "\\|e\\(rfc?\\|xp\\)"
+ "\\|f\\(i\\(nv\\|p\\(namel?\\|state\\)\\)\\|loor\\|uzz\\)\\|gam\\(inv\\|ma\\)"
+ "\\|h\\(bound\\|ms\\|our\\)\\|i\\(n\\(dexc?\\|put\\|t\\(\\|ck\\|nx\\|rr\\)\\)\\|rr\\)"
+ "\\|juldate\\|kurtosis\\|l\\(ag[0-9]*\\|bound\\|e\\(ft\\|ngth\\)\\|gamma\\|og\\(\\|10\\|2\\)\\)"
+ "\\|m\\(ax\\|dy\\|ean\\|in\\(\\|ute\\)\\|o\\(d\\|nth\\|rt\\)\\)"
+ "\\|n\\(\\|etpv\\|miss\\|o\\(rmal\\|t\\)\\|pv\\)"
+ "\\|prob\\([ft]\\|b\\(eta\\|nml\\)\\|chi\\|gam\\|hypr\\|it\\|n\\(egb\\|orm\\)\\)"
+ "\\|ordinal\\|p\\(oisson\\|ut\\)\\|qtr\\|r\\(e\\(peat\\|verse\\)\\|ight\\|ound\\)"
+ "\\|ran\\(bin\\|cau\\|exp\\|g\\(am\\|e\\)\\|k\\|nor\\|poi\\|t\\(bl\\|ri\\)\\|uni\\)"
+ "\\|s\\(aving\\|can\\|econd\\|i\\(gn\\|nh?\\)\\|qrt\\|t\\(d\\(\\|err\\)\\|fips\\|namel?\\)\\|u\\(bstr\\|m\\)\\|ymget\\)"
+ "\\|t\\(anh?\\|i\\(me\\(\\|part\\)\\|nv\\)\\|oday\\|r\\(anslate\\|i\\(gamma\\|m\\)\\|unc\\)\\)"
+ "\\|u\\(niform\\|pcase\\|ss\\)\\|v\\(ar\\|erify\\)"
+ "\\|weekday\\|y\\(ear\\|yq\\)\\|zip\\(fips\\|namel?\\|state\\)"
+
+;;; ;; SAS functions introduced in Technical Report P-222
+
+ "\\|airy\\|b\\(and\\|lshift\\|not\\|or\\|rshift\\|xor\\)"
+ "\\|c\\(nonct\\|ompbl\\)\\|d\\(airy\\|equote\\)\\|fnonct\\|tnonct"
+ "\\|i\\(bessel\\|n\\(dexw\\|put[cn]\\)\\)\\|jbessel\\|put[cn]"
+ "\\|lowcase\\|quote\\|resolve\\|s\\(oundex\\|ysprod\\)\\|tr\\(anwrd\\|imn\\)"
+
+;;; ;; IML functions that are not also Datastep functions
+ "\\|a\\(ll\\|ny\\|pply\\|rmasim\\)\\|b\\(lock\\|ranks\\|tran\\)"
+ "\\|c\\(har\\|hoose\\|on\\(cat\\|tents\\|vexit\\|vmod\\)\\|ovlag\\|shape\\|usum\\|vexhull\\)"
+ "\\|d\\(atasets\\|esignf?\\|et\\|iag\\|o\\|uration\\)"
+ "\\|e\\(chelon\\|igv\\(al\\|ec\\)\\)\\|f\\(ft\\|orward\\)\\|ginv"
+ "\\|h\\(alf\\|ankel\\|dir\\|ermite\\|omogen\\)"
+ "\\|i\\(\\|fft\\|nsert\\|nv\\(updt\\)?\\)\\|j\\(\\|root\\)\\|loc\\|mad"
+ "\\|n\\(ame\\|col\\|leng\\|row\\|um\\)\\|o\\(pscal\\|rpol\\)"
+ "\\|p\\(olyroot\\|roduct\\|v\\)\\|r\\(anktie\\|ates\\|atio\\|emove\\|eturn\\|oot\\|owcatc?\\)"
+ "\\|s\\(etdif\\|hape\\|olve\\|plinev\\|pot\\|qrsym\\|ssq\\|torage\\|weep\\|ymsqr\\)"
+ "\\|t\\(\\|eigv\\(al\\|ec\\)\\|oeplitz\\|race\\|risolv\\|ype\\)"
+ "\\|uni\\(on\\|que\\)\\|v\\(alue\\|ecdiag\\)\\|x\\(mult\\|sect\\)\\|yield"
+
+;;; ;; SCL functions that are known to work with SAS macro function %sysfunc
+
+ "\\|attr[cn]\\|c\\(exist\\|lose\\)\\|d\\(close\\|num\\|open\\|read\\)"
+ "\\|exist\\|f\\(close\\|etchobs\\|i\\(leexist\\|nfo\\)\\|open\\|put\\|write\\)"
+ "\\|get\\(option\\|var[cn]\\)\\|lib\\(name\\|ref\\)\\|op\\(en\\|t\\(getn\\|setn\\)\\)"
+ "\\|pathname\\|sysmsg\\|var\\(fmt\\|l\\(abel\\|en\\)\\|n\\(ame\\|um\\)\\|type\\)\\)"
+ "[ \t]*(") font-lock-function-name-face)
+ ))
+ "Font Lock regexs for SAS.")
+
+
+(defvar SAS-editing-alist
+ '((sentence-end . ";[\t\n */]*")
+ (paragraph-start . "^[ \t]*$")
+ (paragraph-separate . "^[ \t]*$")
+ (paragraph-ignore-fill-prefix . t)
+ ;;(fill-paragraph-function . 'lisp-fill-paragraph)
+ (adaptive-fill-mode . nil)
+ (indent-line-function . 'sas-indent-line)
+ ;;(indent-region-function . 'sas-indent-region)
+ (require-final-newline . mode-require-final-newline)
+ (comment-start . "/*")
+ (comment-start-skip . "/[*]")
+ (comment-end . "*/")
+ (comment-end-skip . "[*]/")
+ (comment-column . 40)
+ ;;(comment-indent-function . 'lisp-comment-indent)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style)
+ (ess-local-process-name . nil)
+ ;;(ess-keep-dump-files . 'ask)
+ (tab-stop-list . ess-sas-tab-stop-list)
+ (ess-mode-syntax-table . SAS-syntax-table)
+ (font-lock-keywords-case-fold-search . t)
+ (font-lock-defaults . '(SAS-mode-font-lock-defaults)))
+ "General options for editing SAS source files.")
+
+
+(defun beginning-of-sas-statement (arg &optional comment-start)
+ "Move point to beginning of current sas statement."
+ (interactive "P")
+ (let ((pos (point))
+ )
+ (if (search-forward ";" nil 1) (forward-char -1))
+ (re-search-backward ";[ \n*/]*$" (point-min) 1 arg)
+ (skip-chars-forward sas-comment-chars)
+ (if comment-start nil
+ (if (looking-at "\\*/")
+ (progn (forward-char 2)
+ (skip-chars-forward sas-comment-chars)))
+ (while (looking-at "/\\*")
+ (if (not (search-forward "*/" pos t 1)) ;;(;; (point-max) 1 1)
+ (forward-char 2))
+ (skip-chars-forward sas-white-chars)))))
+
+(defun sas-indent-line ()
+ "Indent function for SAS mode."
+ (interactive)
+ (let (indent prev-end
+ (pos (- (point-max) (point)))
+ (case-fold-search t)
+ (cur-ind (current-indentation))
+ (comment-col (sas-comment-start-col))) ;; 2/1/95 TDC
+ (save-excursion
+ (cond ((progn
+ (back-to-indentation)
+ (or (bobp)
+ (looking-at
+ "data[ ;]\\|proc[ ;]\\|run[ ;]\\|quit[ ;]\\|endsas[ ;]\\|g?options[ ;]\\|%macro[ ;]\\|%mend[ ;]")))
+ ;; Case where current statement is DATA, PROC, etc...
+ (setq prev-end (point))
+ (goto-char (point-min))
+ ;; Added 6/27/94
+ ;; May get fooled if %MACRO, %DO, etc embedded in comments
+ (setq indent
+ (+ (* (- (sas-how-many "^[ \t]*%macro\\|[ \t]+%do"
+ prev-end)
+ (sas-how-many "^[ \t]*%mend\\|%end" prev-end))
+ sas-indent-width) comment-col))) ;; 2/1/95 TDC
+ ;; Case where current line begins with sas-indent-ignore-comment
+ ;; added 6/27/94 to leave "* ;" comments alone.
+ ((progn
+ (back-to-indentation)
+ (and (not (looking-at "*/"))
+ (looking-at (concat sas-indent-ignore-comment "\\|/\\*"))))
+ (setq indent (current-indentation)))
+ ;; Case where current statement not DATA, PROC etc...
+ (t (beginning-of-line 1)
+ (skip-chars-backward sas-white-chars)
+ (if (bobp) nil
+ (backward-char 1))
+ (cond
+ ((looking-at ";") ; modified 1/31/95
+ (setq indent (sas-next-statement-indentation)))
+ ((save-excursion;; added 4/28/94 to properly check
+ (if (bobp) () (backward-char 1));; for end of comment
+ (setq prev-end (point))
+ (looking-at "\\*/"));; improved 1/31/95
+ (save-excursion
+ (search-backward "*/"
+ (point-min) 1 1); comment start is first /*
+ (search-forward "/*"
+ prev-end 1 1) ; after previous */
+ (backward-char 2) ; 2/1/95 TDC
+ (skip-chars-backward sas-white-chars)
+ (setq indent
+ (if (bobp) 0
+ (if (looking-at ";")
+ (sas-next-statement-indentation)
+ ;;(+ (current-indentation) sas-indent-width)
+ (current-indentation))))))
+
+ ;; added 6/27/94 to leave "* ;" comments alone
+ ((save-excursion
+ (progn
+ (beginning-of-sas-statement 1 t)
+ (and (not (looking-at "*/"))
+ (looking-at sas-indent-ignore-comment))))
+ (setq indent cur-ind))
+ ((progn
+ (beginning-of-sas-statement 1)
+ (bobp));; added 4/13/94
+ (setq indent sas-indent-width));; so the first line works
+ ((save-excursion
+ (beginning-of-sas-statement 2)
+ (looking-at "cards4?;\\|datalines4?;\\|lines4?;"))
+ (setq indent (current-indentation))) ; So cards keep indentation.
+ (t
+ (if (progn
+ (save-excursion
+ (beginning-of-line 1)
+ (skip-chars-backward sas-white-chars)
+ (if (bobp) nil (backward-char 1))
+ (or (looking-at ";")
+ (bobp) (backward-char 1) (looking-at "\\*/"))))
+ (setq indent (+ (current-indentation) sas-indent-width))
+ (setq indent (current-indentation))))))))
+ (save-excursion
+ (let (beg end)
+ (back-to-indentation)
+ (setq end (point))
+ (beginning-of-line 1)
+ (setq beg (point))
+ (delete-region beg end)
+ (indent-to indent)))
+ (if (> (- (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
+;;; cookNOSPAMbiostat.wisc.edu
+;; Created: 8/11/94
+\f
+;; variables section
+(defvar sas-dir-mode-map nil)
+(defvar sas-directory-name nil
+ "Name of directory associated with this buffer.")
+(make-variable-buffer-local 'sas-directory-name)
+(defvar sas-dir-buf-end nil)
+(make-variable-buffer-local 'sas-dir-buf-end)
+(defvar sas-sorted-by-num nil)
+(make-variable-buffer-local 'sas-sorted-by-num)
+;; user variables
+\f
+;; 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))
+ )
+
+ ;(require 'sas)
+
+(defun sas-dir-mode ()
+ "Major mode for managing sas files."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map sas-dir-mode-map)
+ (setq major-mode 'sas-dir-mode)
+ (setq mode-name "SAS")
+ (setq sas-directory-name (expand-file-name default-directory))
+ (setq buffer-read-only 1))
+
+
+;;(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
--- /dev/null
+;;; ess-site.el --- user customization of ESS
+
+;; 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 <D.M.SmithNOSPAMlancaster.ac.uk>
+;; Created: 12 Nov 1993
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+;; 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:
+
+;; This file defines all the site-specific customizations for ESS. It should be
+;; edited on a per-site basis. Read the comments (1.1 in Section 1 to see if
+;; ess-site.el must be edited. The final directory location of this file must be
+;; supplied in ess-lisp-directory. The editing of remaining sections is
+;; optional. It should then be byte-compiled, and 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)
+
+;;; Code:
+
+;;;; Load path, autoloads, and major modes
+;;;; ========================================
+;;
+;; 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: (setq ess-show-load-messages t); instead of nil above
+
+;; This sets `ess-lisp-directory' either from the current directory
+;; when the file is being `load'ed, or from the installed location
+;; otherwise. This way, users can load ESS without having added ESS to
+;; `load-path'.
+(defvar ess-lisp-directory
+ ;; A nice default
+ (directory-file-name
+ (file-name-directory
+ (if load-file-name
+ (file-truename load-file-name)
+ (locate-library "ess-site") )))
+ "Directory containing ess-site.el(c) and other ESS Lisp files.")
+
+(defvar ess-etc-directory nil
+ "Location of the ESS etc/ directory.
+The ESS etc directory stores various auxillary files that are useful
+for ESS, such as icons.")
+
+
+;; 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
+(add-to-list 'load-path (file-name-as-directory ess-lisp-directory))
+;; Add ess-lisp-directory/obsolete to load-path; files here will
+;; automatically warn that they are obsolete when loaded.
+(add-to-list 'load-path (file-name-as-directory (expand-file-name "obsolete" ess-lisp-directory)))
+
+(require 'ess-utils)
+(ess-write-to-dribble-buffer
+ (format "[ess-site:] ess-lisp-directory = '%s'" ess-lisp-directory))
+
+
+;; If ess.info is not found, then ess-lisp-directory/../doc/info is added
+;; resurrecting Stephen's version with a bug-fix
+(unless (locate-file "ess.info" Info-default-directory-list)
+ (add-to-list 'Info-default-directory-list (expand-file-name "../doc/info/" ess-lisp-directory)))
+
+
+;;; Loading popular dialects (they should become optional in the future)
+
+;; R and Julia
+(require 'ess-r-mode)
+
+(when (require 'julia-mode nil 'no-error)
+ (require 'ess-julia))
+
+;; S-PLUS (MathSoft/StatSci/Insightful/TIBCO)
+(require 'ess-sp3-d)
+(if ess-microsoft-p
+ (require 'ess-sp6w-d)
+ (require 'ess-sp6-d))
+
+;; S-elsewhere, on another machine by telnet
+(require 'essd-els)
+
+;; Stata, SAS, BUGS, and JAGS
+(require 'ess-stata-mode)
+(require 'ess-sas-d)
+(require 'ess-bugs-d)
+(require 'ess-jags-d)
+
+(ess-write-to-dribble-buffer
+ (format "[ess-site.el]: ess-customize-alist=%s \n"
+ ess-customize-alist))
+
+;;; Literate Data Analysis
+(require 'ess-noweb)
+(require 'ess-swv)
+
+(ess-write-to-dribble-buffer
+ (format "[ess-site.el _2_]: ess-customize-alist=%s \n"
+ ess-customize-alist))
+
+;;; Speedbar and mouse
+(require 'ess-mouse)
+
+;;; Toolbar support
+(require 'ess-toolbar)
+
+(ess-write-to-dribble-buffer "[ess-site:] *very* end ...")
+
+
+(provide 'ess-site)
+
+;;; ess-site.el ends here
--- /dev/null
+;;; ess-sp3-d.el --- S-PLUS 3.x customization
+
+;; Copyright (C) 1997--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMu.washington.edu>
+;; Created: 12 Jun 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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-s-lang)
+(require 'ess-trns)
+
+(defvar S+3-dialect-name "S+3"
+ "Name of 'dialect' for S-PLUS 3.x.");easily changeable in a user's .emacs
+
+(defvar S+3-customize-alist
+ (append
+ '((ess-local-customize-alist . 'S+3-customize-alist)
+ (ess-dialect . S+3-dialect-name)
+ (ess-object-name-db-file . "ess-s+3-namedb.el" )
+ (inferior-ess-program . inferior-S+3-program)
+ (inferior-ess-help-command . "help(\"%s\", pager=\"cat\", window=FALSE)\n")
+ (inferior-ess-help-filetype . nil)
+ (inferior-ess-search-list-command . "search()\n")
+ (inferior-ess-start-file . nil) ;"~/.ess-S+3")
+ (inferior-ess-start-args . "")
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist)
+
+ "Variables to customize for S+3.")
+
+
+(defun S+3 (&optional proc-name)
+ "Call 'S-PLUS 3.x', the 'Real Thing' from StatSci."
+ (interactive)
+ (setq ess-customize-alist S+3-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+3): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer)))
+ (inferior-ess)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start)))
+
+(defun S+3-mode (&optional proc-name)
+ "Major mode for editing S+3 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S+3-customize-alist)
+ (ess-mode S+3-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+(defun S+3-transcript-mode ()
+ "S-PLUS 3.x transcript mode."
+ (interactive)
+ (ess-transcript-mode S+3-customize-alist))
+
+
+
+\f ; Provide package
+
+(provide 'ess-sp3-d)
+
+;;; ess-sp3-d.el ends here
--- /dev/null
+;;; ess-sp4-d.el --- S-PLUS 4.x customization
+
+;; Copyright (C) 1998--2002 Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Copyright (C) 2003--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Created: December 1998
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 4.x customizations for ess-mode
+;; with ddeclient.
+
+;;; Code:
+
+;;; Requires and Autoloads:
+
+(require 'ess-mode)
+(require 'ess-inf)
+(require 'ess-s-lang)
+(require 'ess-dde)
+(require 'ess-trns)
+
+(defvar ess-S+-startup-delay)
+
+(defvar S+4-dialect-name "S+4"
+ "Name of 'dialect' for S-PLUS 4.x.");easily changeable in a user's .emacs
+
+(defvar inferior-S+4-multipleinstances "/MULTIPLEINSTANCES"
+ "Default \"/MULTIPLEINSTANCES\" opens up a new instance of S+4 in a
+GUI window and connects it to the '(ddeESS [S+4])' window. The
+alternative nil uses an existing S+4 GUI (if there is one) and
+connects it to the '(ddeESS [S+4])' window.")
+
+(defvar S+4-customize-alist
+ (append
+ '((ess-local-customize-alist . 'S+4-customize-alist)
+ (ess-dialect . S+4-dialect-name)
+ (ess-object-name-db-file . "ess-sp4-namedb.el" )
+ (inferior-ess-program . inferior-S+4-program)
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . "chm")
+
+ (ess-send-region-function . #'ess-dde-send-region)
+ (ess-load-file-function . #'ess-dde-load-file)
+ (ess-command-function . #'ess-dde-command)
+ (ess-eval-linewise-function . #'ess-dde-eval-linewise)
+ (ess-dump-object-function . #'ess-dde-dump-object)
+ (ess-read-object-name-function . #'ess-dde-read-object-name)
+ (ess-find-help-file-function . #'ess-dde-find-help-file)
+ (ess-display-help-on-object-function . #'ess-chm-display-help-on-object)
+
+ (inferior-ess-start-file . nil) ;"~/.ess-S+4")
+ (inferior-ess-start-args . (concat
+ inferior-S+4-multipleinstances " "
+ inferior-S+4-print-command
+ " S_PROJ="
+ (directory-file-name default-directory)))
+ ;; (inferior-ess-ddeclient . "ddeclient")
+ ;; (inferior-ess-client-name . "S-PLUS")
+ ;; (inferior-ess-client-command . "SCommand")
+ (ess-STERM . "ddeESS")
+ )
+ S+common-cust-alist)
+
+ "Variables to customize for S+4")
+
+(defvar Sqpe+4-customize-alist
+ (append
+ '((ess-local-customize-alist . 'Sqpe+4-customize-alist)
+ (ess-dialect . S+4-dialect-name)
+ (ess-loop-timeout . 500000 );fixme: dialect specific custom.v
+ (ess-object-name-db-file . "ess-sp4-namedb.el" )
+ (ess-display-help-on-object-function . #'ess-chm-display-help-on-object)
+ (inferior-ess-program . inferior-Sqpe+4-program)
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . "chm")
+ (inferior-ess-search-list-command . "searchPaths()\n")
+ (inferior-ess-start-file . nil) ;"~/.ess-S+4")
+ (inferior-ess-language-start . (concat
+ "options("
+ "STERM='" ess-STERM "'"
+ (if ess-editor
+ (concat ", editor='" ess-editor "'"))
+ (if ess-pager
+ (concat ", pager='" ess-pager "'"))
+ ")"))
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist)
+
+ "Variables to customize for Sqpe+4.")
+
+
+;;; There are extra complications in S+4 (compared to S+3) because
+;;;
+;;; (1) The StatSci supplied Splus.exe doesn't work in an emacs
+;;; buffer. It works as as a GUI window and we must send commands
+;;; to it through ddeclient. Nonetheless, we need to give it a
+;;; process name and be sure that that there is a valid running
+;;; process in the '(ddeESS [S+4])' buffer. Therefore we create an
+;;; ESS process in the buffer as a placeholder and start a shell
+;;; in the ESS buffer. From the shell we start Splus. Once Splus
+;;; finishes initializing and kills the original shell, we start
+;;; another shell. We have a buffer-local variable
+;;; inferior-ess-ddeclient, initialized to nil. When there is a
+;;; non-nil value of inferior-ess-ddeclient we send lines to
+;;; inferior-ess-ddeclient rather than to the Splus process.
+;;; (2) There is no Splus process running in the '(ddeESS [S+4])'
+;;; buffer. Therefore inferior-ess will never see a prompt,
+;;; unless we first change it to the null prompt "^". Then once
+;;; the process has started, we change it back.
+;;; (3) When M-x S+4 starts Splus by a shell command, then Splus is an
+;;; independent process and will be survive if the '(ddeESS [S+4])'
+;;; buffer is killed (or emacs is quit). The '(ddeESS [S+4])' is
+;;; made read-only and a warning is placed in it saying that "You
+;;; can't type anything here." Actually, if the standalone Splus
+;;; is killed and the '(ddeESS [S+4])' is made writable (C-x C-q),
+;;; then '(ddeESS [S+4])' becomes a shell buffer.
+;;;
+(defun S+4 (&optional proc-name)
+ "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Put S-Plus in an
+independent MS-Window (Splus persists even if the '(ddeESS [S+4])'
+window is killed in emacs). Do this by creating a comint process that
+calls sh. Send a shell command in that sh buffer to call Splus. When
+it completes set up a shell as a placeholder in the '(ddeESS [S+4])'
+buffer. The S-Plus options are correctly set. In particular, the
+S-Plus Commands window is opened if the Options/General
+Settings/Startup menu says it should be. There is a 30 second delay
+during startup in which the screen will not be refreshed. This delay
+is here to allow slow disks to start the Splus program."
+ (interactive)
+ (save-excursion
+ (setq ess-customize-alist S+4-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+4): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-program
+ (append ess-customize-alist '((inferior-ess-program . "sh"))))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (setq ess-customize-alist ; change inferior-ess-start-args
+ (append ess-customize-alist '((inferior-ess-start-args . "-i"))))
+ (let ((s-proj (getenv "S_PROJ"))
+ (manpath (getenv "MANPATH")))
+ (if (fboundp 'w32-short-file-name)
+ (cd (w32-short-file-name (directory-file-name default-directory)))
+ (cd (directory-file-name default-directory)))
+ (setenv "S_PROJ" default-directory)
+ ;; I don't know why this PATH/MANPATH game is needed,
+ ;; except that it doesn't work without it.
+ (setenv "MANPATH" (getenv "PATH"))
+ (inferior-ess)
+ (sleep-for 2) ; need to wait, else working too fast! The Splus
+ ; command in '(ddeESS [S+4])' should follow the "$"
+ ; prompt. If not, then increase the sleep-for time!
+ (setenv "MANPATH" manpath)
+ (setenv "S_PROJ" s-proj))
+ (setq ess-customize-alist S+4-customize-alist)
+ (ess-setq-vars-local ess-customize-alist)
+;;; the next three lines belong in customize-alist, but can't be there
+;;; because of the broken ess-setq-vars-default usage in ess-inf.el
+ (setq inferior-ess-ddeclient "ddeclient")
+ (setq inferior-ess-client-name "S-PLUS")
+ (setq inferior-ess-client-command "SCommand")
+;;; end of what belongs in customize-alist
+ (setq comint-process-echoes nil)
+ (setq comint-input-sender 'comint-simple-send)
+ (goto-char (point-max))
+ (insert (concat inferior-S+4-program " "
+ inferior-ess-start-args)) ; Note: there is no final "&".
+ ;; Without the "&", the results of !system.command come to '(ddeESS [S+4])'
+ ;; With the "&", the results of !system.command in S get lost.
+ (inferior-ess-send-input)
+ (sleep-for 30) ; Need to wait, else working too fast!
+ ; If the ess-current-process-name doesn't appear in the
+ ; Splus Commands window increase the sleep-for time!
+ (setq ess-local-process-name ess-current-process-name)
+ (ess-eval-linewise (concat "#" ess-current-process-name))
+ (goto-char (point-min))
+ (insert
+ "This is a placeholder buffer. You can't type anything here.
+Use `C-x b RET' to return to your file.\n
+Anything sent to this process from an S-mode buffer goes
+directly to the associated Splus Commands window.\n
+The S-Plus Commands window must be visible.
+You may need to open the S-Plus Commands window manually (by clicking on
+Splus/Window/Commands Window).\n
+Any results of the !system.command typed at the S prompt in the
+Splus Commands window appear in this buffer.\n\n")
+ (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+4])'
+ ;; (use-local-map comint-mode-map) ;a shell buffer after Splus is finished.
+ (set-process-coding-system (get-process ess-local-process-name) 'raw-text-dos 'raw-text-unix)
+ (setq buffer-read-only t) ; force buffer to be read-only
+ (setq mode-name "ddeESS")
+ ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ ))
+
+
+
+
+(defun S+4-existing (&optional proc-name)
+ "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Do so by finding
+an existing S-Plus in an independent MS-Window (if there is one) and
+set up a '(ddeESS [S+4])' buffer in emacs. If there is no existing
+S-Plus, then a new one will be opened in the default directory,
+usually something like c:/Program Files/spls45se/users/yourname.
+If you have a HOME environment variable, it will open it there."
+ (interactive)
+ (let* ((inferior-S+4-multipleinstances " & # ")) ; Note: there is a final "&".
+ ;; Without the "&", there is a core dump.
+ ;; With the "&", the results of !system.command in S get lost.
+ ;; We are picking up an existing S-Plus process for sending to.
+ ;; It doesn't know about us, so nothing comes back.
+ (S+4 proc-name))
+ (with-current-buffer (car (buffer-list)) ; get the ESS buffer just created
+ (setq buffer-read-only nil) ; permit writing in ESS buffer
+ (goto-char (point-max))
+ (beginning-of-line)
+ (forward-line -1)
+ (insert
+ "This is S+4-existing.
+Results of the !system.command typed at the S prompt in the
+Splus Commands window blink a DOS window and you won't see them.\n\n")
+ (setq buffer-read-only t) ; restore ESS buffer to be read-only
+ ))
+
+
+;;; There are extra complications in Sqpe+4 (compared to S+3) because
+;;; (1) The StatSci supplied Sqpe.exe won't work without SHOME as an
+;;; environment variable and Sqpe does not take command line
+;;; arguments and
+;;; (2) Sqpe.exe comes up with options(interactive=F), which means it
+;;; doesn't provide prompts by default, and we must change it to T so
+;;; it will provide prompts.
+;;;
+(defun Sqpe+4 (&optional proc-name)
+ "Call 'Sqpe' from 'S-PLUS 4.x', the 'Real Thing' from StatSci."
+ (interactive)
+ (setq ess-customize-alist Sqpe+4-customize-alist)
+ (let* ((shome-nil-p (equal (getenv "SHOME") nil)))
+ (if shome-nil-p (setenv "SHOME" inferior-Sqpe+4-SHOME-name))
+ (ess-write-to-dribble-buffer
+ (format "\n(Sqpe+4): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (inferior-ess)
+ (setq ess-customize-alist Sqpe+4-customize-alist) ; restore i-e-p-p in alist
+ (ess-setq-vars-local ess-customize-alist) ; restore i-e-p-p in buffer
+ (setq inferior-ess-prompt ; define with correct i-e-p-p
+ ;; Do not anchor to bol with `^' ; (copied from ess-inf.el)
+ (concat "\\("
+ inferior-ess-primary-prompt
+ "\\|"
+ inferior-ess-secondary-prompt
+ "\\)"))
+ (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
+ ; define with correct i-e-p-p
+ (setq comint-input-sender 'inferior-ess-input-sender)
+ (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
+ (goto-char (point-max))
+ (insert "options(interactive=T)")
+ (inferior-ess-send-input)
+ (setq mode-name "iESS(Sqpe)")
+ ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ (if shome-nil-p (setenv "SHOME" nil))))
+
+
+
+(defun S+4-mode (&optional proc-name)
+ "Major mode for editing S+4 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S+4-customize-alist)
+ (ess-mode S+4-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+(defun S+4-transcript-mode ()
+ "S-PLUS 4.x transcript mode."
+ (interactive)
+ (ess-transcript-mode S+4-customize-alist))
+
+
+(defun S+4-msdos (&optional proc-name)
+ "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Put S-Plus in an
+independent MS-Window (Splus persists even if the '(ddeESS [S+4])'
+window is killed in emacs). Do this by creating a comint process that
+calls sh. Send a shell command in that sh buffer to call Splus. When
+it completes set up a shell as a placeholder in the '(ddeESS [S+4])'
+buffer. The S-Plus options are correctly set. In particular, the
+S-Plus Commands window is opened if the Options/General
+Settings/Startup menu says it should be. There is a 30 second delay
+during startup in which the screen will not be refreshed. This delay
+is here to allow slow disks to start the Splus program."
+ (interactive)
+ (save-excursion
+ (setq ess-customize-alist S+4-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+4): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-program
+ (append ess-customize-alist '((inferior-ess-program
+ . (getenv "COMSPEC")))))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (setq ess-customize-alist ; change inferior-ess-start-args
+ (append ess-customize-alist '((inferior-ess-start-args . ""))))
+ (let ((s-proj (getenv "S_PROJ")))
+ (if (fboundp 'w32-short-file-name)
+ (cd (w32-short-file-name (directory-file-name default-directory)))
+ (cd (directory-file-name default-directory)))
+ (setenv "S_PROJ" default-directory)
+ (inferior-ess)
+ (sleep-for 2) ; need to wait, else working too fast! The Splus
+ ; command in '(ddeESS [S+4])' should follow the "$"
+ ; prompt. If not, then increase the sleep-for time!
+ (setenv "S_PROJ" s-proj))
+ (setq ess-customize-alist S+4-customize-alist)
+ (ess-setq-vars-local ess-customize-alist)
+;;; the next three lines belong in customize-alist, but can't be there
+;;; because of the broken ess-setq-vars-default usage in ess-inf.el
+ (setq inferior-ess-ddeclient "ddeclient")
+ (setq inferior-ess-client-name "S-PLUS")
+ (setq inferior-ess-client-command "SCommand")
+;;; end of what belongs in customize-alist
+ (setq comint-input-sender 'comint-simple-send)
+ (setq comint-process-echoes nil)
+ (set-process-coding-system (get-process ess-local-process-name) 'raw-text-dos 'raw-text-dos)
+ (goto-char (point-max))
+ (insert (concat inferior-S+4-program " "
+ inferior-ess-start-args)) ; Note: there is no final "&".
+ ; Without the "&", the results of !system.command come to '(ddeESS [S+4])'
+ ; With the "&", the results of !system.command in S get lost.
+ (inferior-ess-send-input)
+ (sleep-for 30) ; Need to wait, else working too fast!
+ ; If the ess-current-process-name doesn't appear in the
+ ; Splus Commands window increase the sleep-for time!
+;;; from msdos-minor-mode
+ (setq comint-process-echoes t)
+ (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
+;;; end from msdos-minor-mode
+ (setq ess-local-process-name ess-current-process-name)
+ (ess-eval-linewise (concat "#" ess-current-process-name))
+ (goto-char (point-min))
+ (insert
+ "This is a placeholder buffer. You can't type anything here.
+Use 'C-x b RET' to return to your file.\n
+Anything sent to this process from an S-mode buffer goes
+directly to the associated Splus Commands window.\n
+The S-Plus Commands window must be visible.
+You may need to open the S-Plus Commands window manually
+ (by clicking on Splus/Window/Commands Window).\n There is a 30
+second delay when this program starts during which the emacs
+screen will be partially blank.\n Remember to `q()' from S-Plus
+and then C-x C-q exit from the `'(ddeESS [S+4])'' buffer, or take
+the risk of not being able to shut down your computer and
+suffering through scandisk.\n Any results of the !system.command
+typed at the S prompt in the Splus Commands window (are supposed
+to) appear in this buffer.\n\n")
+ (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+4])'
+ (use-local-map comint-mode-map) ; a shell buffer after Splus is finished.
+ (setq buffer-read-only t) ; force buffer to be read-only
+ (setq mode-name "ddeESS")
+ ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ ))
+
+(defun S+4-msdos-existing (&optional proc-name)
+ "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Do so by finding
+an existing S-Plus in an independent MS-Window (if there is one) and
+set up a '(ddeESS [S+4])' buffer in emacs. If there is no existing
+S-Plus, then a new one will be opened in the default directory,
+usually something like c:/Program Files/spls45se/users/yourname.
+If you have a HOME environment variable, it will open it there."
+ (interactive)
+ (let* ((inferior-S+4-multipleinstances ""))
+ (S+4-msdos proc-name))
+ (with-current-buffer
+ (car (buffer-list)) ; get the ESS buffer just created
+ (setq buffer-read-only nil) ; permit writing in ESS buffer
+ (goto-char (point-max))
+ (beginning-of-line)
+ (forward-line -1)
+ (insert
+ "This is S+4-msdos-existing.
+Results of the !system.command typed at the S prompt in the
+Splus Commands window blink a DOS window and you won't see them.\n\n")
+ (setq buffer-read-only t) ; restore ESS buffer to be read-only
+ ))
+
+\f ; Provide package
+
+(provide 'ess-sp4-d)
+
+;;; ess-sp4-d.el ends here
--- /dev/null
+;;; ess-sp5-d.el --- S-plus 5 customization
+
+;; Copyright (C) 1998 A.J. Rossini
+;; Copyright (C) 1999--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMbiostat.washington.edu>
+;; Created: 9 Nov 1998
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 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-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...
+
+(defvar S+5-dialect-name "S+5"
+ "Name of 'dialect' for S-PLUS 5.");easily changeable in a user's .emacs
+
+(defvar S+5-customize-alist
+ (append
+ '((ess-local-customize-alist . 'S+5-customize-alist)
+ (ess-dialect . S+5-dialect-name)
+ (ess-object-name-db-file . "ess-sp5-namedb.el")
+ (inferior-ess-program . inferior-S+5-program)
+ ;;(inferior-ess-objects-pattern . ".*") ; for new s4 stuff
+ (inferior-ess-help-command . "help(\"%s\", pager=\"slynx -dump\", window=FALSE)\n")
+ (inferior-ess-help-filetype . nil)
+ (inferior-ess-search-list-command . "searchPaths()\n")
+ (inferior-ess-start-args . inferior-S+-start-args)
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist)
+
+ "Variables to customize for S+5.")
+
+
+;; For loading up the S code required for the above.
+;;(add-hook 'ess-post-run-hook
+;; (lambda ()
+;; (ess-command
+;; (concat
+;; "if(exists(\"Sversion\")) library(emacs) else source(\""
+;; ess-mode-run-file
+;; "\")\n"))
+;; (if ess-mode-run-file2
+;; (ess-command
+;; (concat "source(\"" ess-mode-run-file2 "\")\n")))))
+
+
+(defun S+5 (&optional proc-name)
+ "Call 'Splus5', based on S version 4, from Bell Labs.
+New way to do it."
+ (interactive)
+ (setq ess-customize-alist S+5-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+5): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer)))
+ (inferior-ess)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start)))
+
+(defun S+5-mode (&optional proc-name)
+ "Major mode for editing S+5 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S+5-customize-alist)
+ (ess-mode S+5-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+(defun S+5-transcript-mode ()
+ "S-PLUS 5 transcript mode."
+ (interactive)
+ (ess-transcript-mode S+5-customize-alist))
+
+\f ; Provide package
+
+(provide 'ess-sp5-d)
+
+;;; ess-sp5-d.el ends here
--- /dev/null
+;;; 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 <rossiniNOSPAMu.washington.edu>
+;; Created: 2001/02/06
+;; Maintainer: ESS Core Team <ESS-coreNOSPAMr-project.org>
+
+;; 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-dde)
+(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-help-filetype . nil)
+ (inferior-ess-search-list-command . "searchPaths()\n")
+
+ (ess-send-region-function . #'ess-dde-send-region)
+ (ess-load-file-function . #'ess-dde-load-file)
+ (ess-command-function . #'ess-dde-command)
+ (ess-eval-linewise-function . #'ess-dde-eval-linewise)
+ (ess-dump-object-function . #'ess-dde-dump-object)
+ (ess-read-object-name-function . #'ess-dde-read-object-name)
+ (ess-find-help-file-function . #'ess-dde-find-help-file)
+ (ess-display-help-on-object-function . #'ess-dde-display-help-on-object)
+
+ (ess-directory-function . S+-directory-function)
+ (ess-setup-directory-function . S+-setup-directory-function)
+ (inferior-ess-start-args . inferior-S+-start-args)
+ (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)
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+): ess-dialect=%s, buf=%s\n" ess-dialect (current-buffer)))
+ (inferior-ess)
+ (ess-command ess-S+--injected-code)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ (with-ess-process-buffer nil
+ (run-mode-hooks 'ess-S+-post-run-hook)))
+
+
+(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 ess-customize-alist S+-customize-alist)
+ (ess-mode S+-customize-alist proc-name)
+ (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+(defalias 'S+6-transcript-mode 'S+-transcript-mode)
+(defun S+-transcript-mode ()
+ "S-PLUS 6 transcript mode."
+ (interactive)
+ (ess-transcript-mode S+-customize-alist))
+
+(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 `ess-uniq-list'.
+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
+ (ess-uniq-list
+ (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
+(if ess-microsoft-p
+ (nconc
+ (ess-sqpe-versions-create ess-SHOME-versions) ;; 32-bit
+ (ess-sqpe-versions-create ess-SHOME-versions-64 "-64-bit")) ;; 64-bit
+ (ess-s-define-runners))
+(define-obsolete-function-alias
+ 'ess-s-versions-create 'ess-s-define-runners "ESS 18.10")
+
+
+
+\f ; Provide package
+
+(provide 'ess-sp6-d)
+
+;;; ess-sp6-d.el ends here
--- /dev/null
+;;; ess-sp6w-d.el --- S-PLUS 6.x for Windows customization
+
+;;; copied and edited from ess-s4-d.el - Richard M. Heiberger, April 2001
+
+;; Copyright (C) 2001 Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Copyright (C) 2002--2005 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Created: April 2001
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 6.x for Windows customizations
+;; for ess-mode with ddeclient.
+
+;;; Code:
+
+;;; Requires and Autoloads:
+
+(require 'ess-s-lang)
+(require 'ess-trns)
+(defvar ess-S+-startup-delay)
+(defvar version-function-name)
+;;NO: this is autoloaded from other places (require 'ess-dde)
+
+(defvaralias 'inferior-S+6-multipleinstances 'inferior-S+-multipleinstances)
+(defvar inferior-S+-multipleinstances "/MULTIPLEINSTANCES"
+ "Default \"/MULTIPLEINSTANCES\" opens up a new instance of S+[678] in a
+GUI window and connects it to the '(ddeESS [S+])' window. The
+alternative nil uses an existing S+ GUI (if there is one) and
+connects it to the '(ddeESS [S+])' window.")
+
+(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-object-name-db-file . "ess-sp6-namedb.el" )
+ (ess-display-help-on-object-function . #'ess-chm-display-help-on-object)
+ (inferior-ess-program . inferior-S+-program)
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . "chm")
+ (inferior-ess-search-list-command . "searchPaths()\n")
+ (inferior-ess-start-file . nil) ;"~/.ess-S+")
+ (inferior-ess-start-args . (concat
+ inferior-S+-multipleinstances
+ " "
+ inferior-S+-start-args
+ " "
+ inferior-S+-print-command
+ " S_PROJ="
+ (when (fboundp 'w32-short-file-name)
+ (w32-short-file-name
+ (directory-file-name
+ default-directory)))))
+ ;; (inferior-ess-ddeclient . "ddeclient")
+ ;; (inferior-ess-client-name . "S-PLUS")
+ ;; (inferior-ess-client-command . "SCommand")
+ (ess-STERM . "ddeESS")
+ )
+ S+common-cust-alist)
+ "Variables to customize for S+")
+
+(defvaralias 'Sqpe+6-customize-alist 'Sqpe+-customize-alist)
+(defvar Sqpe+-customize-alist
+ (append
+ '((ess-local-customize-alist . 'Sqpe+-customize-alist)
+ (ess-dialect . S+-dialect-name)
+ (ess-loop-timeout . 500000 );fixme: dialect specific custom.var
+ (ess-object-name-db-file . "ess-sp6-namedb.el" )
+ (ess-display-help-on-object-function . #'ess-chm-display-help-on-object)
+ (inferior-ess-program . inferior-Sqpe+-program)
+ (inferior-ess-help-command . "help(\"%s\")\n")
+ (inferior-ess-help-filetype . "chm")
+ (inferior-ess-search-list-command . "searchPaths()\n")
+ (inferior-ess-start-file . nil) ;"~/.ess-S+")
+ (inferior-ess-start-args . (concat
+ ;; workaround for bug in S-Plus 6 for Windows:
+ "ALWAYS_PROMPT=X"
+ " "
+ inferior-Sqpe+-start-args ;; e.g. license manager
+ ))
+ (ess-STERM . "iESS")
+ )
+ S+common-cust-alist)
+ "Variables to customize for Sqpe+.")
+
+
+
+;;; There are extra complications in S+6 and S+7 and S+8 (compared to S+3)
+;;; because
+;;;
+;;; (1) The StatSci supplied Splus.exe doesn't work in an emacs
+;;; buffer. It works as as a GUI window and we must send commands
+;;; to it through ddeclient. Nonetheless, we need to give it a
+;;; process name and be sure that that there is a valid running
+;;; process in the '(ddeESS [S+])' buffer. Therefore we create an
+;;; ESS process in the buffer as a placeholder and start a shell
+;;; in the ESS buffer. From the shell we start Splus. Once Splus
+;;; finishes initializing and kills the original shell, we start
+;;; another shell. We have a buffer-local variable
+;;; inferior-ess-ddeclient, initialized to nil. When there is a
+;;; non-nil value of inferior-ess-ddeclient we send lines to
+;;; inferior-ess-ddeclient rather than to the Splus process.
+;;; (2) There is no Splus process running in the '(ddeESS [S+])'
+;;; buffer. Therefore inferior-ess will never see a prompt,
+;;; unless we first change it to the null prompt "^". Then once
+;;; the process has started, we change it back.
+;;; (3) When M-x S+ starts Splus by a shell command, then Splus is an
+;;; independent process and will be survive if the '(ddeESS [S+])'
+;;; buffer is killed (or emacs is quit). The '(ddeESS [S+])' is
+;;; made read-only and a warning is placed in it saying that "You
+;;; can't type anything here." Actually, if thestandalone Splus
+;;; is killed and the '(ddeESS [S+])' is made writable (C-x C-q),
+;;; then '(ddeESS [S+])' becomes a shell buffer.
+;;;
+(defalias 'S+6 'S+)
+(defun S+ (&optional proc-name)
+ "Verify that `inferior-S+-program' points to S-Plus 6 or
+S-Plus 7 or S-Plus 8. Start normally for S-Plus 6.1 and later.
+Inform the user to start S-Plus 6.0 from the icon and then
+connect to it with `S+-existing'. Give an error message if
+`inferior-S+-program' doesn't point to S-Plus 6 or S-Plus 7
+or S-Plus 8."
+ (interactive)
+ (with-current-buffer (find-file-noselect
+ (concat (executable-find inferior-S+-program)
+ "/../../versions") t)
+ (setq buffer-read-only 1)
+ (forward-line)
+ (if (not (search-backward-regexp "splus\t[678].[0-9]" (point-min) t))
+ (error "The emacs variable `inferior-S+-program' does
+not point to S-Plus 6 or 7 or 8. Please add `splus[678]?/cmd' (expand the
+`[678]?' to match your setup) to your `exec-path' or specify the complete
+path to `Splus.exe' in the variable `inferior-S+-program' in your
+`.emacs' file.")
+ (forward-line)
+ (if (search-backward "splus\t6.0" (point-min) t)
+ (error "S-Plus 6.0 for Microsoft Windows has a bug that
+prevents it from being started by emacs. Instead, you must start it
+by double-clicking an icon. Then you can connect to it with
+`S+-existing'. You should consider upgrading to a newer
+release of S-Plus."))))
+ (S+-initiate proc-name)) ;; normal start ;
+
+(defalias 'S+6-initiate 'S+-initiate)
+(defun S+-initiate (&optional proc-name)
+ "Call 'S-PLUS [678].x for Windows', the 'GUI Thing' from StatSci. Put
+S-Plus in an independent MS-Window (Splus persists even if the
+'(ddeESS [S+])' window is killed in emacs). Do this by creating a
+comint process that calls sh. Send a shell command in that sh buffer
+to call Splus. When it completes set up a shell as a placeholder in
+the '(ddeESS [S+])' buffer. The S-Plus options are correctly set.
+In particular, the S-Plus Commands window is opened if the
+Options/General Settings/Startup menu says it should be. There is a
+startup delay of `ess-S+-startup-delay' seconds during which the
+screen will not be refreshed. This delay is here to allow slow disks
+to start the Splus program."
+ (interactive)
+ (save-excursion
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-program
+ (append ess-customize-alist '((inferior-ess-program . "sh"))))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (setq ess-customize-alist ; change inferior-ess-start-args
+ (append ess-customize-alist '((inferior-ess-start-args . "-i"))))
+ (let ((s-proj (getenv "S_PROJ"))
+ (use-dialog-box (not (or ess-microsoft-p (eq system-type 'cygwin))))
+ )
+ (cd (when (fboundp 'w32-short-file-name)
+ (w32-short-file-name (directory-file-name default-directory))))
+ (setenv "S_PROJ" (when
+ (fboundp 'w32-short-file-name)
+ (w32-short-file-name default-directory)))
+ (inferior-ess)
+ (sleep-for 2) ; need to wait, else working too fast! The Splus
+ ; command in '(ddeESS [S+])' should follow the "$"
+ ; prompt. If not, then increase the sleep-for time!
+ (setenv "S_PROJ" s-proj))
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-setq-vars-local ess-customize-alist)
+;;; the next three lines belong in customize-alist, but can't be there
+;;; because of the broken ess-setq-vars-default usage in ess-inf.el
+ (setq inferior-ess-ddeclient "ddeclient")
+ (setq inferior-ess-client-name "S-PLUS")
+ (setq inferior-ess-client-command "SCommand")
+;;; end of what belongs in customize-alist
+ (setq comint-process-echoes nil)
+ (setq comint-input-sender 'comint-simple-send)
+ (goto-char (point-max))
+ (insert (concat inferior-S+-program " "
+ inferior-ess-start-args)) ; Note: there is no final "&".
+ ;; Without the "&", the results of !system.command come to '(ddeESS [S+])'
+ ;; With the "&", the results of !system.command in S get lost.
+ (inferior-ess-send-input)
+ (sleep-for ess-S+-startup-delay) ; Need to wait, else working too fast!
+ ; If the ess-current-process-name doesn't appear in the
+ ; Splus Commands window increase the sleep-for time!
+ (setq ess-local-process-name ess-current-process-name)
+ (ess-eval-linewise (concat "#" ess-current-process-name))
+ (goto-char (point-min))
+ (insert
+ "This is a placeholder buffer. You can't type anything here.
+Use `C-x b RET' to return to your file.\n
+Anything sent to this process from an S-mode buffer goes
+directly to the associated Splus Commands window.\n
+The S-Plus Commands window must be visible.
+You may need to open the S-Plus Commands window manually (by clicking on
+Splus/Window/Commands Window).\n
+Any results of the !system.command typed at the S prompt in the
+Splus Commands window appear in this buffer.\n\n")
+ (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+])'
+ ;; (use-local-map comint-mode-map) ;a shell buffer after Splus is finished.
+ (set-process-coding-system (get-buffer-process (current-buffer))
+ 'raw-text-dos 'raw-text-unix)
+ (setq buffer-read-only t) ; force buffer to be read-only
+ (setq mode-name "ddeESS")
+ ;; (ess-eval-linewise inferior-S+-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ ))
+
+
+(defalias 'S+6-existing 'S+-existing)
+(defun S+-existing (&optional proc-name)
+ "Call 'S-PLUS [678].x for Windows', the 'GUI Thing' from StatSci. Do so by
+finding an existing S-Plus in an independent MS-Window (if there is one) and
+set up a '(ddeESS [S+])' buffer in emacs. If there is no existing
+S-Plus, then a new one will be opened in the default directory. The default
+is usually something like 'c:/Program Files/Insightful/splus70/users/yourname'
+for S-Plus before 8.0.4. Beginning with 8.0.4, S-Plus uses the default directory
+'c:/Documents and Settings/yourname/My Documents/S-PLUS Projects/Project1'.
+Beginning with TIBCO Spotfire S+ Version 8.1.1 for Microsft Windows, the default
+directory is 'c:/DOCUME~1/yourname/MYDOCU~1/SPOTFI~1/Project1'.
+If you have a HOME environment variable, it will open it there."
+ (interactive)
+ (let* ((inferior-S+-multipleinstances " & # ") ; Note: there is a final "&".
+ (ess-S+-startup-delay 0)) ;; No delay for existing S-Plus
+ ;; Without the "&", there is a core dump.
+ ;; With the "&", the results of !system.command in S get lost.
+ ;; We are picking up an existing S-Plus process for sending to.
+ ;; It doesn't know about us, so nothing comes back.
+ (S+-initiate proc-name))
+ (with-current-buffer (car (buffer-list)) ; get the ESS buffer just created
+ (setq buffer-read-only nil) ; permit writing in ESS buffer
+ (goto-char (point-max))
+ (beginning-of-line)
+ (forward-line -1)
+ (insert
+ "This is S+-existing.
+Results of the !system.command typed at the S prompt in the
+Splus Commands window blink a DOS window and you won't see them.\n\n")
+ (setq buffer-read-only t) ; restore ESS buffer to be read-only
+ ))
+
+
+;;; There are extra complications in Sqpe+6 (compared to S+3) because
+;;; (1) The StatSci supplied Sqpe.exe won't work without SHOME as an
+;;; environment variable and Sqpe does not take command line
+;;; arguments and
+;;; (2) Sqpe.exe comes up with options(interactive=FALSE), which means it
+;;; doesn't provide prompts by default, and we must change it to T so
+;;; it will provide prompts.
+;;;
+(defalias 'Sqpe+6 'Sqpe+)
+(defun Sqpe+ (&optional proc-name)
+ "Call 'Sqpe' from 'S-PLUS [678].x for Windows', the 'Real Thing' from StatSci."
+ (interactive)
+ (setq ess-customize-alist Sqpe+-customize-alist)
+ (let* ((shome-nil-p (equal (getenv "SHOME") nil))
+ (use-dialog-box (not (or ess-microsoft-p (eq system-type 'cygwin))))
+ )
+ (if shome-nil-p (setenv "SHOME" inferior-Sqpe+-SHOME-name))
+ (ess-write-to-dribble-buffer
+ (format "\n(Sqpe+6): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (inferior-ess)
+ (setq ess-customize-alist Sqpe+-customize-alist) ; restore i-e-p-p in alist
+ (ess-setq-vars-local ess-customize-alist) ; restore i-e-p-p in buffer
+ (setq inferior-ess-prompt ; define with correct i-e-p-p
+ ;; Do not anchor to bol with `^' ; (copied from ess-inf.el)
+ (concat "\\("
+ inferior-ess-primary-prompt
+ "\\|"
+ inferior-ess-secondary-prompt
+ "\\)"))
+ (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
+ ; define with correct i-e-p-p
+ (setq comint-input-sender 'inferior-ess-input-sender)
+ (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
+ (goto-char (point-max))
+ (insert "options(interactive=TRUE)")
+ (inferior-ess-send-input)
+ (setq mode-name "iESS(Sqpe)")
+ ;; (ess-eval-linewise inferior-S+-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ (if shome-nil-p (setenv "SHOME" nil))))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.sp\\'" . S-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.[qsS]\\'" . S-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.ssc\\'" . S-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.SSC\\'" . S-mode))
+
+(defalias 'S+6-mode 'S+-mode)
+(defun S+-mode (&optional proc-name)
+ "Major mode for editing S+[678] source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-mode S+-customize-alist proc-name)
+ (if ess-imenu-use-S (ess-imenu-S)))
+
+(defalias 'S+6-transcript-mode 'S+-transcript-mode)
+(defun S+-transcript-mode ()
+ "S-PLUS transcript mode."
+ (interactive)
+ (ess-transcript-mode S+-customize-alist))
+
+(defun S+-msdos (&optional proc-name)
+ "Verify that `inferior-S+-program' points to S-Plus 6 or
+S-Plus 7 or S-Plus 8. Start normally for S-Plus 6.1 and later.
+Inform the user to start S-Plus 6.0 from the icon and then
+connect to it with `S+-msdos-existing'. Give an error message
+if `inferior-S+-program' doesn't point to S-Plus 6 or
+S-Plus 7 or S-Plus 8."
+ (interactive)
+ (with-current-buffer (find-file-noselect
+ (concat (executable-find inferior-S+-program)
+ "/../../versions") t)
+ (setq buffer-read-only 1)
+ (forward-line)
+ (if (not (search-backward-regexp "splus\t[678].[0-9]" (point-min) t))
+ (error "The emacs variable `inferior-S+-program' does
+ not point to S-Plus 6 or 7 or 8. Please add `splus[678]?/cmd'
+ (expand the `[678]?' to match your setup) to your `exec-path' or
+ specify the complete path to `Splus.exe' in the variable
+`inferior-S+-program' in your `.emacs' file.") ;;; " This comment keeps emacs font-lock from getting out of phase.
+
+ (progn
+ (forward-line)
+ (if (search-backward "splus\t6.0" (point-min) t)
+ (error "S-Plus 6.0 for Microsoft Windows has a bug that
+prevents it from being started by emacs. Instead, you must start it
+by double-clicking an icon. Then you can connect to it with
+`S+-msdos-existing'. You should consider upgrading to a newer
+release of S-Plus.")
+ (S+-msdos-initiate proc-name))) ;; normal start ;
+ )))
+
+(defalias 'S+6-msdos-initiate 'S+-msdos-initiate)
+(defun S+-msdos-initiate (&optional proc-name)
+ "Call 'S-PLUS [678].x for Windows', the 'GUI Thing' from StatSci. Put
+S-Plus in an independent MS-Window (Splus persists even if the
+'(ddeESS [S+])' window is killed in emacs). Do this by creating a
+comint process that calls sh. Send a shell command in that sh buffer
+to call Splus. When it completes set up a shell as a placeholder in
+the '(ddeESS [S+])' buffer. The S-Plus options are correctly set.
+In particular, the S-Plus Commands window is opened if the
+Options/General Settings/Startup menu says it should be. There is a
+startup delay of `ess-S+-startup-delay' seconds during which the
+screen will not be refreshed. This delay is here to allow slow disks
+to start the Splus program."
+ (interactive)
+ (save-excursion
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-program
+ (append ess-customize-alist '((inferior-ess-program
+ . (getenv "COMSPEC")))))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
+ (setq ess-customize-alist ; change inferior-ess-start-args
+ (append ess-customize-alist '((inferior-ess-start-args . ""))))
+ (let ((s-proj (getenv "S_PROJ"))
+ (use-dialog-box (not (or ess-microsoft-p (eq system-type 'cygwin))))
+ )
+ (cd (when (fboundp 'w32-short-file-name)
+ (w32-short-file-name (directory-file-name default-directory))))
+ (setenv "S_PROJ" (when
+ (fboundp 'w32-short-file-name)
+ (w32-short-file-name default-directory)))
+ (inferior-ess)
+ (sleep-for 2) ; need to wait, else working too fast! The Splus
+ ; command in '(ddeESS [S+])' should follow the "$"
+ ; prompt. If not, then increase the sleep-for time!
+ (setenv "S_PROJ" s-proj))
+ (setq ess-customize-alist S+-customize-alist)
+ (ess-setq-vars-local ess-customize-alist)
+;;; the next three lines belong in customize-alist, but can't be there
+;;; because of the broken ess-setq-vars-default usage in ess-inf.el
+ (setq inferior-ess-ddeclient "ddeclient")
+ (setq inferior-ess-client-name "S-PLUS")
+ (setq inferior-ess-client-command "SCommand")
+;;; end of what belongs in customize-alist
+ (setq comint-input-sender 'comint-simple-send)
+ (setq comint-process-echoes nil)
+ (set-process-coding-system (get-buffer-process (current-buffer))
+ 'raw-text-dos 'raw-text-dos)
+ (goto-char (point-max))
+ (insert (concat inferior-S+-program " "
+ inferior-ess-start-args)) ; Note: there is no final "&".
+ ;; Without the "&", the results of !system.command come to '(ddeESS [S+])'
+ ;; With the "&", the results of !system.command in S get lost.
+ (inferior-ess-send-input)
+ (sleep-for ess-S+-startup-delay) ; Need to wait, else working too fast!
+ ; If the ess-current-process-name doesn't appear in the
+ ; Splus Commands window increase the sleep-for time!
+;;; from msdos-minor-mode
+ (setq comint-process-echoes t)
+ (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
+;;; end from msdos-minor-mode
+ (setq ess-local-process-name ess-current-process-name)
+ (ess-eval-linewise (concat "#" ess-current-process-name))
+ (goto-char (point-min))
+ (insert
+ "This is a placeholder buffer. You can't type anything here.
+Use `C-x b RET' to return to your file.\n
+Anything sent to this process from an S-mode buffer goes
+directly to the associated Splus Commands window.\n
+The S-Plus Commands window must be visible.
+You may need to open the S-Plus Commands window manually
+ (by clicking on Splus/Window/Commands Window).\n
+There is a `ess-S+-startup-delay' second delay when this program starts
+during which the emacs screen will be partially blank.\n
+Remember to 'q()' from S-Plus and
+then C-x C-q exit from the '(ddeESS [S+])' buffer,
+or take the risk of not being able to shut down your computer
+and suffering through scandisk.\n
+Any results of the !system.command typed at the S prompt in the
+Splus Commands window (are supposed to) appear in this buffer.\n\n")
+ (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+])'
+ (use-local-map comint-mode-map) ; a shell buffer after Splus is finished.
+ (setq buffer-read-only t) ; force buffer to be read-only
+ (setq mode-name "ddeESS")
+ ;; (ess-eval-linewise inferior-S+-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ ))
+
+(defalias 'S+6-msdos-existing 'S+-msdos-existing)
+(defun S+-msdos-existing (&optional proc-name)
+ "Call 'S-PLUS [678].x for Windows', the 'GUI Thing' from StatSci. Do so by
+finding an existing S-Plus in an independent MS-Window (if there is one) and
+set up a '(ddeESS [S+])' buffer in emacs. If there is no existing
+S-Plus, then a new one will be opened in the default directory. The default
+is usually something like 'c:/Program Files/Insightful/splus70/users/yourname'
+for S-Plus before 8.0.4. Beginning with 8.0.4, S-Plus uses the default directory
+'c:/Documents and Settings/yourname/My Documents/S-PLUS Projects/Project1'.
+Beginning with TIBCO Spotfire S+ Version 8.1.1 for Microsft Windows, the default
+directory is 'c:/DOCUME~1/yourname/MYDOCU~1/SPOTFI~1/Project1'.
+If you have a HOME environment variable, it will open it there."
+ (interactive)
+ (let* ((inferior-S+-multipleinstances "")
+ (ess-S+-startup-delay 0)) ;; No delay for existing S-Plus
+ (S+-msdos-initiate proc-name))
+ (with-current-buffer (car (buffer-list)) ; get the ESS buffer just created
+ (setq buffer-read-only nil) ; permit writing in ESS buffer
+ (goto-char (point-max))
+ (beginning-of-line)
+ (forward-line -1)
+ (insert
+ "This is S+-msdos-existing.
+Results of the !system.command typed at the S prompt in the
+Splus Commands window blink a DOS window and you won't see them.\n\n")
+ (setq buffer-read-only t) ; restore ESS buffer to be read-only
+ ))
+
+(defun ess-sqpe-versions-create (ess-SHOME-versions &optional x64)
+ "Generate the `M-x splusxy' functions for starting other versions of
+Sqpe. `ESS-SHOME-VERSIONS' is normally taken from
+`ess-sqpe-versions', a variable that contains strings that determine which
+functions are created. This works by creating a temp buffer where the
+template function `Sqpe+template' is edited by replacing the string
+'Sqpe+template' by the version name. The list of functions actually
+created appears in the `ess-dribble-buffer'. If `X64' is not nil, then
+modify the function name to show \"-64bit\" in its name.
+
+The result `ess-sqpe-versions-created' will store a list of the new
+Sqpe defuns, if any, that were created. The defuns will normally be
+placed on the menubar upon ESS initialisation."
+ (let ((beg)
+ (versions)
+ (version)
+ (eval-buf (get-buffer-create "*ess-temp-sqpe-evals*"))
+ (ess-sqpe-versions-created)
+ )
+ ;;
+ (with-current-buffer eval-buf
+ ;; clear the buffer.
+ (delete-region (point-min) (point-max))
+
+ ;; Find which versions of Sqpe we want.
+ (setq x64 (if x64 "-64bit"))
+ (setq versions (ess-uniq-list ess-SHOME-versions))
+ ;; Iterate over each string in VERSIONS, creating a new defun each time.
+ (while versions
+ (setq version (car versions)
+ versions (cdr versions))
+ (if (file-executable-p version)
+ (progn
+ (setq beg (point))
+ (setq version-function-name (concat (file-name-nondirectory version) x64))
+ (prin1 (symbol-function 'Sqpe+template) eval-buf)
+ (insert "\n\n")
+ (goto-char beg)
+ (while (search-forward "lambda" nil t 1)
+ (replace-match
+ (concat "defun " version-function-name)
+ t t))
+ (while (search-forward "ess-SHOME" nil t)
+ (replace-match version t t))
+ (goto-char (point-max))
+ (setq ess-sqpe-versions-created
+ (cons version-function-name
+ ess-sqpe-versions-created))
+ (ess-write-to-dribble-buffer
+ (format
+ "(Sqpe): ess-sqpe-versions-create making M-x defun %s for %s \n"
+ version-function-name version))
+ )))
+ ;; buffer has now been created with defuns, so eval them!
+ (eval-buffer)
+ (kill-buffer eval-buf))
+ ess-sqpe-versions-created))
+
+;; template function used by ess-sqpe-versions-create
+(defun Sqpe+template (&optional proc-name)
+ "Call 'Sqpe' from 'S-PLUS for Windows ess-SHOME',
+the 'Real Thing' from StatSci.
+This function was generated by `ess-sqpe-versions-create'."
+ (interactive)
+ (setq ess-customize-alist Sqpe+-customize-alist)
+ (let* ((use-dialog-box) ;; MS dialog box won't return a directory
+ (shome-old (getenv "SHOME"))
+ (inferior-Sqpe+-SHOME-name "ess-SHOME")
+ (inferior-Sqpe+-program (concat "ess-SHOME" "/cmd/sqpe.exe")))
+ (setenv "SHOME" "ess-SHOME")
+ (ess-write-to-dribble-buffer
+ (format "\n(Sqpe+template): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (setq ess-customize-alist ; change inferior-ess-primary-prompt
+ (append ess-customize-alist
+ '((inferior-ess-primary-prompt . "^"))))
+ (inferior-ess)
+ (setq ess-customize-alist Sqpe+-customize-alist) ; restore i-e-p-p in alist
+ (ess-setq-vars-local ess-customize-alist) ; restore i-e-p-p in buffer
+ (setq inferior-ess-prompt ; define with correct i-e-p-p
+ ;; Do not anchor to bol with `^' ; (copied from ess-inf.el)
+ (concat "\\("
+ inferior-ess-primary-prompt
+ "\\|"
+ inferior-ess-secondary-prompt
+ "\\)"))
+ (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
+ ; define with correct i-e-p-p
+ (setq comint-input-sender 'inferior-ess-input-sender)
+ (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
+ (goto-char (point-max))
+ (insert "options(interactive=TRUE)")
+ (inferior-ess-send-input)
+ (setq mode-name "iESS(Sqpe)")
+ ;; (ess-eval-linewise inferior-S+-editor-pager-command)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start))
+ (setenv "SHOME" shome-old)))
+
+
+\f ; Provide package
+
+(provide 'ess-sp6w-d)
+
+;;; ess-sp6w-d.el ends here
--- /dev/null
+;;; ess-stata-lang.el --- Stata customization
+
+;; 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 <thomasNOSPAMbiostat.washington.edu>,
+;; Brendan Halpin <brendanNOSPAMessex.ac.uk>
+;; Created: 2 Nov 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+(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
+(unless (boundp 'c-emacs-features)
+ (require 'cc-vars));; for syntax-table
+(require 'comint)
+(require 'ess-trns)
+
+ ;(setq max-lisp-eval-depth 500)
+(eval-when-compile
+ (setq max-lisp-eval-depth (max 600 max-lisp-eval-depth)))
+
+(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.")
+
+(defvar STA-syntax-table
+ (let ((tbl (make-syntax-table)))
+ (modify-syntax-entry ?\\ "." tbl) ;nullify escape meaning
+ (modify-syntax-entry ?\$ "." tbl)
+ (modify-syntax-entry ?` "(\'" tbl)
+ (modify-syntax-entry ?\' ")`" tbl)
+ ;;--------- begin cut-and-paste from lisp/progmodes/c-langs.el
+ (modify-syntax-entry ?/ ". 124b" tbl)
+ (modify-syntax-entry ?* ". 23" tbl)
+ (modify-syntax-entry ?\n "> b" tbl)
+ ;; Give CR the same syntax as newline, for selective-display
+ (modify-syntax-entry ?\^m "> b" tbl)
+ ;;--------- end cut-and-paste ------------------
+ (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 Stata code.")
+
+(defun ado-set-font-lock-keywords ()
+ "Create font lock keywords for Stata syntax. This is from the
+ado-mode of Bill Rising <brisingNOSPAMjhsph.edu>, 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)
+ (require-final-newline . mode-require-final-newline)
+ (comment-column . 40)
+ ;;(comment-indent-function . 'S-comment-indent)
+ ;;(ess-comment-indent . 'S-comment-indent)
+ ;;(ess-indent-line . 'S-indent-line)
+ ;;(ess-calculate-indent . 'ess-calculate-indent)
+ (indent-line-function . 'ess-indent-line)
+ (parse-sexp-ignore-comments . t)
+ (ess-style . ess-default-style)
+ (ess-local-process-name . nil)
+ ;;(ess-keep-dump-files . 'ask)
+ (ess-mode-syntax-table . STA-syntax-table)
+ (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))))
+
+;;;; <IGNORE>
+;;; This doesn't do anything at the moment. I have vague plans of
+;;; implementing a menu interface using emacs
+;;;
+(defun stata-watch-for-menu-filter (proc string)
+ (if (string-match "^!!!window!!!" string)
+ (stata-handle-menu-code proc string)
+ (comint-output-filter proc string)))
+
+(defun stata-handle-menu-code (proc string)
+ (let ((old-buffer (current-buffer)))
+ (unwind-protect
+ (let (moving)
+ (set-buffer (process-buffer proc))
+ (setq moving (= (point)
+ (process-mark proc)))
+ (save-excursion
+ ;; Insert the text, moving the process-marker.
+ (goto-char (process-mark proc))
+ (insert "Handling menu code\n")
+ (set-marker (process-mark proc) (point)))
+ (if moving (goto-char (process-mark proc))))
+ (set-buffer old-buffer))))
+
+;;;; </IGNORE>
+
+(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 "^. "))))))
+
+(defun stata-help-mode ()
+ "Major mode for displaying Stata help in a read-only buffer.
+Active commands are Help (\\[stata-help]) and hyperlink
+(\\[stata-rehelp] or mouse-2)."
+ (interactive)
+ (setq major-mode 'stata-help-mode)
+ (setq mode-name "Stata help")
+ ;;(use-local-map stata-help-mode-map)
+ (setq buffer-read-only t))
+
+;;; 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
--- /dev/null
+;;; ess-stata-mode.el --- Stata customization
+
+;; 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 <rossiniNOSPAMbiostat.washington.edu>
+;; Created: 9 Sep 1998
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 <thomasNOSPAMbiostat.washington.edu>.
+
+;;; 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 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-mode-syntax-table . STA-syntax-table)
+ (ess-mode-edit . 'STA-mode)
+ (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" )
+ (ess-help-web-search-command . "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")
+ (ess-eval-linewise-function . #'stata-eval-linewise)
+ (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--")
+ (comint-use-prompt-regexp . t)
+ (inferior-ess-start-file . inferior-STA-start-file) ;"~/.ess-stata")
+ (inferior-ess-start-args . inferior-STA-start-args)
+ (ess-get-help-topics-function . 'ess-get-STA-help-topics)
+ (inferior-ess-search-list-command . "set more off\n search()\n")
+ (comment-start . "/\* ")
+ (comment-end . " \*/")
+ (comment-start-skip . "/\\*+ *")
+ (comment-use-syntax . t) ;; needed for multiline
+ (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.")
+
+
+;;;###autoload
+(defun STA-mode (&optional proc-name)
+ "Major mode for editing Stata source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist STA-customize-alist)
+ (ess-mode STA-customize-alist proc-name))
+
+(fset 'stata-mode 'STA-mode)
+(fset 'Stata-mode 'STA-mode)
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.do\\'" . STA-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.ado\\'" . STA-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."
+ (interactive "P")
+ (setq ess-customize-alist STA-customize-alist)
+ (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####] ? ")))))
+ (inferior-ess sta-start-args)
+ (let ((proc (get-process ess-local-process-name)))
+ (while (process-get proc 'sec-prompt)
+ ;; get read of all --more-- if stata.msg is too long.
+ (ess-send-string proc "q")
+ (ess-wait-for-process proc t))
+ (ess-send-string proc "set more off")
+ (goto-char (point-max))
+ (with-current-buffer (process-buffer proc)
+ (add-hook 'ess-presend-filter-functions 'ess-sta-remove-comments nil 'local)
+ (run-mode-hooks 'ess-stata-post-run-hook)))))
+
+
+(defun STA-transcript-mode ()
+ "Stata transcript mode."
+ (interactive)
+ (ess-transcript-mode STA-customize-alist))
+
+(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))
+ )))
+
+(defun ess-get-STA-help-topics (&optional name)
+ "Return a list of current STA help topics associated with process NAME."
+ (or (ess-process-get 'help-topics)
+ (progn
+ (ess-process-put 'help-topics (ess--STA-retrive-topics-from-search))
+ (ess-process-get 'help-topics))))
+
+(defun stata-eval-linewise (text &optional invisibly &rest args)
+ ;; The following is required to make sure things work!
+ (let ((ess-eval-linewise-function nil)
+ ;; RAS: mindless replacement of semi-colons
+ (text (if ess-sta-delimiter-friendly
+ (ess-replace-in-string text ";" "\n")
+ text)))
+ (apply #'ess-eval-linewise text t args)))
+
+\f ; Provide package
+
+(provide 'ess-stata-mode)
+
+;;; ess-stata-mode.el ends here
--- /dev/null
+;;; 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 <david.whitingNOSPAMncl.ac.uk>
+;; Created: 15 April 2005
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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")
+
+(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)
+ (switch-to-buffer rnw-buf)
+ (ess-show-buffer (buffer-name sbuffer) nil))))))
+
+(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"))
+
+(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 (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)
+
+\f ; provides
+
+(provide 'ess-swv)
+
+;;; ess-swv.el ends here
--- /dev/null
+;;; ess-toolbar.el --- Support for a toolbar in ESS.
+
+;; 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 <ESS-coreNOSPAMr-project.org>
+
+;; 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-utils)
+(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."
+ ;; 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."
+ (if (and ess-toolbar (not ess-toolbar-global))
+ (set (make-local-variable '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
--- /dev/null
+;; ess-tracebug.el --- Tracing and debugging facilities for ESS.
+;;
+;; 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/
+
+;;
+;; Features that might be required by this library:
+;;
+;; ESS - required
+;; ido, face-remap, cl - desirable and are part of default emacs
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; 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 at
+;; https://code.google.com/p/ess-tracebug/ and a brief tutorial at
+;; https://code.google.com/p/ess-tracebug/wiki/GettingStarted
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(eval-when-compile
+ (require 'cl)
+ (require 'cl-lib)
+ (require 'tramp))
+(require 'comint)
+(require 'compile)
+(require 'overlay)
+(require 'ring)
+(require 'ess-custom)
+(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)
+(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-show-buffer "ess-inf")
+(declare-function ess-switch-to-ESS "ess-inf")
+(declare-function ess-wait-for-process "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")
+
+
+(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--tracebug-p nil
+;; "Non nil if ess-tracebug is turned on for current process.
+;; Function `ess-tracebug' toggles on/off this variable.")
+;; (make-variable-buffer-local 'ess--tracebug-p)
+;; (add-to-list 'minor-mode-alist '(ess--tracebug-p ess-tracebug-indicator))
+
+(defvar ess-watch-mode-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map special-mode-map)
+ (define-key map "?" 'ess-watch-help)
+ (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-watch-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 the *R watch* buffer.
+
+\\{ess-watch-mode-map}")
+
+
+(defcustom ess-tracebug-prefix nil
+ "*Key to be used as prefix for all `ess-tracebug' commands.
+Set this to a key cominbation 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)
+
+;; (make-obsolete-variable 'ess-tracebug-prefix "ess-tracebug-prefix will be removed in future versions.
+;; Electric debug keys are now on C-c and ess-dev maps." "ESS 13.05")
+;; (define-obsolete-variable-alias 'ess-tracebug-command-prefix 'ess-tracebug-prefix)
+
+(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 ess-watch-current-block-overlay nil
+ "The overlay for currently selected block in the R watch buffer .")
+(make-variable-buffer-local 'ess-watch-current-block-overlay)
+
+(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 enteres the code it desplayes
+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 soruce 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."
+ (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-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)
+
+* 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 (&optional ev)
+ "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 ess--busy-count 0
+ "Used to compute the busy indicator.")
+(make-variable-buffer-local 'ess--busy-count)
+
+;; (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))
+ (set (make-local-variable '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)
+ (if (null ess-traceback-command)
+ (error "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))
+ (setq next-error-last-buffer trbuf)
+ (with-current-buffer trbuf
+ (setq buffer-read-only nil)
+ (setq ess-local-process-name lproc-name)
+ (ess-command cmd trbuf)
+ (goto-char (point-min))
+ ;; fixme: this is R specific check
+ (if (re-search-forward "No traceback available" nil t)
+ (message "No traceback available")
+ (ess-dirs)
+ (message nil)
+ (make-local-variable 'compilation-error-regexp-alist)
+ (when (boundp 'ess-r-error-regexp-alist)
+ (setq compilation-error-regexp-alist ess-r-error-regexp-alist))
+ (make-local-variable 'compilation-search-path)
+ (setq 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)
+ ;(use-local-map ess-traceback-minor-mode-map)
+ ;; ess keys
+ (local-set-key "\C-c\C-s" 'ess-watch-switch-process)
+ (local-set-key "\C-c\C-y" 'ess-switch-to-ESS)
+ (local-set-key "\C-c\C-z" 'ess-switch-to-end-of-ESS)
+
+ (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)))
+ (last 1)
+ (n (or n 1))
+ timestamp
+ (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 err
+ (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 end-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))
+ end-loc (if (fboundp 'compilation--message->end-loc) ;; emacs 24
+ (compilation--message->end-loc msg)
+ (nth 2 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 ess--dbg-current-ref (make-marker)
+ "Current debug reference in *ess.dbg* buffers (a marker).")
+(make-variable-buffer-local 'ess--dbg-current-ref)
+
+(defvar ess--dbg-last-ref-marker (make-marker)
+ "Last debug reference in *ess.dbg* buffer (a marker).")
+(make-variable-buffer-local 'ess--dbg-last-ref-marker)
+
+(defvar ess--dbg-buf-p nil
+ "This is t in ess.dbg buffers.")
+(make-variable-buffer-local 'ess--dbg-buf-p)
+
+;; (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}")
+
+(ess-if-verbose-write "\n<- debug-vars done")
+
+;;;_ + 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* ((alist ess-debug-error-action-alist)
+ (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 initialy 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
+ (switch-to-buffer (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)
+ (switch-to-buffer (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
+ (switch-to-buffer (marker-buffer ess--dbg-current-debug-position))
+ (goto-char (marker-position ess--dbg-current-debug-position ))
+ (back-to-indentation))
+ (switch-to-buffer (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)
+ (switch-to-buffer (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'."
+ ;; the process here is an ugly reliance on dynamic scope
+ (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 spiner 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)
+ ;; looks like redisplay is necessary for emacs > 24.4
+ (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 ()
+ (and (ess-process-live-p)
+ (or (ess-process-get 'dbg-active)
+ (ess-process-get 'is-recover))))
+
+(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)
+
+
+\f
+;;; MPI
+
+(defvar ess-mpi-control-regexp "\e\\([^\1e]+\\)\1e\\([^\1d]+\\)\1d")
+
+(defvar ess-mpi-alist
+ '(("message" . message)
+ ("error" . ess-mpi:error)
+ ("eval" . ess-mpi:eval)
+ ("y-or-n" . ess-mpi:y-or-n)))
+
+(defun ess-mpi:error (msg)
+ (message (format "Error in inferior: %s" msg)))
+
+(defun ess-mpi:eval (expr &optional callback)
+ "Evaluate EXP 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 expr))))
+ (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
+ (ess-send-string (ess-get-process) (format callback result)))))
+
+(defun ess-mpi-handle-messages (buf)
+ "Handle all mpi messages in BUF and delete them."
+ (let ((obuf (current-buffer)))
+ (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 (re-search-forward ess-mpi-control-regexp nil t)
+ (let* ((mbeg (match-beginning 0))
+ (mend (match-end 0))
+ (head (match-string 1))
+ (payload (split-string (match-string 2) "\1e"))
+ (handler (cdr (assoc head ess-mpi-alist))))
+ (if handler
+ (condition-case-unless-debug err
+ (with-current-buffer obuf
+ (apply handler payload))
+ (error (message (format "Error in mpi `%s' handler: %%s" head)
+ (error-message-string err))))
+ ;; don't throw error here. The buffer must be cleaned first.
+ (message "Now handler defined for MPI message '%s" head))
+ (goto-char mbeg)
+ (delete-region mbeg mend))))))
+
+(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))
+ (len (length 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)
+ ;; 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))
+ (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)
+ (ess-show-buffer (process-buffer proc))))
+ (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))
+ (eol (point-at-eol)))
+ (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.
+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 (member major-mode (list 'inferior-ess-mode 'ess-watch-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 (not (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 surpressing 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)
+ (and (boundp 'edebug-mode) 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)
+ (and (boundp 'org-babel-current-src-block-location)
+ org-babel-current-src-block-location))
+ (ess--flush-accumulated-output proc)
+ ;; setup new flush timer; ideally also for fast-flush cased 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 inferiro
+ (ess-show-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."
+ (interactive)
+ (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)
+ (switch-to-buffer 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 (and (boundp 'org-babel-tangled-file)
+ 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))))
+ buffsym buffer fmts name buffername)
+ (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)
+ (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."
+ (interactive "p")
+ (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--dbg-next-ref-function (n &optional reset)
+ "Advance to the next reference and visit the location given by the reference.
+This is the value of `next-error-function' in *ess.dbg* buffers."
+ (interactive "p")
+ (if reset
+ (set-marker ess--dbg-current-ref ess--dbg-last-ref-marker))
+ (let ((loc (ess--dbg-get-next-ref n nil ess--dbg-current-ref)) ;; moves point to next/prev ref if any
+ ; loc is (file . line_nr)
+ dbuff)
+ (if loc
+ (progn
+ (set-marker ess--dbg-current-ref (line-end-position))
+ (set-marker overlay-arrow-position (line-beginning-position))
+ (setq dbuff (ess--dbg-find-buffer (car loc)))
+ (switch-to-buffer dbuff)
+ (save-restriction
+ (widen)
+ (goto-char 1)
+ (forward-line (1- (cdr loc))))
+ (move-marker ess--dbg-current-debug-position (line-beginning-position)) ; move the overlay-arrow
+ (back-to-indentation))
+ (if (>= 0 (or n 1))
+ (error "Moved past first debug line")
+ (error "Moved past last debug line")))))
+
+
+;; not used; remove in 13.09
+(defvar ess-electric-debug-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "c" 'ess-debug-command-continue)
+ (define-key map "C" 'ess-debug-command-continue-multi)
+ (define-key map "n" 'ess-debug-command-next)
+ (define-key map "N" 'ess-debug-command-next-multi)
+ (define-key map "q" 'ess-debug-command-quit)
+ (define-key map "u" 'ess-debug-command-up)
+ map)
+ "Keymap used to define commands for single key input mode.
+This commands are triggered by `ess-electric-debug' .
+\\{ess-electric-debug-map}")
+(make-obsolete-variable 'ess-electric-debug-map nil "ESS 13.05")
+
+(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")
+ " "))))
+
+;; not used anywhere; remove in ESS 13.09
+(defun ess-electric-debug (&optional wait)
+ "Call commands defined in `ess-electric-debug-map'.
+Single-key input commands are those that once invoked do not
+requre the prefix command for subsequent invocation.
+
+For example, if the prefix key is 'C-c C-t' and
+`ess-debug-command-next' is bound to 'n' and `ess-debug-command-continue' is
+bound to 'c' then 'C-c C-t n n c' executes `ess-debug-command-next'
+twice and `ess-debug-command-continue' once. Any other input not defined
+in `ess-electric-debug-map' will cause the exit from single-key
+input mode.
+
+If WAIT is t, wait for next input and ignore the keystroke which
+triggered the command."
+ (interactive)
+ (let ((help-mess (ess--debug-keys-message-string
+ ess-electric-debug-map)))
+ (ess--execute-electric-command
+ ess-electric-debug-map help-mess wait
+ (not (ess-process-get 'dbg-active)))))
+
+(define-obsolete-function-alias
+ 'ess-singlekey-debug 'ess-electric-debug "ESS 13.05")
+(make-obsolete 'ess-electric-debug nil "ESS 13.05")
+
+(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
+requre the prefix command for subsequent invocation. See
+`ess-electric-debug' for more.
+
+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))))
+
+(make-obsolete 'ess-singlekey-selection 'ess-electric-selection "ESS 13.05")
+
+(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 (&optional ev)
+ "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 ev 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 ev 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 (&optional ev)
+ "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 (&optional ev)
+ "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 (&optional ev)
+ "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"))
+ (bp-length (length bp-command))
+ (dummy-string (format "##:ess-bp-start::%s@%s:##\n" (car bp-specs) condition))
+ (dummy-length (length dummy-string))
+ 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
+ 'intangible 'ess-bp
+ 'rear-nonsticky '(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
+ '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
+ (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
+ 'intangible 'ess-bp
+ 'rear-nonsticky '(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
+ '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
+ ;; 'intangible 'ess-bp
+ ;; 'display (propertize (nth 1 ess-bp-inactive-spec) 'face fringe-face)
+ ;; 'bp-type type
+ ;; 'bp-substring 'comment)))
+ ))))))))
+
+(add-hook '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))))
+ pos 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-arround 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))
+ (inhibit-point-motion-hooks t) ;; deactivates intangible property
+ bp-id beg-pos-dummy end-pos-comment 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
+ ;; '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)
+ (let ((cur-pos (point))
+ (bp-pos (next-single-property-change (point) 'ess-bp)))
+ (when bp-pos
+ (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)
+ (let ((cur-pos (point))
+ (bp-pos (previous-single-property-change (point) 'ess-bp)))
+ (if bp-pos
+ (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)))))
+
+(defun ess-watch-mode ()
+ "Major mode in `ess-watch' window.
+\\{ess-watch-mode-map}"
+ (let ((cur-block (max 1 (ess-watch-block-at-point)))
+ (dummy-string
+ (ess-tracebug--propertize "|" 'current-watch-bar 'font-lock-keyword-face)))
+ (kill-all-local-variables)
+ (ess-tracebug--set-left-margin)
+ (make-local-variable 'revert-buffer-function)
+ (setq revert-buffer-function 'ess-watch-revert-buffer)
+ (use-local-map ess-watch-mode-map)
+ (setq major-mode 'ess-watch-mode)
+ (setq mode-name (concat "watch " ess-current-process-name))
+ (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) ;;
+ (when (require 'face-remap nil t)
+ ;; scale the font
+ (setq text-scale-mode-amount ess-watch-scale-amount)
+ (text-scale-mode 1) ; (text-scale-mode -1) ;;restore to default
+ )))
+
+(defun ess-watch ()
+ "Run `ess-watch' mode on R objects.
+This is the trigger function. See documentation of
+`ess-watch-mode' for more information.
+
+\\{ess-watch-mode-map}"
+ (interactive)
+ (ess-force-buffer-current)
+ (let ((wbuf (get-buffer-create ess-watch-buffer))
+ (pname ess-local-process-name)
+ (alist (symbol-value ess-local-customize-alist)))
+ (set-buffer wbuf)
+ (ess-setq-vars-local alist)
+ (setq ess-local-process-name pname)
+ (ess-watch-mode)
+ (ess-watch-refresh-buffer-visibly wbuf) ;; evals the ess-command and displays the buffer if not visible
+ (pop-to-buffer wbuf)
+ (set-window-dedicated-p (selected-window) 1) ;; not strongly dedicated
+ ))
+
+
+(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.
+
+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
+ (interactive)
+ (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
+ (setq buffer-read-only nil)
+ (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))
+ (setq buffer-read-only t)))))
+
+(defun ess-watch-buffer-show (buffer-or-name)
+ "Make watch buffer BUFFER-OR-NAME visible, and position acordingly.
+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
+ )
+
+(defvar ess-watch-help nil
+ "Keymap for the *R watch* buffer.
+
+\\{ess-watch-mode-map}")
+
+(defun ess-watch-help ()
+ "Help on `ess-watch'."
+ (interactive)
+ (describe-variable 'ess-watch-help))
+
+(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 curr-point)
+ (save-excursion
+ (ess-if-verbose-write (format "ess-get-signatures*(%s).. " method))
+ (ess-command (concat "showMethods(\"" method "\")\n") tbuffer)
+ (message ess-local-process-name)
+ (message 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 redability 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 default-string out-message)
+ ;; 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 (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 out-message)))
+
+;;;_ * Kludges and Fixes
+;;; delete-char and delete-backward-car do not delete whole intangible text
+(defadvice delete-char (around ess-delete-backward-char-intangible activate)
+ "When deleting an intangible char, delete the whole intangible region.
+Only do this when #chars is 1"
+ (if (and (eq major-mode 'ess-mode)
+ (= (ad-get-arg 0) 1)
+ (get-text-property (point) 'intangible))
+ (progn
+ (kill-region (point) (or (next-single-property-change (point) 'intangible)
+ (point-max)))
+ (indent-for-tab-command))
+ ad-do-it))
+
+(defadvice delete-backward-char (around ess-delete-backward-char-intangible activate)
+ "When deleting an intangible char, delete the whole intangible region.
+Only do this when called interactively and #chars is 1"
+ (if (and (eq major-mode 'ess-mode)
+ (= (ad-get-arg 0) 1)
+ (> (point) (point-min))
+ (get-text-property (1- (point)) 'intangible))
+ (progn
+ (let ((beg (or (previous-single-property-change (point) 'intangible)
+ (point-min))))
+ (kill-region beg (point))))
+ ad-do-it))
+
+;; reported as bug#21368
+
+;; ;; previous-line gets stuck if next char is intangible
+;; reported
+;; (defadvice previous-line (around ess-fix-cursor-stuck-at-intangible-text activate)
+;; "When about to move to previous line when next char is
+;; intangible, step char backward first"
+;; (when (and (eq major-mode 'ess-mode)
+;; (or (null (ad-get-arg 0))
+;; (= (ad-get-arg 0) 1))
+;; (get-text-property (point) 'intangible))
+;; (goto-char (1- (point))))
+;; ad-do-it)
+
+;; (ad-remove-advice 'previous-line 'around 'ess-fix-cursor-stuck-at-intangible-text)
+
+(make-obsolete-variable 'ess-dbg-blink-ref-not-found-face 'ess-debug-blink-ref-not-found-face "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-blink-same-ref-face 'ess-debug-blink-same-ref-face "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-current-debug-line-face 'ess-debug-current-debug-line-face "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-error-action nil "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-error-action-alist 'ess-debug-error-action-alist "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-blink-interval 'ess-debug-blink-interval "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-indicator 'ess-debug-indicator "ESS 13.05")
+(make-obsolete-variable 'ess-dbg-ask-for-file 'ess-debug-ask-for-file "ESS 13.05")
+(make-obsolete 'ess-dbg-set-error-action 'ess-debug-set-error-action "ESS 13.05")
+(make-obsolete 'ess-dbg-toggle-error-action 'ess-debug-toggle-error-action "ESS 13.05")
+(make-obsolete 'ess-dbg-goto-input-event-marker 'ess-debug-goto-input-event-marker "ESS 13.05")
+(make-obsolete 'ess-dbg-goto-debug-point 'ess-debug-goto-debug-point "ESS 13.05")
+(make-obsolete 'ess-dbg-insert-in-forward-ring 'ess-debug-insert-in-forward-ring "ESS 13.05")
+(make-obsolete 'ess-dbg-start 'ess-debug-start "ESS 13.05")
+(make-obsolete 'ess-dbg-stop 'ess-debug-stop "ESS 13.05")
+(make-obsolete 'ess-dbg-command-digit 'ess-debug-command-digit "ESS 13.05")
+(make-obsolete 'ess-dbg-command-n 'ess-debug-command-next "ESS 13.05")
+(make-obsolete 'ess-dbg-command-Q 'ess-debug-command-quit "ESS 13.05")
+(make-obsolete 'ess-dbg-command-c 'ess-debug-command-continue "ESS 13.05")
+(make-obsolete 'ess-dbg-flag-for-debugging 'ess-debug-flag-for-debugging "ESS 13.05")
+(make-obsolete 'ess-dbg-unflag-for-debugging 'ess-debug-unflag-for-debugging "ESS 13.05")
+(make-obsolete-variable 'ess-tb-last-input-fringe-face 'ess-tracebug-last-input-fringe-face "ESS 13.05")
+(make-obsolete-variable 'ess-tb-next-error-function 'ess-tracebug-next-error-function "ESS 13.05")
+
+(ess-if-verbose-write "\n<- debug done")
+(provide 'ess-tracebug)
+
+;;; ess-tracebug.el ends here
--- /dev/null
+;;; ess-trns.el --- Support for manipulating S transcript files
+
+;; 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 <dsmithNOSPAMstats.adelaide.edu.au>
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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:
+
+\f ; Requires and autoloads
+
+(require 'ess-mode)
+(require 'ess-inf)
+(require 'comint)
+
+\f ; ess-transcript-mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; In this section:
+;;;;
+;;;; * The major mode ess-transcript-mode
+;;;; * Commands for ess-transcript-mode
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;*;; Major mode definition
+(defvar ess-transcript-mode-map nil "Keymap for `ess-transcript-mode'.")
+(unless ess-transcript-mode-map
+ (setq ess-transcript-mode-map (make-sparse-keymap))
+
+ (define-key ess-transcript-mode-map "\C-c\C-s" 'ess-switch-process)
+ (define-key ess-transcript-mode-map "\C-c\C-r" 'ess-eval-region)
+ (define-key ess-transcript-mode-map "\C-c\M-r" 'ess-eval-region-and-go)
+ ;; (define-key ess-transcript-mode-map "\M-\C-x" 'ess-eval-function)
+ ;; (define-key ess-transcript-mode-map "\C-c\M-f" 'ess-eval-function-and-go)
+ ;; (define-key ess-transcript-mode-map "\C-c\C-j" 'ess-eval-line)
+ ;; (define-key ess-transcript-mode-map "\C-c\M-j" 'ess-eval-line-and-go)
+
+ (define-key ess-transcript-mode-map "\C-c\C-k" 'ess-force-buffer-current)
+ (define-key ess-transcript-mode-map "\C-c\C-q" 'ess-quit)
+
+ (define-key ess-transcript-mode-map "\C-c\C-j" 'ess-transcript-send-command)
+ (define-key ess-transcript-mode-map "\C-c\M-j" 'ess-transcript-send-command-and-move)
+ (define-key ess-transcript-mode-map "\M-\C-a" 'ess-goto-end-of-function-or-para)
+ (define-key ess-transcript-mode-map "\M-\C-e" 'ess-goto-end-of-function-or-para)
+ (define-key ess-transcript-mode-map "\C-c\C-y" 'ess-switch-to-ESS)
+ (define-key ess-transcript-mode-map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
+ (define-key ess-transcript-mode-map "\C-c\C-v" 'ess-display-help-on-object)
+ (define-key ess-transcript-mode-map "\C-c\C-d" 'ess-dump-object-into-edit-buffer)
+ (define-key ess-transcript-mode-map "\C-c\t" 'ess-complete-object-name-deprecated)
+ (define-key ess-transcript-mode-map "\C-a" 'comint-bol)
+ (define-key ess-transcript-mode-map "\M-\t" 'comint-replace-by-expanded-filename)
+ (define-key ess-transcript-mode-map "\M-?" 'comint-dynamic-list-completions)
+ (define-key ess-transcript-mode-map "\C-c\C-k" 'ess-request-a-process)
+ (define-key ess-transcript-mode-map "{" 'skeleton-pair-insert-maybe)
+ (define-key ess-transcript-mode-map "}" 'skeleton-pair-insert-maybe)
+ (define-key ess-transcript-mode-map "\e\C-h" 'ess-mark-function)
+ (define-key ess-transcript-mode-map "\e\C-q" 'ess-indent-exp)
+ ;(define-key ess-transcript-mode-map "\177" 'backward-delete-char-untabify)
+ (define-key ess-transcript-mode-map "\t" 'ess-indent-command)
+
+ (define-key ess-transcript-mode-map "\C-c\C-p" 'comint-previous-prompt)
+ (define-key ess-transcript-mode-map "\C-c\C-n" 'comint-next-prompt)
+ ;; (define-key ess-transcript-mode-map "\C-c\C-n" 'ess-eval-line-and-step)
+
+ (define-key ess-transcript-mode-map "\r" 'ess-transcript-send-command-and-move)
+ (define-key ess-transcript-mode-map "\M-\r" 'ess-transcript-send-command)
+ (define-key ess-transcript-mode-map "\C-c\r" 'ess-transcript-copy-command)
+ (define-key ess-transcript-mode-map "\C-c\C-w" 'ess-transcript-DO-clean-region)
+ (define-key ess-transcript-mode-map "\C-c\M-c" 'ess-transcript-clean-buffer)
+ )
+
+(easy-menu-define
+ ess-transcript-mode-menu ess-transcript-mode-map
+ "Menu for use in S transcript mode."
+ '("ESS-trans"
+ ["What is this? (beta)" ess-mouse-me t]
+ ["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]
+ ))
+
+(if (featurep 'ess-trans)
+ (define-key ess-transcript-mode-map [menu-bar ess-trans]
+ (cons "ess-trans" ess-transcript-mode-menu))
+ (eval-after-load "ess-trans"
+ '(define-key ess-transcript-mode-map
+ [menu-bar ess-trans]
+ (cons "ess-trans"
+ ess-transcript-mode-menu))))
+;;;###autoload
+(defun ess-transcript-mode (alist &optional proc)
+ "Major mode for manipulating {ESS} transcript files.
+
+Type \\[ess-transcript-send-command] to send a command in the
+transcript to the current S 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 S commands. Other keybindings are:
+
+\\{ess-transcript-mode-map}"
+ (kill-all-local-variables)
+ (setq buffer-read-only t) ;; to protect the buffer.
+ (ess-setq-vars-local alist); (current-buffer))
+ (setq major-mode 'ess-transcript-mode)
+ (setq mode-name "ESS Transcript")
+ (use-local-map ess-transcript-mode-map)
+ (set-syntax-table (or inferior-ess-mode-syntax-table
+ ess-mode-syntax-table))
+ (setq mode-line-process
+ '(" [" ess-local-process-name "]"))
+ (make-local-variable 'ess-local-process-name)
+ (setq ess-local-process-name nil)
+ (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
+ "\\)")))
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^" inferior-ess-prompt "\\|^\^L"))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate "^\^L")
+ (make-local-variable 'comint-use-prompt-regexp)
+ (setq comint-use-prompt-regexp t)
+ (make-local-variable 'comint-prompt-regexp)
+ (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
+ (setq inferior-ess-font-lock-keywords 'inferior-ess-r-font-lock-keywords)
+ (setq font-lock-defaults '(ess-build-font-lock-keywords
+ nil nil ((?\. . "w") (?\_ . "w") (?' . "."))))
+
+ ;;; Keep <tabs> out of the code.
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+
+ (run-mode-hooks 'ess-transcript-mode-hook))
+
+;;*;; 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)
+ ;; (ess-transcript-send-command) ;; This doesn't work properly
+ ;; replacement code begins
+ (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))))
+ ;; replacement code ends
+ (goto-char ess-temp-point)
+ (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))
+
+;;;###autoload
+(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)))))
+
+
+;; unfinished idea :-----------------------
+
+;; (defun ess-clean-region-in-new-transcript (beg end)
+;; "Copy the region into a new ess-transcript buffer, and clean it there,
+;; using \\[ess-transcript-clean-region]."
+;; (interactive "r")
+
+;; (let ((bname (buffer-file-name)))
+;; (setq bname (if bname .. ..))
+;; (let
+;; (fbase (if fname (file-name-sans-extension (file-name-nondirectory fname))
+;; (buffer-name)))
+;;
+;; ;; the buffer name should be like a file name
+;; (buf-nam ....)
+;; (trns-buf (get-buffer-create fbase))
+;; (pop-to-buffer trns-buf)
+;; (ess-transcript-mode .....)
+;; )))
+
+
+
+
+(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
--- /dev/null
+;;; ess-utils.el --- General Emacs utility functions used by ESS
+
+;; 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 <maechlerNOSPAMstat.math.ethz.ch>
+;; Created: 9 Sept 1998
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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)
+(eval-when-compile
+ (require 'tramp))
+;; The only ESS file this file should depend on is ess-custom.el
+(require 'comint)
+(require 'ess-custom)
+(require 'ido)
+(defvar ac-modes)
+(declare-function evil-visual-state-p "evil")
+(declare-function evil-normal-state "evil")
+(declare-function color-lighten-name "color")
+(declare-function tramp-dissect-file-name "tramp")
+
+\f
+;;*;; Internal ESS tools and variables
+
+(defvar ess-lisp-directory
+ (directory-file-name
+ (file-name-directory
+ (if load-file-name
+ (file-truename load-file-name)
+ (locate-library "ess-utils") )))
+ "Directory containing ess-site.el(c) and other ESS Lisp files.")
+
+(defvar ess-etc-directory nil
+ "Location of the ESS etc/ directory.
+The ESS etc directory stores various auxillary files that are useful
+for ESS, such as icons.")
+
+;; Try to detect the `etc' folder only if not alread set up by distribution
+(unless ess-etc-directory
+ (let ((path-list '("../etc/ess/" "../etc/" "../../etc/ess/" "./etc/")))
+ (while (and (listp path-list) (consp path-list))
+ (setq ess-etc-directory
+ (expand-file-name (concat ess-lisp-directory "/"
+ (car path-list))))
+ (if (file-directory-p ess-etc-directory)
+ (setq path-list nil)
+ (setq ess-etc-directory nil)
+ (setq path-list (cdr path-list))
+ (when (null path-list)
+ (beep 0) (beep 0)
+ (message (concat
+ "ERROR:ess-etc-directory\n"
+ "Relative to ess-lisp-directory, one of the following must exist:\n"
+ "../etc/ess, ../etc, ../../etc/ess or ./etc"))
+ (sit-for 4))))))
+
+(defvar ess--make-local-vars-permanent nil
+ "If this variable is non-nil in a buffer make all variable permannet.
+Used in noweb modes.")
+(make-variable-buffer-local 'ess--make-local-vars-permanent)
+(put 'ess--make-local-vars-permanent 'permanent-local t)
+
+(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)))
+
+\f
+;;*;; elisp tools
+
+(defun ess-goto-line (line)
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line (1- line))))
+
+(defun ess-line-end-position (&optional N)
+ "Return the 'point' at the end of N lines. N defaults to 1, i.e., current line."
+ (save-excursion
+ (end-of-line N)
+ (point)))
+
+(defun ess-search-except (regexp &optional except backward)
+ "Search for a REGEXP and store as match 1.
+Optionally ignore strings that match exceptions."
+ (interactive)
+ (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."
+ (interactive)
+
+ (let ((ess-temp-point (point))
+ (ess-temp-return-value (buffer-modified-p)))
+ ;; if buffer has changed, save buffer now (before potential revert)
+ (if ess-temp-return-value (save-buffer))
+
+ ;; If Local Variables are defined, update them now
+ ;; since they may have changed since the last revert
+ ;; (save-excursion
+ (beginning-of-line -1)
+ (save-match-data
+ (if (search-forward "End:" nil t) (revert-buffer t t)))
+ ;; save-excursion doesn't save point in the presence of a revert
+ ;; so you need to do it yourself
+ (goto-char ess-temp-point)
+
+ 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."
+ (interactive)
+ (if file-or-buffer
+ (if (bufferp file-or-buffer) file-or-buffer
+ (find-buffer-visiting file-or-buffer))))
+
+(defun ess-set-local-variables (alist &optional file-or-buffer)
+ "Set local variables from ALIST in current buffer.
+If FILE-OR-BUFFER is specified, perform action in that buffer."
+ (interactive)
+ (if file-or-buffer (set-buffer (ess-get-file-or-buffer file-or-buffer)))
+
+ (mapcar (lambda (pair)
+ (make-local-variable (car pair))
+ (set (car pair) (eval (cdr pair))))
+ alist))
+
+(defun ess-return-list (ess-arg)
+ "If ESS-ARG is a list return it, else return ESS-ARG in a list."
+ (if (listp ess-arg) ess-arg (list ess-arg)))
+
+;; Copyright (C) 1994 Simon Marshall.
+;; Author: Simon Marshall <Simon.MarshallNOSPAMmail.esrin.esa.it>
+;; LCD Archive Entry:
+;; unique|Simon Marshall|Simon.MarshallNOSPAMmail.esrin.esa.it|
+;; Functions and commands to uniquify lists or buffer text (cf. sort).
+;; 23-Apr-1994|1.00|~/packages/unique.el.Z|
+;;
+;; MM: renamed from 'unique' to 'ess-unique', then
+(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 `ess-uniq-list'."
+ (let ((list list))
+ (while list
+ (setq list (setcdr list (funcall predicate (car list) (cdr list))))))
+ list)
+
+(defun ess-uniq-list (items)
+ "Delete all duplicate entries in ITEMS list, calling `ess-uniq'."
+ (ess-uniq items 'delete))
+
+(defun ess-flatten-list (&rest 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 '((a . b) c (d . e) (f g h) i . j))
+ ;; => (a b c d e f g h i j)
+ (ess-flatten-list-1 list))
+
+(defun ess-flatten-list-1 (list)
+ (cond
+ ((null list) (list))
+ ((consp list)
+ (append (ess-flatten-list-1 (car list))
+ (ess-flatten-list-1 (cdr list))))
+ (t (list list))))
+
+(defun ess-delete-blank-lines ()
+ "Convert 2 or more lines of white space into one."
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (save-match-data
+ (while (search-forward-regexp "^[ \t]*\n[ \t]*\n" nil t)
+ ;;(goto-char (match-beginning 0))
+ (delete-blank-lines)))))
+
+;; Parse a line into its constituent parts (words separated by
+;; whitespace). Return a list of the words.
+;; Taken from rlogin.el, from the comint package, from XEmacs 20.3.
+(defun ess-line-to-list-of-words (line)
+ (if (listp line)
+ line
+ (let ((list nil)
+ (posn 0))
+ ;; (match-data (match-data)))
+ (while (string-match "[^ \t\n]+" line posn)
+ (setq list (cons (substring line (match-beginning 0) (match-end 0))
+ list))
+ (setq posn (match-end 0)))
+ (store-match-data (match-data))
+ (nreverse list))))
+
+\f
+;;*;; 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)
+
+ (if (not (verify-visited-file-modtime (current-buffer))) (progn
+ (let ((ess-temp-store-point (point)))
+ (revert-buffer t t)
+ (goto-char ess-temp-store-point))
+ t)
+ nil))
+
+
+(defun ess-find-exec (ess-root-arg ess-root-dir)
+ "Given a root directory and the root of an executable file name,
+find it's full name and path, if it exists, anywhere in the sub-tree."
+ (let* ((ess-tmp-dirs (directory-files ess-root-dir t "^[^.]"))
+ (ess-tmp-return (ess-find-exec-completions ess-root-arg ess-root-dir))
+ (ess-tmp-dir nil))
+
+ (while ess-tmp-dirs
+ (setq ess-tmp-dir (car ess-tmp-dirs)
+ ess-tmp-dirs (cdr ess-tmp-dirs))
+ (if (file-accessible-directory-p ess-tmp-dir)
+ (setq ess-tmp-return
+ (nconc ess-tmp-return
+ (ess-find-exec ess-root-arg ess-tmp-dir)))))
+ ess-tmp-return))
+
+(defun ess-find-exec-completions (ess-root-arg &optional ess-exec-dir)
+ "Given the root of an executable file name, find all possible completions.
+Search for the executables in ESS-EXEC-DIR (which defaults to
+`exec-path' if no value is given)."
+ (let* ((ess-exec-path
+ (if ess-exec-dir (ess-return-list ess-exec-dir) exec-path))
+ (ess-tmp-exec nil)
+ (ess-tmp-path-count (length ess-exec-path))
+ (ess-tmp-dir nil)
+ (ess-tmp-files nil)
+ (ess-tmp-file nil))
+
+ (while ess-exec-path
+ (setq ess-tmp-dir (car ess-exec-path)
+ ess-exec-path (cdr ess-exec-path))
+ (when
+ (and (> (length ess-tmp-dir) 0)
+ (file-accessible-directory-p ess-tmp-dir))
+ ;; the first test above excludes "" from exec-path, which can be
+ ;; problematic with Tramp.
+ (setq ess-tmp-files
+ (file-name-all-completions ess-root-arg ess-tmp-dir))
+
+ (while ess-tmp-files
+ (setq ess-tmp-file
+ (concat (file-name-as-directory ess-tmp-dir)
+ (car ess-tmp-files))
+ ess-tmp-files (cdr ess-tmp-files))
+ (if (and (file-executable-p ess-tmp-file)
+ (not (backup-file-name-p ess-tmp-file))
+ (not (file-directory-p ess-tmp-file)))
+ ;; we have found a possible executable, so keep it.
+ (setq ess-tmp-exec
+ (nconc ess-tmp-exec (list ess-tmp-file)))))))
+ ess-tmp-exec))
+
+(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))
+
+\f
+;;*;; Interaction with inferiors
+
+(defmacro ess-when-new-input (time-var &rest body)
+ "BODY is evaluate only if the value of procss 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 ess-execute-dialect-specific (command &optional prompt &rest args)
+ "Execute dialect specific COMMAND.
+
+-- If command is nil issue warning 'Not available for dialect X'
+-- If command is a elisp function, execute it with ARGS
+-- If a string starting with 'http' or 'www', browse with `browse-url',
+ otherwise execute the command in inferior process.
+-- If a string, interpret as a command to subprocess, and
+ substitute ARGS with `(format ,command ,@args).
+
+When PROMPT is non-nil ask the user for a string value and
+prepend the response to ARGS.
+
+If prompt is a string just pass it to `read-string'. If a list, pass it
+to `ess-completing-read'."
+ `(if (null ,command)
+ (message "Not implemented for dialect %s" ess-dialect)
+ (let* ((com (if (symbolp ,command)
+ (symbol-function ,command)
+ ,command))
+ (prompt ',prompt)
+ (resp (and prompt
+ (if (stringp prompt)
+ (read-string prompt)
+ (apply 'ess-completing-read prompt))))
+ (args (append (list resp) ',args)))
+ (cond ((functionp com)
+ (apply com args))
+ ((and (stringp com)
+ (string-match "^\\(http\\|www\\)" com))
+ (setq com (apply 'format com args))
+ (require 'browse-url)
+ (browse-url com))
+ ((stringp com)
+ (unless (string-match "\n$" com)
+ (setq com (concat com "\n")))
+ (setq com (apply 'format com args))
+ (ess-eval-linewise com))
+ (t
+ (error "Argument COMMAND must be either a function or a string"))))))
+
+(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 initialise it in
+`ess-mode-hook' or `ess-post-run-hook', or one of the more
+specialised 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'."
+ ;; (while-no-input
+ (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'.")
+
+\f
+;;*;; Emacs Integration
+
+;;;*;;; Menus
+
+(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 (if (derived-mode-p 'ess-mode)
+ ess-font-lock-keywords
+ ;; also in transcript mode
+ inferior-ess-font-lock-keywords)))
+ (if (and (symbolp sym)
+ (custom-variable-p sym))
+ (cons
+ (eval (car (get sym 'standard-value)))
+ (symbol-value sym))
+ (error "(inferior-)`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' and `inferior-ess-font-lock-keywords'
+should hold 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 (&optional keyword)
+ (interactive)
+ (let* ((values (ess--fl-keywords-values))
+ (keyword (or keyword
+ (if (called-interactively-p 'any)
+ (intern (ess-completing-read
+ "Keyword to toggle"
+ (mapcar (lambda (el) (symbol-name (car el)))
+ (car values))
+ nil t))
+ (error "Wrong number of arguments"))))
+ (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 (if (derived-mode-p 'ess-mode)
+ ess-font-lock-keywords
+ inferior-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 in MENU."
+ (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 (if (derived-mode-p 'ess-mode)
+ ess-font-lock-keywords
+ inferior-ess-font-lock-keywords)
+ (ess--extract-fl-keywords)))
+ t])))
+
+
+;;;*;;; External modes
+
+(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
+arguments is as in `completing-read' (PROMPT is automatically
+suffixed with ': ' and (default %s) when needed). If HIST
+is null use `ess--completing-hist' as history.
+
+See also `ess-use-ido'."
+ (let ((use-ido (and ess-use-ido (featurep 'ido))))
+ (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
+ ;; Can remove this call when we drop support for Emacs
+ ;; < 25.1, as it is aliased to ignore then
+ (ido-init-completion-maps)
+ (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-load-extras (&optional inferior)
+ "Load all the extra features depending on custom settings."
+
+ (let ((mode (if inferior 'inferior-ess-mode 'ess-mode))
+ (isR (string-match "^R" ess-dialect)))
+
+ ;; auto-complete
+ (when (and (boundp 'ac-sources)
+ (if inferior
+ (eq ess-use-auto-complete t)
+ ess-use-auto-complete))
+ (add-to-list 'ac-modes mode)
+ ;; files should be in front; ugly, but needed
+ (when ess-ac-sources
+ (setq ac-sources
+ (delq 'ac-source-filename ac-sources))
+ (mapc (lambda (el) (add-to-list 'ac-sources el))
+ ess-ac-sources)
+ (add-to-list 'ac-sources 'ac-source-filename)))
+
+ ;; company
+ (when (and (boundp 'company-backends)
+ (if inferior
+ (eq ess-use-company t)
+ ess-use-company))
+ (when ess-company-backends
+ (set (make-local-variable 'company-backends)
+ (cl-copy-list (append ess-company-backends company-backends)))
+ (delq 'company-capf company-backends)))
+
+ ;; eldoc)
+ (require 'eldoc)
+ (when (and ess-eldoc-function ;; if mode provide this, it suports eldoc
+ (or (and (not inferior) ess-use-eldoc)
+ (and inferior (eq ess-use-eldoc t))))
+ (when (> eldoc-idle-delay 0.4) ;; default is too slow for paren help
+ (set (make-local-variable 'eldoc-idle-delay) 0.1))
+ (set (make-local-variable 'eldoc-documentation-function) ess-eldoc-function)
+ (eldoc-mode 1))
+
+ ;; tracebug
+ (when (and ess-use-tracebug inferior isR (fboundp 'ess-tracebug))
+ (ess-tracebug 1))))
+
+(defmacro ess--execute-electric-command (map &optional prompt wait exit-form &rest args)
+ "Execute single-key comands defined in MAP till a key is pressed which is not part of map.
+
+Return the value of the lastly executed command.
+
+Single-key input commands are those that once executed do not
+requre the prefix command for subsequent invocation.
+
+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)))
+
+(defvar ess-build-tags-command nil
+ "Command passed to generate tags.
+
+If nil, `ess-build-tags-for-directory' uses the mode's imenu
+regexpresion. Othersiwe, it should be a string with two %s
+formats: one for directory and another for the output file.")
+
+;;;*;;; 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 C-u C-u C-y."
+ (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)
+ "With double prefix ARG (C-u C-u) 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 (or imenu-generic-expression ess-imenu-generic-expression) ;; need both!!
+ (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!")))))
+
+
+;;;*;;; System
+
+;; trying different viewers; thanks to an original patch for
+;; ess-swv.el from Leo <sdlNOSPAMweb.de> :
+(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))
+
+\f
+;;*;; 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)
+ (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 ()
+ (cond ((and (featurep 'evil) (bound-and-true-p evil-mode))
+ (when (evil-visual-state-p)
+ (evil-normal-state)))
+ (mark-active
+ (deactivate-mark))))
+
+;; SJE: 2009-01-30 -- this contribution from
+;; Erik Iverson <iversonNOSPAMbiostat.wisc.edu>
+
+(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 acknowledgement, 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) '-)
+ (- (x-display-pixel-width) (car (cdr fx)) fw)
+ (car (cdr fx)))))
+
+ (setq frame-top (if (not (consp fy))
+ fy
+ (if (eq (car fy) '-)
+ (- (x-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)))
+
+(defun ess-do-auto-fill ()
+ "This is the same as \\[do-auto-fill] in GNU emacs 21.3, with one major
+difference: if we could not find a suitable place to break the line,
+we simply do not break it (instead of breaking after the first word)."
+ (let (fc justify bol give-up
+ (fill-prefix fill-prefix))
+ (if (or (not (setq justify (current-justification)))
+ (null (setq fc (current-fill-column)))
+ (and (eq justify 'left)
+ (<= (current-column) fc))
+ (save-excursion (beginning-of-line)
+ (setq bol (point))
+ (and auto-fill-inhibit-regexp
+ (looking-at auto-fill-inhibit-regexp))))
+ nil ;; Auto-filling not required
+ (if (memq justify '(full center right))
+ (save-excursion (unjustify-current-line)))
+
+ ;; Choose a fill-prefix automatically.
+ (if (and adaptive-fill-mode
+ (or (null fill-prefix) (string= fill-prefix "")))
+ (let ((prefix
+ (fill-context-prefix
+ (save-excursion (backward-paragraph 1) (point))
+ (save-excursion (forward-paragraph 1) (point)))))
+ (and prefix (not (equal prefix ""))
+ (setq fill-prefix prefix))))
+
+ (while (and (not give-up) (> (current-column) fc))
+ ;; Determine where to split the line.
+ (let* (after-prefix
+ (fill-point
+ (let ((opoint (point))
+ bounce
+ (first t))
+ (save-excursion
+ (beginning-of-line)
+ (setq after-prefix (point))
+ (and fill-prefix
+ (looking-at (regexp-quote fill-prefix))
+ (setq after-prefix (match-end 0)))
+ (move-to-column (1+ fc))
+ ;; Move back to the point where we can break the line.
+ ;; We break the line between word or
+ ;; after/before the character which has character
+ ;; category `|'. We search space, \c| followed by
+ ;; a character, or \c| following a character. If
+ ;; not found, place the point at beginning of line.
+ (while (or first
+ ;; If this is after period and a single space,
+ ;; move back once more--we don't want to break
+ ;; the line there and make it look like a
+ ;; sentence end.
+ (and (not (bobp))
+ (not bounce)
+ sentence-end-double-space
+ (save-excursion (forward-char -1)
+ (and (looking-at "\\. ")
+ (not (looking-at "\\. ")))))
+ (and (not (bobp))
+ (not bounce)
+ fill-nobreak-predicate
+ (funcall fill-nobreak-predicate)))
+ (setq first nil)
+ (re-search-backward "[ \t]\\|\\c|.\\|.\\c|\\|^")
+ ;; If we find nowhere on the line to break it,
+ ;; do not break it. Set bounce to t
+ ;; so we will not keep going in this while loop.
+ (if (<= (point) after-prefix)
+ (setq bounce t)
+ (if (looking-at "[ \t]")
+ ;; Break the line at word boundary.
+ (skip-chars-backward " \t")
+ ;; Break the line after/before \c|.
+ (forward-char 1))))
+ (if enable-multibyte-characters
+ ;; If we are going to break the line after or
+ ;; before a non-ascii character, we may have
+ ;; to run a special function for the charset
+ ;; of the character to find the correct break
+ ;; point.
+ (if (not (and (eq (charset-after (1- (point))) 'ascii)
+ (eq (charset-after (point)) 'ascii)))
+ (fill-find-break-point after-prefix)))
+
+ ;; Let fill-point be set to the place where we end up.
+ ;; But move back before any whitespace here.
+ (skip-chars-backward " \t")
+ (point)))))
+
+ ;; See whether the place we found is any good.
+ (if (save-excursion
+ (goto-char fill-point)
+ (and (not (bolp))
+ ;; There is no use breaking at end of line.
+ (not (save-excursion (skip-chars-forward " ") (eolp)))
+ ;; It is futile to split at the end of the prefix
+ ;; since we would just insert the prefix again.
+ (not (and after-prefix (<= (point) after-prefix)))
+ ;; Don't split right after a comment starter
+ ;; since we would just make another comment starter.
+ (not (and comment-start-skip
+ (let ((limit (point)))
+ (beginning-of-line)
+ (and (re-search-forward comment-start-skip
+ limit t)
+ (eq (point) limit)))))))
+ ;; Ok, we have a useful place to break the line. Do it.
+ (let ((prev-column (current-column)))
+ ;; If point is at the fill-point, do not `save-excursion'.
+ ;; Otherwise, if a comment prefix or fill-prefix is inserted,
+ ;; point will end up before it rather than after it.
+ (if (save-excursion
+ (skip-chars-backward " \t")
+ (= (point) fill-point))
+ (funcall comment-line-break-function t)
+ (save-excursion
+ (goto-char fill-point)
+ (funcall comment-line-break-function t)))
+ ;; Now do justification, if required
+ (if (not (eq justify 'left))
+ (save-excursion
+ (end-of-line 0)
+ (justify-current-line justify nil t)))
+ ;; If making the new line didn't reduce the hpos of
+ ;; the end of the line, then give up now;
+ ;; trying again will not help.
+ (if (>= (current-column) prev-column)
+ (setq give-up t)))
+ ;; No good place to break => stop trying.
+ (setq give-up t))))
+ ;; Justify last line.
+ (justify-current-line justify t t)
+ t)))
+
+\f
+;;*;; Syntax
+
+(defun ess-containing-sexp-position ()
+ (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.")
+
+(let* ((Q "\\s\"") ; quote
+ (repl "\\(<-\\)?") ; replacement (function)
+ (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.
+ (_or_ "\\)\\|\\(") ; OR
+ (space "\\(\\s-\\|\n\\)*") ; white space
+
+ (part-1 (concat
+ "\\(" ;;--------outer Either-------
+ "\\(\\(" ; EITHER
+ Q xSymb Q ; any function name between quotes
+ _or_
+ "\\(^\\|[ ]\\)" 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
+ )))
+
+ (defvar ess-r-function-pattern
+ (concat part-1
+ "\\s-*\\(<-\\|=\\)" ; whitespace, assign
+ part-2)
+ "The regular expression for matching the beginning of an R function.")
+
+ (defvar ess-s-function-pattern
+ (concat part-1
+ "\\s-*\\(<-\\|_\\|=\\)" ; whitespace, assign (incl. "_")
+ part-2)
+ "The regular expression for matching the beginning of an S function."))
+
+
+(defvar ess--fn-name-start-cache nil)
+
+(defun ess--fn-name-start (&optional look-back)
+ "Return (FN-NAME . START-POS).
+FN-NAME is a function name located before the pointer. START-POS
+is the position where FN-NAME starts. LOOK-BACK is a number of
+characters to look back; defaults to 2000. 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 functon
+ (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-beginning-of-function (&optional no-error)
+ "Leave (and return) the point at the beginning of the current ESS function.
+If the optional argument NO-ERROR is non-nil, the function returns nil when
+it cannot find a function beginning."
+ ;; FIXME: should not throw error in accordance with beginning-of-defun and
+ ;; beginning-of-defun-function specification
+ ;; FIXME: should __WORK__ in the crucial case: large function w/ internal function defs
+ (interactive)
+ (let ((init-point (point))
+ (in-set-S4 nil)
+ beg end done)
+
+ ;; Note that we must be sure that we are past the 'function (' text,
+ ;; such that ess-function-pattern is found in BACKwards later.
+ ;; In case we're sitting in a function or setMethod() header,
+ ;; we need to move further.
+ ;; But not too far! {wrongly getting into next function}
+ (if (search-forward "("
+ (ess-line-end-position 2) t) ; at most end of next line
+ (forward-char 1))
+ ;; TODO: replace the above by hopefully more sucessful logic:
+ ;; 1. If we have 'function *(' in the same line, move to end of that line
+ ;; 2. if *not*, skip all comment lines (concat space comment-char .* "\n")
+ ;; and only* then do something like the
+ ;; (search-forward '(' .. (..line-end.. 2) ) above
+
+ (setq end (point)) ; = init-point when nothing found
+
+ (ess-write-to-dribble-buffer
+ (format "ess-BEG-of-fun after 'search-FWD (': Ini-pt %d, (p)-Ini-pt = %d\n"
+ init-point (- end init-point)))
+ (if (and (> end 1)
+ (re-search-backward ;; in case of setMethod() etc ..
+ ess-r-set-function-start
+ ;; at most 1 line earlier {2 is too much: finds previous sometimes}
+ (+ 1 (ess-line-end-position -1)) t))
+
+ (progn ;; yes we *have* an S4 setMethod(..)-like
+ (setq in-set-S4 t
+ beg (point))
+ (ess-write-to-dribble-buffer
+ (format " set*() function start at position %d" beg))
+ ;; often need to move even further to have 'function(' to our left
+ ;; (if (search-forward "function" end t)
+ ;; (ess-write-to-dribble-buffer
+ ;; (format " -> 'function' already at pos %d\n" (point)))
+ ;; ;; else need to move further
+ (goto-char end)
+ ;; search 4 lines, we are pretty sure now:
+ (search-forward
+ "function" (ess-line-end-position 4) t)
+ ;; )
+ (search-forward "(" (ess-line-end-position) t))
+ ;; else: regular function; no set*Method(..)
+ (ess-write-to-dribble-buffer "ELSE not in setMethod() header ...\n"))
+
+ (while (not done)
+ ;; Need this while loop to skip over local function definitions
+
+ ;; In the case of non-success, it is inefficiently
+ ;; going back in the buffer through all function definitions...
+ (unless
+ (and (re-search-backward ess-function-pattern (point-min) t)
+ (not (ess-inside-string-or-comment-p (point))))
+ (goto-char init-point)
+ (if no-error
+ (setq done t beg nil)
+ ;; else [default]:
+ (error "Point is not in a function according to 'ess-function-pattern'")))
+ (unless done
+ (setq beg (point))
+ (ess-write-to-dribble-buffer
+ (format "\tMatch,Pt:(%d,%d),%d\n"
+ (match-beginning 0) (match-end 0) beg))
+ (setq in-set-S4 (looking-at ess-r-set-function-start))
+ (forward-list 1) ; get over arguments
+
+ ;; The following used to bomb "Unbalanced parentheses", n1, n2
+ ;; when the above (search-forward "(" ..) wasn't delimited :
+ (unless in-set-S4 (forward-sexp 1)) ; move over braces
+ ;;DBG (ess-write-to-dribble-buffer "|")
+ (setq end (point))
+ (goto-char beg)
+ ;; current function must begin and end around point
+ (setq done (and (>= end init-point) (<= beg init-point)))))
+ beg))
+
+(defun ess-end-of-function (&optional beginning no-error)
+ "Leave the point at the end of the current ESS function.
+Optional argument for location of BEGINNING. Return '(beg end)."
+ (interactive)
+ (if beginning
+ (goto-char beginning)
+ (setq beginning (ess-beginning-of-function no-error)))
+ (if beginning
+ ;; *hack* only for S (R || S+): are we in setMethod(..) etc?
+ (let ((in-set-S4 (looking-at ess-r-set-function-start))
+ (end-pos) (npos))
+ (ess-write-to-dribble-buffer
+ (format "ess-END-of-fun: S4=%s, beginning = %d\n" in-set-S4 beginning))
+ (forward-list 1) ; get over arguments || whole set*(..)
+ (unless in-set-S4 (forward-sexp 1)) ; move over braces
+ (ess-write-to-dribble-buffer
+ (format "ess-END-of-fun: found #1 : %d\n" (point)))
+
+ ;; For one-line functions withOUT '{ .. }' body -- added 2008-07-23 --
+ ;; particularly helpful for C-c C-c (ess-eval-function-or-paragraph-and-step):
+ (setq end-pos (ess-line-end-position))
+ (while (< (point) end-pos) ; if not at end of line, move further forward
+ (goto-char ;; careful not to move too far; e.g. *not* over empty lines:
+ (min (save-excursion (forward-sexp 1) (point))
+ (save-excursion (forward-paragraph 1) (point)))))
+ (list beginning (point)))
+ ;; else: 'no-error': we are not in a function
+ 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
+ ess-mode-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
+ ess-mode-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)))
+
+\f
+;;*;; String manipulation
+
+(defun ess-quote-special-chars (string)
+ (replace-regexp-in-string
+ "\"" "\\\\\\&"
+ (replace-regexp-in-string ;; replace backslashes
+ "\\\\" "\\\\" string nil t)))
+
+;; simple alternative to ess-read-object-name-default of ./ess-inf.el :
+;; is "wrongly" returning "p1" for word "p1.part2" :
+(defun ess-extract-word-name ()
+ "Get the word you're on (cheap algorithm).
+Use `ess-read-object-name-default' for a better but slower
+version."
+ (save-excursion
+ (re-search-forward "\\<\\w+\\>" nil t)
+ (buffer-substring (match-beginning 0) (match-end 0))))
+
+(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)
+ ;;or (if verbose (setq pl (append pl (list p))))
+ )))
+ ;;or (if (and verbose pl)
+ ;;or (message "s/%s/%s/ at %s" regexp to-string pl))
+ ) )
+
+(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 occurences 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."
+ (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: friedmanNOSPAMgnu.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))
+
+\f
+;;*;; 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))))
+
+(defvar ess-adjust-chunk-faces t
+ "Whether to adjust background color in code chunks.")
+
+(defvar-local ess-buffer-has-chunks nil
+ "Internal usage: indicates whether a buffer has chunks.
+This is used to make face adjustment a no-op when a buffer does
+not contain chunks.")
+
+(defvar ess-adjust-face-intensity 2
+ "Default intensity for adjusting faces.")
+
+(defun ess-adjust-face-background (start end &optional intensity)
+ "Adjust face background between START and END.
+On dark background, lighten. Oposite on light."
+ (let* ((intensity (or intensity ess-adjust-face-intensity))
+ (color (color-lighten-name
+ (face-background 'default)
+ (if (eq (frame-parameter nil 'background-mode) 'light)
+ (- intensity)
+ intensity)))
+ (face (list (cons 'background-color color))))
+ (with-silent-modifications
+ (ess-adjust-face-properties start end 'face face))))
+
+;; Taken from font-lock.el.
+(defun ess-adjust-face-properties (start end prop value)
+ "Tweaked `font-lock-prepend-text-property'.
+Adds the `ess-face-adjusted' property so we only adjust face once."
+ (let ((val (if (listp value) value (list value))) next prev)
+ (while (/= start end)
+ (setq next (next-single-property-change start prop nil end)
+ prev (get-text-property start prop))
+ ;; Canonicalize old forms of face property.
+ (and (memq prop '(face font-lock-face))
+ (listp prev)
+ (or (keywordp (car prev))
+ (memq (car prev) '(foreground-color background-color)))
+ (setq prev (list prev)))
+ (add-text-properties start next
+ (list prop (append val (if (listp prev) prev (list prev)))
+ 'ess-face-adjusted t))
+ (setq start next))))
+
+(defun ess-find-overlay (pos prop)
+ (cl-some (lambda (overlay)
+ (when (overlay-get overlay prop)
+ overlay))
+ (overlays-at pos)))
+
+(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 ess--make-local-vars-permanent
+ (put (car pair) 'permanent-local t))) ;; hack for Rnw
+ alist))
+
+(defun ess-setq-vars-default (alist &optional buf)
+ "Set language variables from ALIST, in buffer BUF, if desired."
+ (when buf (set-buffer buf))
+ (mapc (lambda (pair)
+ (set-default (car pair) (eval (cdr pair))))
+ alist))
+
+(defvar ess-error-regexp "^\\(Syntax error: .*\\) at line \\([0-9]*\\), file \\(.*\\)$"
+ "Regexp to search for errors.")
+
+(provide 'ess-utils)
+
+;;; ess-utils.el ends here
--- /dev/null
+;;; ess-vst-d.el --- ViSta customization
+
+;; Copyright (C) 1997 A. J. Rossini
+;; Copyright (C) 1997--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMu.washington.edu>
+;; Created: 26 Aug 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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 extends the XLispStat configuration for ViSta.
+
+;;; Code:
+
+;;; Requires and Autoloads:
+
+(require 'ess-custom)
+(require 'ess-lsp-l)
+(require 'ess-utils)
+(require 'ess-inf)
+
+(defvar VST-customize-alist
+ '((ess-customize-alist . VST-customize-alist )
+ (ess-language . "XLS" )
+ (ess-dialect . "ViSta" )
+ (ess-object-name-db-file . "ess-xls-namedb.el" )
+ (ess-help-sec-regex . " ")
+ (ess-help-sec-keys-alist . " ")
+ (inferior-ess-primary-prompt . "> ?" )
+ (comint-use-prompt-regexp . t)
+ (inferior-ess-program . inferior-VST-program)
+ (inferior-ess-help-command . "(help '%s)\n" )
+ (inferior-ess-objects-command . "(variables)\n" )
+ (inferior-ess-exit-command . "(exit)\n" )
+ (inferior-ess-start-file . nil) ;"~/.ess-VST")
+ ;;(inferior-ess-start-args . nil)
+ )
+ "Variables to customize for XLS.")
+
+
+(defun VST-mode (&optional proc-name)
+ "Major mode for editing ViSta source. NOT EVEN STARTED."
+ (interactive)
+ (setq ess-customize-alist VST-customize-alist)
+ (lisp-mode))
+
+
+(defun ViSta ()
+ "Call 'ViSta', the extend XLispStat statistical system, from Forrest Young."
+
+ (interactive)
+ (setq ess-customize-alist VST-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "(ViSta): ess-dialect=%s , buf=%s\n"
+ ess-dialect (current-buffer)))
+ (inferior-ess))
+
+\f ; Provide package
+
+(provide 'ess-vst-d)
+
+;;; ess-vst-d.el ends here
--- /dev/null
+;;; ess-xls-d.el --- XLispStat customization for ESS.
+
+;; Copyright (C) 1997 A. J. Rossini
+;; Copyright (C) 1998--2004 A.J. Rossini, Richard M. Heiberger, Martin
+;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
+
+;; Author: A.J. Rossini <rossiniNOSPAMstat.sc.edu>
+;; Created: 12 Jun 1997
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; Keywords: statistics, 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 XLispStat customizations for ESS. See
+;; ess-lsp-l.el for general Lisp modifications.
+
+;;; Code:
+
+;;; Requires and Autoloads:
+
+(require 'ess-custom)
+(require 'ess-lsp-l)
+(require 'ess-utils)
+(require 'ess-mode)
+(require 'ess-inf)
+(require 'ess-trns)
+
+(defvar ess-help-XLS-sec-keys-alist
+ '((?a . "Args:"))
+ "Sparse online XLS help.")
+
+(defvar XLS-editing-alist Lisp-editing-alist)
+
+(defvar XLS-customize-alist
+ '((ess-local-customize-alist . 'XLS-customize-alist)
+ (ess-language . "XLS" )
+ (ess-dialect . "XLS" )
+ (ess-mode-editing-alist . XLS-editing-alist )
+ (ess-object-name-db-file . "ess-xls-namedb.el" )
+ (ess-help-sec-regex . "^[A-Z. ---]+:$")
+ (ess-help-sec-keys-alist . ess-help-XLS-sec-keys-alist)
+ (inferior-ess-primary-prompt . "> ?" )
+ (inferior-ess-secondary-prompt . "^" )
+ (comint-use-prompt-regexp . t)
+ (inferior-ess-program . inferior-XLS-program)
+ (inferior-ess-help-command . "(help '%s)\n" )
+ (inferior-ess-objects-command . "(variables)\n" )
+ (inferior-ess-exit-command . "(exit)\n" )
+ ;;(inferior-ess-start-args . ""))
+ (inferior-ess-start-file . nil))
+ "Variables to customize for XLS.")
+
+;;; The functions of interest (mode, inferior mode)
+
+;;;###autoload
+(defun XLS-mode (&optional proc-name)
+ "Major mode for editing XLispStat source. NOT EVEN STARTED."
+ (interactive)
+ (setq ess-customize-alist XLS-customize-alist)
+ (ess-mode XLS-customize-alist proc-name)
+ (setq major-mode 'XLS-mode))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.lsp\\'" . XLS-mode))
+
+(fset 'xlispstat-mode 'XLS-mode)
+
+(defun XLS ()
+ "Call 'XLispStat', the Lisp statistical system from Luke Tierney."
+
+ (interactive)
+ (setq ess-customize-alist XLS-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "(XLS): ess-dialect=%s , buf=%s\n"
+ ess-dialect (current-buffer)))
+ (inferior-ess))
+
+(defun xls-transcript-mode ()
+ "Does the right thing."
+ (interactive)
+ (ess-transcript-mode XLS-customize-alist))
+
+(fset 'XLS-transcript-mode 'xls-transcript-mode)
+
+\f ; Provide package
+
+(provide 'ess-xls-d)
+
+;;; ess-xls-d.el ends here
--- /dev/null
+;;; ess.el --- Emacs Speaks Statistics
+;;
+;; Author: David Smith <dsmithNOSPAMstats.adelaide.edu.au>
+;; A.J. Rossini <blindglobeNOSPAMgmail.com>
+;; Richard M. Heiberger <rmhNOSPAMtemple.edu>
+;; Kurt Hornik <Kurt.HornikNOSPAMR-project.org>
+;; Martin Maechler <maechlerNOSPAMstat.math.ethz.ch>
+;; Rodney A. Sparapani <rsparapaNOSPAMmcw.edu>
+;; Stephen Eglen <stephenNOSPAMgnu.org>
+;; Sebastian P. Luque <spluqueNOSPAMgmail.com>
+;; Henning Redestig <henning.redNOSPAMgooglemail.com>
+;; Vitalie Spinu <spinuvitNOSPAMgmail.com>
+;; Lionel Henry <lionel.hryNOSPAMgmail.com>
+;; J. Alexander Branham <alex.branhamNOSPAMgmail.com>
+;;
+;; Maintainer: ESS Core Team <ESS-coreNOSPAMr-project.org>
+;; Copyright (C) 1997-2018 ESS Core Team <ESS-coreNOSPAMr-project.org>
+;; Created: 7 Jan 1994
+;; Version: 18.10.2
+;; Package-Requires: ((julia-mode "0.3"))
+;;
+;; 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:
+
+(eval-when-compile
+ (require 'cl)
+ (require 'cl-lib))
+(require 'ess-custom)
+(require 'ess-utils)
+(require 'ess-generics)
+(require 'ess-inf)
+
+;; FIXME: should this be optional?
+(require 'ess-noweb-mode)
+
+;; Silence the byte compiler
+(declare-function run-ess-r "ess-r-mode")
+(declare-function S+ "ess-sp6w-d")
+(declare-function SAS "ess-sas-d")
+
+\f ; ESS mode
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; In this section:
+;;;;
+;;;; * The major mode ess-mode
+;;;; * Commands for ess-mode
+;;;; * Code evaluation commands
+;;;; * Indenting code and commands
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;*;; Major mode definition
+
+(defvar ess-mode-map
+ (let ((map (make-sparse-keymap)))
+
+ ;; By popular demand:
+ (define-key map (kbd "RET") 'ess-newline-and-indent)
+ (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-<up>") 'ess-eval-buffer-from-beg-to-here)
+ (define-key map (kbd "C-c C-<down>") '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-y" 'ess-switch-to-ESS-deprecated)
+ (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\t" 'ess-complete-object-name-deprecated)
+ (define-key map "\M-?" 'ess-list-object-completions)
+ (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)
+ (with-no-warnings ; Obsolete key variable
+ (when ess-smart-S-assign-key
+ (define-key map ess-smart-S-assign-key 'ess-smart-S-assign)))
+ (define-key map (kbd "C-c C-=") 'ess-cycle-assign)
+ 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
+ ["What is this? (beta)" ess-mouse-me t]
+ ["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-versions-create' 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))
+ "------"
+ ("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]
+ ["Eval chunk" ess-eval-chunk ess-noweb-mode]
+ ["Eval chunk and step" ess-eval-chunk-and-step ess-noweb-mode]
+ ["Eval thread" ess-eval-thread ess-noweb-mode]
+ ["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]
+ ["Eval chunk" ess-eval-chunk-and-go ess-noweb-mode]
+ ["Eval thread" ess-eval-thread-and-go ess-noweb-mode]
+ ["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
+(defun ess-mode (&optional alist proc-name is-derived)
+ "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}
+
+Extra binding to note: 'ESC C-\\' indent-region.
+
+Entry to this mode runs the hooks in ess-mode-hook.
+
+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-beginning-of-function' and `ess-end-of-function' move the point to
+ the beginning and end of the current ESS function.
+ `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-tab-always-indent'
+ Non-nil means TAB in ESS mode should always reindent the current line,
+ regardless of where in the line point is when the TAB command is used.
+ `ess-auto-newline'
+ Non-nil means automatically newline before and after braces inserted in S
+ code.
+ `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. At present, predefined style are `BSD', `GNU', `K&R', `C++',
+`CLB' (quoted from C language style)."
+ (setq alist (or alist
+ (buffer-local-value 'ess-local-customize-alist (current-buffer))
+ (error "Customise alist is not specified, nor ess-local-customize-alist is set")))
+ (unless is-derived
+ (kill-all-local-variables)) ;; NOTICE THIS! *** NOTICE THIS! *** NOTICE THIS! ***
+ (ess-setq-vars-local alist)
+ (ess-write-to-dribble-buffer
+ (format "(ess-mode-1): ess-language=%s, ess-dialect=%s buf=%s \n"
+ ess-language
+ ess-dialect
+ (current-buffer)))
+ ;; (ess-write-to-dribble-buffer
+ ;; (format "(ess-mode-1.2): ess-process=%s \n"
+ ;; (ess-local-process-name ess-local-process-name "none")))
+ (ess-write-to-dribble-buffer
+ (format "(ess-mode-1.5): alist=%s \n" alist))
+ (unless is-derived
+ (setq major-mode 'ess-mode)
+ (setq mode-name (concat "ESS[" (or ess-dialect ess-language) "]")))
+ ;; The following line does the next 20 or so :-).
+ (ess-write-to-dribble-buffer
+ (format "(ess-mode-1.6): editing-alist=%s \n"
+ ess-mode-editing-alist))
+ (ess-setq-vars-local ess-mode-editing-alist)
+
+ (ess-set-style ess-style t)
+ (use-local-map ess-mode-map)
+ (when ess-mode-syntax-table
+ (set-syntax-table ess-mode-syntax-table))
+
+ ;; Keep <tabs> out of the code.
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+
+ (put 'ess-local-process-name 'permanent-local t) ; protect from RCS
+ (setq mode-line-process
+ '(" ["
+ (:eval (ess--get-mode-line-indicator))
+ ess--local-mode-line-process-indicator
+ "]"))
+ ;; completion
+ (add-hook 'comint-dynamic-complete-functions 'ess-complete-filename nil 'local)
+ (delq t comint-dynamic-complete-functions)
+ (set (make-local-variable 'comint-completion-addsuffix)
+ (cons "/" ""))
+
+ (add-hook 'ess-idle-timer-functions 'ess-synchronize-dirs nil 'local)
+ (ess-load-extras)
+ (run-mode-hooks 'prog-mode-hook)
+ (run-mode-hooks 'ess-mode-hook)
+ (ess-write-to-dribble-buffer "\nFinished setting up ESS-mode.\n"))
+
+;; Set parent to `prog-mode'
+(put 'ess-mode 'derived-mode-parent 'prog-mode)
+(set-keymap-parent ess-mode-map prog-mode-map)
+
+(defun ess--get-mode-line-indicator ()
+ "Get `ess--mode-line-process-indicator' from process buffer.
+Internal function to be used for dynamic mode-line dysplay 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"))
+
+\f
+;;*;; User commands in ess-mode
+
+;;;*;;; Miscellaneous
+
+(defun ess-install-library ()
+ "Install library/package for current dialect.
+Currently works only for R."
+ (interactive)
+ (cond
+ ((fboundp ess-install-library-function)
+ (funcall ess-install-library-function))
+ (t
+ (error "Sorry, not available for %s" 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)
+ (or (ess-beginning-of-function 'no-error)
+ (backward-paragraph))
+ (point))
+
+(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)
+ (or (ess-end-of-function nil 'no-error)
+ (forward-paragraph))
+ (point))
+
+(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)
+ ;; if point is not in a function, ess-end-of-function catches the error.
+ (save-excursion
+ (widen)
+ (let* ((beg (ess-goto-beginning-of-function-or-para))
+ (end (ess-goto-end-of-function-or-para)))
+ (narrow-to-region beg end))))
+
+(define-obsolete-function-alias 'ess-narrow-to-defun 'ess-narrow-to-defun-or-para "15.09")
+
+(defun ess-newline-and-indent ()
+ "Like `newline-and-indent' but accounts for roxygen comments."
+ (interactive)
+ (cond ((and (fboundp 'ess-roxy-newline-and-indent)
+ (string= ess-dialect "R"))
+ (ess-roxy-newline-and-indent))
+ (t
+ (newline-and-indent))))
+
+(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
+
+(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. When non-nil, QUIET
+suppresses messaging."
+ (interactive)
+ (let ((ess-styles (mapcar 'symbol-name (mapcar 'car ess-style-alist))))
+ (unless style
+ (setq style
+ (intern (ess-completing-read "Set ESS mode indentation style"
+ ess-styles nil t nil nil ess-default-style))))
+ (setq style (or style ess-style))
+ (make-local-variable 'ess-style)
+ (if (memq (symbol-name style) ess-styles)
+ (setq ess-style style)
+ (error (format "Bad ESS style: %s" style)))
+ (if (not quiet)
+ (message "ESS-style: %s" ess-style))
+ ;; finally, set the indentation style variables making each one local
+ (mapc (lambda (ess-style-pair)
+ (make-local-variable (car ess-style-pair))
+ (set (car ess-style-pair)
+ (cdr ess-style-pair)))
+ (cdr (assq ess-style ess-style-alist)))
+ ess-style))
+
+;; FIXME: Move into ess-indent-or-complete, indentation functions are overly
+;; scattered around
+(defun ess-indent-command (&optional whole-exp)
+ "Indent current line as ESS code, or in some cases insert a tab character.
+If `ess-tab-always-indent' is non-nil (the default), 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.
+A numeric argument, regardless of its value, 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."
+ (interactive "P")
+ (if whole-exp
+ ;; If arg, always indent this line as S
+ ;; and shift remaining lines of expression the same amount.
+ (let ((shift-amt (ess-indent-line))
+ beg end)
+ (save-excursion
+ (if ess-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)))
+ (if (and (not ess-tab-always-indent)
+ (save-excursion
+ (skip-chars-backward " \t")
+ (not (bolp))))
+ (insert-tab)
+ ;; call ess-indent-line
+ (funcall indent-line-function))))
+
+(defun ess-indent-or-complete ()
+ "When region is selected indent the region.
+Otherwise, if `ess-tab-complete-in-script' is non-nil, try to
+indent, if code is already indented, complete instead.
+
+The default of `ess-tab-complete-in-script' is nil. Also see
+`ess-first-tab-never-complete'."
+ (interactive)
+ (if (use-region-p)
+ (indent-region (region-beginning) (region-end))
+ (let ((shift (ess-indent-command)))
+ (when (and ess-tab-complete-in-script
+ (numberp shift) ;; can be nil if ess-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."
+ ;; fixme: make this work with standard indent-line-function
+ (cond ((fboundp ess-indent-line-function)
+ (funcall ess-indent-line-function))
+ ;; else S and R default behavior
+ ((fboundp 'ess-r-indent-line)
+ (ess-r-indent-line))
+ ;; fallback on Emacs
+ (t (funcall indent-line-function))))
+
+\f
+;;*;; Creating and manipulating dump buffers
+;;;###autoload
+(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-customize-alist)
+ (apply ess-source-directory nil)))))
+ (filename (concat dirname (format ess-dump-filename-template object)))
+ (old-buff (get-file-buffer filename)))
+
+ ;; If the directory doesn't exist, offer to create it
+ (if (file-exists-p (directory-file-name dirname)) nil
+ (if (y-or-n-p ; Approved
+ (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
+
+ (if current-prefix-arg
+ (ess-dump-object object filename)
+ (if old-buff
+ (progn
+ (pop-to-buffer old-buff)
+ (message "Popped to edit buffer."))
+ ;; No current buffer containing desired file
+ (if (file-exists-p filename)
+ (progn
+ (ess-find-dump-file-other-window filename)
+ (message "Read %s" filename))
+ ;; No buffer and no file
+ (ess-dump-object object filename))))))
+
+(ess-defgeneric ess-dump-object (object filename)
+ "Dump the ESS object OBJECT into file FILENAME."
+ (let ((complete-dump-command (format inferior-ess-dump-command
+ object filename)))
+ (if (file-writable-p filename) nil
+ (error "Can't dump %s as %f is not writeable" object filename))
+
+ (:override
+ ;; Make sure we start fresh
+ (when (get-file-buffer filename)
+ (kill-buffer (get-file-buffer filename)))
+
+ (ess-command complete-dump-command)
+ (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."
+
+ (if (file-exists-p filename) nil
+ (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)
+ (ess-mode ess-customize-alist)
+
+ (auto-save-mode 1) ; Auto save in this buffer
+ (setq ess-local-process-name ess-current-process-name)
+
+ (if ess-function-template
+ (progn
+ (goto-char (point-max))
+ (if (re-search-backward ess-dumped-missing-re nil t)
+ (progn
+ (replace-match ess-function-template t t)
+ (set-buffer-modified-p nil) ; Don't offer to save if killed now
+ (goto-char (point-min))
+ (condition-case nil
+ ;; This may fail if there are no opens
+ (down-list 1)
+ (error nil)))))))
+
+(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."
+ (lexical-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))))))))
+;;;###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(<from source>) 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 "<unknown>"))
+ (concat ess-version " [" ess-revision "]")))
+
+
+(provide 'ess)
+
+;;; ess.el ends here
--- /dev/null
+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
+******************************
+
+\1f
+File: ess.info, Node: Top, Next: Introduction, Up: (dir)
+
+ESS: Emacs Speaks Statistics
+****************************
+
+ESS version 18.10.2
+
+ 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::
+
+\1f
+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 mods 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
+
+\1f
+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
+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 <https://www.gnu.org/philosophy/free-sw.html>.
+
+* Menu:
+
+* Current Features::
+
+\1f
+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::.
+
+\1f
+File: ess.info, Node: New features, Next: Credits, Prev: Features, Up: Introduction
+
+1.2 New features in ESS
+=======================
+
+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" <ess-config-here>)' 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 invokations
+ 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 commond 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 insterting 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 initialisation 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 recognised when
+ they are function definitions or function calls.
+ * ESS[R]: Backquoted names and '%op%' operators are recognised 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
+
+\1f
+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:blindglobeNOSPAMgmail.com)
+ * Richard M. Heiberger (mailto:rmhNOSPAMtemple.edu)
+ * Kurt Hornik (mailto:Kurt.HornikNOSPAMR-project.org)
+ * Martin Maechler (mailto:maechlerNOSPAMstat.math.ethz.ch)
+ * Rodney A. Sparapani (mailto:rsparapaNOSPAMmcw.edu)
+ * Stephen Eglen (mailto:stephenNOSPAMgnu.org)
+ * Sebastian P. Luque (mailto:spluque@gmail.com)
+ * Henning Redestig (mailto:henning.redNOSPAMgooglemail.com)
+ * Vitalie Spinu (mailto:spinuvitNOSPAMgmail.com)
+ * Lionel Henry (mailto:lionel.hryNOSPAMgmail.com)
+ * J. Alexander Branham (mailto:alex.branhamNOSPAMgmail.com)
+
+\1f
+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-<chr>'
+means hold the CONTROL key while typing the character <chr>. 'M-<chr>'
+means hold the META key (usually ALT) down while typing <chr>. If there
+is no META, EDIT or ALT key, instead press and release the ESC key and
+then type <chr>.
+
+ 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.
+
+\1f
+File: ess.info, Node: Installation, Next: Interactive ESS, Prev: Introduction, Up: Top
+
+2 Installing ESS on your system
+*******************************
+
+ESS supports GNU Emacs versions 24.3 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::
+
+\1f
+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.
+
+\1f
+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: <https://github.com/emacs-ess/ESS>. '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.
+
+\1f
+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.
+
+\1f
+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'.
+
+\1f
+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::
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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
+ <https://www.splode.com/~friedman/software/emacs-lisp/src/ssh.el>).
+
+ 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.
+
+\1f
+File: ess.info, Node: Customizing startup, 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'.
+
+ 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.
+
+ By default, the new process will be displayed in the same window in
+the current frame. If you wish your iESS process to appear in a
+separate frame, customize the variable 'inferior-ess-own-frame'.
+Alternatively, change 'inferior-ess-same-window' if you wish the process
+to appear within another window of the current frame.
+
+\1f
+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
+
+\1f
+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 <RETURN> 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
+<RETURN> (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.
+
+\1f
+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
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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 <RETURN> 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 <RETURN> 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::.
+
+\1f
+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.
+
+\1f
+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::
+
+\1f
+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.
+
+\1f
+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
+<TAB> 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 <RET> to execute.
+
+ For example, to execute the last command that referenced the variable
+'data', type '!?data SPC TAB RET'.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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::.
+
+\1f
+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-<RET>' 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'.
+
+\1f
+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
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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
+
+\1f
+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'.
+
+\1f
+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.
+
+\1f
+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 `'.
+
+\1f
+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
+ 'ess-tab-complete-in-script' is non-nil. See also
+ 'ess-first-tab-never-complete'.
+
+ -- User Option: ess-tab-complete-in-script
+ If non-'nil', 'TAB' in script buffers tries to complete if there is
+ nothing to indent.
+
+ -- 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 <LINEFEED> key,
+ but <RET> 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
+
+\1f
+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-default-style
+ The default value of 'ess-style'. 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-default-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-default-style'.
+
+ The styles 'DEFAULT' and 'OWN' are initially identical. If you wish
+to edit some of the default values, set 'ess-default-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-default-style 'MINE)' to use your new style.
+
+\1f
+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: <TAB> 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.
+
+\1f
+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'.
+
+\1f
+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.
+
+\1f
+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'.
+
+\1f
+File: ess.info, Node: Completion, Next: Developing with ESS, Prev: Help, Up: Top
+
+9 Completion
+************
+
+* Menu:
+
+* Object names::
+* Function arguments::
+* Minibuffer completion::
+* Auto-complete::
+* Company::
+* Icicles::
+
+\1f
+File: ess.info, Node: Object names, Next: Function arguments, Up: Completion
+
+9.1 Completion of object names
+==============================
+
+The <TAB> key is for completion. The value of the variable
+'ess-first-tab-never-complete' controls when completion is allowed
+controls when completion is allowed to occur. In 'ess-mode' <TAB> 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 <TAB> 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-list-object-completions
+ '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 <TAB> 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.
+
+\1f
+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'.
+
+ A related functionality is *Note ESS ElDoc::, which displays function
+arguments in the echo area whenever the point is inside a function call.
+
+\1f
+File: ess.info, Node: Minibuffer completion, Next: Auto-complete, 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.
+
+\1f
+File: ess.info, Node: Auto-complete, Next: Company, Prev: Minibuffer completion, Up: Completion
+
+9.4 Integration with auto-complete package
+==========================================
+
+ESS provides three sources for 'Auto Completion' mode:
+'ac-source-R-args', 'ac-source-R-objects' and 'ac-source-R'. The last
+one combines the previous two and makes them play nicely together. See
+auto-complete package documentation
+(<http://cx4a.org/software/auto-complete/>) for how to modify and
+install your own completion sources.
+
+ For the default auto-complete ESS configuration, install the latest
+version of 'auto-complete' package. ESS automatically detect the
+package and activates auto-complete in ESS buffers.
+
+ To deactivate AC, place the following into your init file:
+
+ (setq ess-use-auto-complete nil)
+
+ Or, to activate auto-completion only in the 'ess-mode' buffers:
+
+ (setq ess-use-auto-complete 'script-only)
+
+ ESS provides AC help both for arguments and objects (default keys
+'C-?' or '<f1>'). You can bind 'M-h' to display quick help pop-ups:
+
+ (define-key ac-completing-map (kbd "M-h") 'ac-quick-help)
+
+ 'AC' binds 'M-n', and 'M-p' for the navigation in the completion
+menu, which might be inconvenient if you want it to use in the inferior
+R. Bind it to something else:
+
+ (define-key ac-completing-map "\M-n" nil) ;; was ac-next
+ (define-key ac-completing-map "\M-p" nil) ;; was ac-previous
+ (define-key ac-completing-map "\M-," 'ac-next)
+ (define-key ac-completing-map "\M-k" 'ac-previous)
+
+\1f
+File: ess.info, Node: Company, Next: Icicles, Prev: Auto-complete, Up: Completion
+
+9.5 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.
+
+\1f
+File: ess.info, Node: Icicles, Prev: Company, Up: Completion
+
+9.6 Icicles
+===========
+
+Another option for comprehensively handling completion in Emacs is via
+Icicles (<https://www.emacswiki.org/emacs/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'.
+
+\1f
+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
+
+\1f
+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")
+
+\1f
+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'.
+
+\1f
+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
+
+\1f
+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).
+
+ Note that R also accepts Rd files with extension 'rd'; to activate
+ESS[Rd] support for this extension, you may need to add
+
+ (add-to-list 'auto-mode-alist '("\\.rd\\'" . Rd-mode))
+
+to one of your Emacs startup files.
+
+ 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)))
+
+\1f
+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 <http://roxygen.org> 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 for Emacs but not for XEmacs.
+
+ 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'
+ 'move-beginning-of-line' Move to the point directly to the right of
+ the Roxygen start string.
+
+'RET'
+ 'newline-and-indent' Insert a new line and the Roxygen prefix
+ string.
+
+\1f
+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
+<https://cran.r-project.org/doc/manuals/R-ints.html#Namespaces>.
+
+ 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).
+
+\1f
+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
+* Rutils:: R object/package management and help utilities
+* Org:: Interaction with Org mode
+* Sweave and AUCTeX:: Support for Sweave in ESS and AUCTeX
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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)
+
+\1f
+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
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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.)
+
+\1f
+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'.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+File: ess.info, Node: Rdired, Next: Rutils, 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).
+
+\1f
+File: ess.info, Node: Rutils, Next: Org, Prev: Rdired, Up: Extras
+
+11.11 Rutils
+============
+
+Ess-rutils builds up on ess-rdired, providing key bindings for
+performing basic R functions in the inferior-ESS process buffer, such as
+loading and managing packages, object manipulation (listing, viewing,
+and deleting), and alternatives to 'help.start()' and 'RSiteSearch()'
+that use the 'browse-url' Emacs function. The library can be loaded
+using 'M-x load-file', but the easiest is to include:
+
+ (require 'ess-rutils)
+
+ in your Emacs configuration file. Once R is started with 'M-x R',
+and if the value of the customizable variable 'ess-rutils-keys' is true,
+several key bindings become available in iESS process buffers:
+
+ -- Command: ess-rutils-local-pkgs
+ 'C-c C-. l' List all packages in all available libraries.
+
+ -- Command: ess-rutils-repos-pkgs
+ 'C-c C-. r' List available packages from repositories listed by
+ 'getOptions(``repos'')' in the current R session.
+
+ -- Command: ess-rutils-update-pkgs LIB REPOS
+ 'C-c C-. u' Update packages in a particular library LIB and
+ repository REPOS.
+
+ -- Command: ess-rutils-apropos
+ 'C-c C-. a' Search for a string using apropos.
+
+ -- Command: ess-rutils-rm-all
+ 'C-c C-. m' Remove all R objects.
+
+ -- Command: ess-rutils-objs
+ 'C-c C-. o' Manipulate R objects; wrapper for 'ess-rdired'.
+
+ -- 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.
+
+ See the submenu 'Rutils' under the iESS menu for alternative access
+to these functions. The function 'ess-rutils-rsitesearch' is provided
+without a particular key binding. This function is useful in any Emacs
+buffer, so can be bound to a user-defined key:
+
+ (eval-after-load "ess-rutils"
+ '(global-set-key [(control c) (f6)] 'ess-rutils-rsitesearch))
+
+ 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).
+
+\1f
+File: ess.info, Node: Org, Next: Sweave and AUCTeX, Prev: Rutils, Up: Extras
+
+11.12 Interaction with Org mode
+===============================
+
+Org-mode (<https://orgmode.org>) now supports reproducible research and
+literate programming in many languages (including R) - see chapter 14 of
+the Org manual
+(<https://orgmode.org/org.html#Working-With-Source-Code>). 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.)
+
+\1f
+File: ess.info, Node: Sweave and AUCTeX, Prev: Org, Up: Extras
+
+11.13 Support for Sweave in ESS and AUCTeX
+==========================================
+
+ESS provides support for writing and processing Sweave
+(<https://www.statistik.lmu.de/~leisch/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 (<https://www.gnu.org/software/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.
+
+\1f
+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::
+
+\1f
+File: ess.info, Node: ESS(R)--Editing files, Next: iESS(R)--Inferior ESS processes, Prev: ESS for R, 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.
+
+\1f
+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 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-versions'. 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 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.)
+
+ S on Unix systems: If you have "Splus7" on your 'exec-path', it can
+be started using 'M-x Splus7'. By default, ESS will find all
+executables beginning "Splus" on your path. If your versions of S are
+called other names, consider renaming them with a symbolic link or
+change the variable 'ess-s-versions'. To see which functions have been
+created for starting different versions of Splus, type 'M-x Splus' and
+then hit [Tab]. These other versions of Splus can also be started from
+the "ESS->Start Process->Other" menu.
+
+ A second mechanism is also available for running other versions of
+Splus. The variable 'ess-s-versions-list' is a list of lists; each
+sublist should be of the form: (DEFUN-NAME PATH ARGS). DEFUN-NAME is the
+name of the new emacs function you wish to create to start the new S
+process; PATH is the full path to the version of S you want to run; ARGS
+is an optional string of command-line arguments to pass to the S
+process. Here is an example setting:
+ (setq ess-s-versions-list
+ '( ("Splus64" "/usr/local/bin/Splus64")
+ ("Splus64-j" "/usr/local/bin/Splus64" "-j")))
+ which will then allow you to do 'M-x Splus64-j' to start Splus64 with
+the corresponding command line arguments.
+
+ If you change the value of either 'ess-r-versions' or
+'ess-s-versions-list', you should put them in your Emacs configuration
+file before ess-site is loaded, since the new Emacs functions are
+created when ESS is loaded.
+
+ Sqpe (S-Plus running inside an Emacs buffer) on Windows systems: If
+you have an older version of S-Plus (S-Plus 6.1 for example) on your
+system, ir can be started inside an Emacs buffer with 'M-x splus61'. By
+default, ESS will find versions of S-Plus located in the installation
+directories that Insightful uses by default. If your versions of S-Plus
+are anywhere else, you will need to change the variable
+'ess-SHOME-versions'. To see which functions have been created for
+starting different versions of S-Plus, type 'M-x spl' and then hit
+[Tab]. These other versions of S-Plus can also be started from the
+"ESS->Start Process->Other" menu.
+
+\1f
+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)
+
+\1f
+File: ess.info, Node: Example ESS usage, Prev: Philosophies for using ESS(R), Up: ESS for R
+
+12.4 Example ESS usage
+======================
+
+We present some basic examples for using ESS to interact with R These
+are just a subset of approaches, many better approaches are possible.
+Contributions of examples of how you work with ESS are appreciated
+(especially since it helps us determine priorities on future
+enhancements)! Comments as to what should be happening are prefixed by
+"##".
+ 1: ## Data Analysis Example
+ ## Load the file you want to work with
+ C-x C-f myfile.R
+
+ ## Edit as appropriate, then start and switch to an R buffer
+ 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 (prefix with C-c if you have pressed other keys)
+ C-z
+
+ ## Send regions, lines, or the entire file contents to R. For regions,
+ ## highlight a region with keystrokes or mouse and then send with:
+ C-c C-r
+
+ ## Re-edit myfile.R as necessary to correct any difficulties. Add
+ ## new commands here. Send them to R by region with C-c C-r, or
+ ## one line at a time with C-c C-n.
+
+ ## Save the revised myfile.R with C-x C-s.
+
+ ## Save the entire *R* interaction buffer with C-c C-s. You
+ ## will be prompted for a file name. The recommended name is
+ ## myfile.Rout. With this suffix, the file will come up in ESS
+ ## Transcript mode the next time it is accessed from Emacs.
+
+
+
+ 2: ## Program revision example (source code is real)
+
+ ## Start R in a process buffer (this will be *R*)
+ M-x R
+
+ ## Load the file you want to work with
+ C-x C-f myfile.R
+
+ ## edit program, functions, and code in myfile.R, and send revised
+ ## functions to R when ready with
+ C-c C-f
+ ## or highlighted regions with
+ C-c C-r
+ ## or individual lines with
+ C-c C-n
+ ## or load the entire buffer with
+ C-c M-l
+
+ ## save the revised myfile.R when you have finished
+ C-c C-s
+
+
+\1f
+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.
+
+\1f
+File: ess.info, Node: ESS(SAS)--Design philosophy, Next: ESS(SAS)--Editing files, Prev: ESS for SAS, 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.
+
+\1f
+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 <TAB> and <RET>.
+ * 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.
+
+\1f
+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]-<TAB> key
+=======================
+
+Two options. The <TAB> 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 <TAB> 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-<TAB>', 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, <TAB> is bound to 'M-x tab-to-tab-stop'
+and the stops are defined by 'ess-sas-tab-stop-list'.
+
+\1f
+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 (<F3> or <F8>) 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 '~/.xemacs/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 '~/.xemacs/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.
+ <F3> (<F8>)
+ 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.
+ <F8> (<F3>)
+ 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.
+ <F5> (<F6>)
+ Goto the next error message, if any.
+ <F5> (<F6>)
+ Now, 'refresh' the '.lst' and go to it's buffer.
+ <F6> (<F7>)
+ If you wish to make changes, go to the '.sas' file with.
+ <F4> (<F5>)
+ Make your editing changes and submit again.
+ <F3> (<F8>)
+
+\1f
+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
+<F2> <F2> 'refresh'
+ revert the current buffer with the file of the same name if the file is
+ newer than the buffer
+<F3> <F8> '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
+<F4> <F5> 'PROGRAM'
+ switch buffer to '.sas' file
+<F5> <F6> 'LOG'
+ switch buffer to '.log' file, 'refresh' and goto next error message, if
+ any
+<F6> <F7> 'OUTPUT'
+ switch buffer to '.lst' file and 'refresh'
+<F7> <F4> 'filetype-1'
+ switch buffer to 'filetype-1' (defaults to '.txt') file and 'refresh'
+<F8> <F3> 'shell'
+ switch buffer to '*shell*'
+<F9> <F9> 'VIEWTABLE'
+ open an interactive 'PROC FSEDIT' session on the SAS dataset near point
+<F10> <F10> toggle-log
+ toggle ESS[SAS] for '.log' files; useful for certain debugging situations
+<F11> <F11> 'filetype-2'
+ switch buffer to 'filetype-2' (defaults to '.dat') file and 'refresh'
+<F12> <F12> viewgraph
+ open a 'GSASFILE' near point for viewing either in emacs or with an
+ external viewer
+'C-<F1>' 'C-<F1>' rtf-portrait
+ create an MS RTF portrait file from the current buffer with a file
+ extension of '.rtf'
+'C-<F2>' 'C-<F2>' rtf-landscape
+ create an MS RTF landscape file from the current buffer with a file
+ extension of '.rtf'
+'C-<F3>' 'C-<F8>' submit-region
+ write region to 'ess-temp.sas' and submit
+'C-<F5>' 'C-<F6>' append-to-log
+ append 'ess-temp.log' to the current '.log' file
+'C-<F6>' 'C-<F7>' append-to-output
+ append 'ess-temp.lst' to the current '.lst' file
+'C-<F9>' 'C-<F9>' 'INSIGHT'
+ open an interactive 'PROC INSIGHT' session on the SAS dataset near point
+'C-<F10>''C-<F10>'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'.
+
+ <F2> 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 <F11> 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 '~/.xemacs/init.el' file:
+ (setq ess-sas-suffix-1 "csv") ; for example
+
+ <F9> 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-<F9>' 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'.
+
+ <F10> 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.
+
+ <F11> is the same as 'filetype-1' except it is '.dat' by default.
+
+ <F12> 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-<F2>' 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)
+
+\1f
+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::.
+
+\1f
+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.
+
+\1f
+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 <F12>, 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;
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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.
+
+\1f
+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::
+
+\1f
+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'.
+
+\1f
+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 <ESS-bugsNOSPAMr-project.org>,
+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.
+
+\1f
+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 <ess-help-requestNOSPAMr-project.org>; contributions
+to the list may be mailed to <ess-helpNOSPAMr-project.org>. 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 on Emacs and XEmacs.
+ * suggestions for improvements.
+ * announcements of new releases of ESS.
+ * posting small patches to ESS.
+
+\1f
+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
+(<https://www.emacswiki.org>). Please consult them before asking on the
+mailing list about issues that are not specific to ESS.
+
+\1f
+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.
+
+\1f
+File: ess.info, Node: Indices, Prev: Customization, Up: Top
+
+Indices
+*******
+
+* Menu:
+
+* Key index::
+* Function and program index::
+* Variable index::
+* Concept index::
+
+\1f
+File: ess.info, Node: Key index, Next: Function and program index, Up: Indices
+
+Key index
+=========
+
+\0\b[index\0\b]
+* Menu:
+
+* ,: Handy commands. (line 6)
+* {: Indenting. (line 57)
+* }: Indenting. (line 57)
+* C-c C-. a: Rutils. (line 31)
+* C-c C-. d: Rutils. (line 46)
+* C-c C-. H: Rutils. (line 49)
+* C-c C-. l: Rutils. (line 20)
+* C-c C-. m: Rutils. (line 34)
+* C-c C-. o: Rutils. (line 37)
+* C-c C-. r: Rutils. (line 23)
+* C-c C-. s: Rutils. (line 43)
+* C-c C-. u: Rutils. (line 27)
+* C-c C-. w: Rutils. (line 40)
+* 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 64)
+* 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 53)
+* 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 53)
+* M-;: Indenting. (line 69)
+* M-?: Object names. (line 34)
+* M-C-q: Indenting. (line 53)
+* M-n l: Sweave and AUCTeX. (line 16)
+* M-n P: Sweave and AUCTeX. (line 22)
+* M-n s: Sweave and AUCTeX. (line 12)
+* M-RET: Resubmit. (line 10)
+* RET: Command-line editing. (line 10)
+* RET <1>: Resubmit. (line 18)
+* TAB: Indenting. (line 35)
+
+\1f
+File: ess.info, Node: Function and program index, Next: Variable index, Prev: Key index, Up: Indices
+
+Function and program index
+==========================
+
+\0\b[index\0\b]
+* 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 13)
+* 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: Rutils. (line 45)
+* ess-cleanup: Hot keys. (line 71)
+* ess-cleanup <1>: Help. (line 163)
+* 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 56)
+* 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 52)
+* ess-indent-or-complete: Indenting. (line 34)
+* ess-list-object-completions: Object names. (line 33)
+* 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 163)
+* ess-R-complete-object-name: Roxygen. (line 80)
+* 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 53)
+* ess-roxy-hide-all: Roxygen. (line 71)
+* 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-apropos: Rutils. (line 30)
+* ess-rutils-html-docs: Rutils. (line 48)
+* ess-rutils-load-wkspc: Rutils. (line 39)
+* ess-rutils-local-pkgs: Rutils. (line 19)
+* ess-rutils-objs: Rutils. (line 36)
+* ess-rutils-repos-pkgs: Rutils. (line 22)
+* ess-rutils-rm-all: Rutils. (line 33)
+* ess-rutils-rsitesearch: Rutils. (line 58)
+* ess-rutils-save-wkspc: Rutils. (line 42)
+* ess-rutils-update-pkgs: Rutils. (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 15)
+* ess-swv-PDF: Sweave and AUCTeX. (line 21)
+* ess-swv-PS: Sweave and AUCTeX. (line 18)
+* ess-swv-weave: Sweave and AUCTeX. (line 11)
+* 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)
+* move-beginning-of-line: Roxygen. (line 97)
+* newline-and-indent: Roxygen. (line 101)
+* 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 20)
+* source(): Evaluating code. (line 18)
+* source() <1>: Loading. (line 11)
+* STERM: Statistical Process running in ESS?.
+ (line 6)
+
+\1f
+File: ess.info, Node: Variable index, Next: Concept index, Prev: Function and program index, Up: Indices
+
+Variable index
+==============
+
+\0\b[index\0\b]
+* Menu:
+
+* ac-source-R: Auto-complete. (line 6)
+* ac-source-R-args: Auto-complete. (line 6)
+* ac-source-R-objects: Auto-complete. (line 6)
+* 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 30)
+* ess-ask-about-transfile <1>: Saving transcripts. (line 12)
+* ess-ask-for-ess-directory: Customizing startup. (line 7)
+* ess-default-style: Styles. (line 21)
+* 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 46)
+* 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-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-alist: Styles. (line 29)
+* ess-switch-to-end-of-proc-buffer: Other. (line 21)
+* ess-swv-pdflatex-commands: Sweave and AUCTeX. (line 27)
+* ess-tab-complete-in-script: Indenting. (line 42)
+* ess-use-eldoc: ESS ElDoc. (line 13)
+* ess-use-flymake: ESS Flymake. (line 12)
+* iESS program arguments: Customizing startup. (line 42)
+* inferior-ess-program: Customizing startup. (line 42)
+* inferior-R-font-lock-keywords: Highlighting. (line 12)
+* Rd-indent-level: R documentation files.
+ (line 85)
+* Rd-mode-hook: R documentation files.
+ (line 82)
+* Rd-to-help-command: R documentation files.
+ (line 89)
+
+\1f
+File: ess.info, Node: Concept index, Prev: Variable index, Up: Indices
+
+Concept Index
+=============
+
+\0\b[index\0\b]
+* Menu:
+
+* aborting R commands: Other. (line 9)
+* aborting S commands: Other. (line 9)
+* arguments to R program: Customizing startup. (line 45)
+* arguments to S program: Customizing startup. (line 45)
+* authors: Credits. (line 6)
+* auto-complete: Auto-complete. (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 40)
+* completion on lists: Object names. (line 38)
+* 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 21)
+* 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 38)
+* 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)
+* starting directory: Starting up. (line 11)
+* starting ESS: Starting up. (line 6)
+* STERM: Statistical Process running in ESS?.
+ (line 6)
+* temporary buffers: Help. (line 162)
+* 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 34)
+* 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)
+
+
+\1f
+Tag Table:
+Node: Top\7f268
+Node: Introduction\7f2906
+Node: Features\7f5659
+Node: Current Features\7f6495
+Node: New features\7f9946
+Node: Credits\7f23693
+Node: Manual\7f27310
+Node: Installation\7f29976
+Node: Installing from a third-party repository\7f30913
+Node: Installing from source\7f31860
+Node: Activating and Loading ESS\7f33452
+Node: Check Installation\7f34526
+Node: Interactive ESS\7f34746
+Node: Starting up\7f35560
+Node: Multiple ESS processes\7f36304
+Node: ESS processes on Remote Computers\7f37385
+Node: Customizing startup\7f41488
+Node: Entering commands\7f44105
+Node: Command-line editing\7f45263
+Node: Transcript\7f46496
+Node: Last command\7f48265
+Node: Process buffer motion\7f49691
+Node: Transcript resubmit\7f51194
+Node: Saving transcripts\7f53159
+Node: Command History\7f54949
+Node: Saving History\7f58358
+Node: History expansion\7f59119
+Node: Hot keys\7f62330
+Node: Statistical Process running in ESS?\7f66400
+Node: Emacsclient\7f67679
+Node: Other\7f68471
+Node: Evaluating code\7f69490
+Node: Transcript Mode\7f73171
+Node: Resubmit\7f74324
+Node: Clean\7f75387
+Node: Editing objects\7f76383
+Node: Edit buffer\7f77501
+Node: Loading\7f79547
+Node: Error Checking\7f80574
+Node: Indenting\7f81623
+Node: Styles\7f84812
+Node: Other edit buffer commands\7f87247
+Node: Source Files\7f88903
+Node: Source Directories\7f93507
+Node: Help\7f96660
+Node: Completion\7f100758
+Node: Object names\7f100991
+Node: Function arguments\7f103664
+Node: Minibuffer completion\7f104203
+Node: Auto-complete\7f104683
+Node: Company\7f106230
+Node: Icicles\7f106609
+Node: Developing with ESS\7f107929
+Node: ESS tracebug\7f108375
+Node: Getting started with tracebug\7f111382
+Node: Editing documentation\7f113540
+Node: R documentation files\7f114090
+Node: Roxygen\7f118017
+Node: Namespaced Evaluation\7f122352
+Node: Extras\7f124350
+Node: ESS ElDoc\7f125374
+Node: ESS Flymake\7f126870
+Node: Handy commands\7f127964
+Node: Highlighting\7f129161
+Node: Parens\7f130196
+Node: Graphics\7f130672
+Node: printer\7f131343
+Node: X11\7f132099
+Node: winjava\7f132438
+Node: Imenu\7f132850
+Node: Toolbar\7f133697
+Node: Xref\7f134105
+Node: Rdired\7f134428
+Node: Rutils\7f135482
+Node: Org\7f137876
+Node: Sweave and AUCTeX\7f138821
+Node: ESS for R\7f140947
+Node: ESS(R)--Editing files\7f141247
+Node: iESS(R)--Inferior ESS processes\7f141766
+Node: Philosophies for using ESS(R)\7f146515
+Node: Example ESS usage\7f147442
+Node: ESS for SAS\7f149663
+Node: ESS(SAS)--Design philosophy\7f150386
+Node: ESS(SAS)--Editing files\7f151339
+Node: ESS(SAS)--TAB key\7f153193
+Node: ESS(SAS)--Batch SAS processes\7f154559
+Node: ESS(SAS)--Function keys for batch processing\7f159585
+Node: iESS(SAS)--Interactive SAS processes\7f169071
+Node: iESS(SAS)--Common problems\7f172825
+Node: ESS(SAS)--Graphics\7f174348
+Node: ESS(SAS)--Windows\7f175131
+Node: ESS for BUGS\7f175709
+Node: ESS for JAGS\7f177465
+Node: Mailing lists/bug reports\7f180817
+Node: Bugs\7f181081
+Node: Reporting Bugs\7f182706
+Node: Mailing Lists\7f183599
+Node: Help with Emacs\7f184346
+Node: Customization\7f184878
+Node: Indices\7f185652
+Node: Key index\7f185827
+Node: Function and program index\7f191105
+Node: Variable index\7f200744
+Node: Concept index\7f204232
+\1f
+End Tag Table
--- /dev/null
+;;; essd-els.el --- S-PLUS 3.x at another location customization
+
+;; 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 <rmhNOSPAMtemple.edu>
+;; Created: December 1998
+
+;; Maintainer: ESS-core <ESS-coreNOSPAMr-project.org>
+
+;; 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-arc-d)
+(require 'ess-julia)
+(require 'ess-omg-d)
+(require 'ess-s-lang)
+(require 'ess-s3-d)
+(require 'ess-s4-d)
+(require 'ess-sas-d)
+(require 'ess-sp3-d)
+(require 'ess-sp4-d)
+(require 'ess-sp5-d)
+(require 'ess-sp6-d)
+(require 'ess-sp6w-d)
+(require 'ess-stata-mode)
+(require 'ess-trns)
+(require 'ess-utils)
+(require 'ess-vst-d)
+(require 'ess-xls-d)
+
+(defvar S+elsewhere-dialect-name "S+6"
+ "Name of 'dialect' for S-PLUS at another location.")
+ ;easily changeable in a user's .emacs
+
+(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")
+
+ (inferior-ess-start-file . nil) ;"~/.ess-S+3")
+ (inferior-ess-start-args . "-i")
+ (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."
+ (interactive)
+ (setq ess-customize-alist S+elsewhere-customize-alist)
+ (ess-write-to-dribble-buffer
+ (format "\n(S+elsewhere): ess-dialect=%s, buf=%s\n" ess-dialect
+ (current-buffer)))
+ (inferior-ess)
+ (if inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start)))
+;; git commit 104c4d7c56bc239ea245562763caa317bc3a1a84
+(make-obsolete 'S+elsewhere #'ess-remote "2000")
+
+(defun S+elsewhere-mode (&optional proc-name)
+ "Major mode for editing S+3 source. See `ess-mode' for more help."
+ (interactive)
+ (setq ess-customize-alist S+elsewhere-customize-alist)
+ (ess-mode S+elsewhere-customize-alist proc-name))
+
+(defun S+elsewhere-transcript-mode ()
+ "S-PLUS 3.x transcript mode."
+ (interactive)
+ (ess-transcript-mode S+elsewhere-customize-alist))
+
+;; 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 "arc") ARC-customize-alist)
+ ((string= dialect "vst") VST-customize-alist)
+ ((string= dialect "omg") OMG-customize-alist)
+ ((string= dialect "s3") S3-customize-alist)
+ ((string= dialect "s4") S4-customize-alist)
+ ((string= dialect "stata") STA-customize-alist)
+ ((string= dialect "R") ess-r-customize-alist)
+ ((string= dialect "sp3") S+3-customize-alist)
+ ((string= dialect "sp4") S+4-customize-alist)
+ ((string= dialect "sqpe4") Sqpe+4-customize-alist)
+ ((string= dialect "sp5") S+5-customize-alist)
+ ((string= dialect "S+") S+-customize-alist)
+ ((string= dialect "sqpe") Sqpe+-customize-alist)
+ ((string= dialect "XLS") XLS-customize-alist)
+ ((string= dialect "SAS") SAS-customize-alist);was S+elsewhere-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 ess-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 process 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 execute `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 ((ess-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 ess-customize-alist)
+ (inferior-ess-mode)
+ (set (make-local-variable '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)
+ (inferior-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-load-extras)
+
+ (when inferior-ess-language-start
+ (ess-eval-linewise inferior-ess-language-start
+ nil nil nil 'wait-prompt))))
+
+
+\f ; Provide package
+
+(provide 'essd-els)
+
+;;; essd-els.el ends here
--- /dev/null
+#!/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 <- load.ESSR('./R/')
+saveRDS(ESSR, file = "../ESSR.rds")
--- /dev/null
+## -*- mode: R -*-
+## loading code which is first sent to R on remote sessions
+local({
+ ver <- '1.3'
+ 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)
+ attach(ESSR)
+ print(TRUE)
+ },
+ error = function(e) {
+ print(e)
+ print(FALSE)
+ })
+})
--- /dev/null
+#### 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
+
+
+## loading ESSR.rda might fail, so re-assign here:
+.ess.Rversion <-
+ if( exists("getRversion", mode="function") ){
+ getRversion()
+ } else {
+ paste(R.version$major, R.version$minor, sep=".")
+ }
+
+.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))
+ }
+
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+## 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
+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)
+
+ ESSRver <- scan(paste(dirname(dir), "/VERSION", sep = ""),
+ what = "character", quiet = TRUE)
+ assign(".ess.ESSRversion", ESSRver, 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)
+}
+
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+## 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 = TRUE),
+ error=function(e) NULL)
+ allargs <- sprintf("'(\"%s\")",
+ paste(allargs, collapse = '\" "'))
+ envname <- 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){
+ if(.ess.Rversion > '2.14.1'){
+ comp <- compiler::enableJIT(0)
+ op <- options(error=NULL)
+ on.exit({ options(op); compiler::enableJIT(comp) })
+ }
+ 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')
+};
+
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+### 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
+ }
+}
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+.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.
+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")
+}
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+## simple Message Parsing Inerface
+
+.ess_mpi_send <- function(head, ...){
+ payload <- paste(..., sep = "\1e")
+ cat(sprintf("\e%s\1e%s\1d", head, payload))
+}
+
+.ess_mpi_message <- function(msg){
+ .ess_mpi_send("message", msg)
+}
+
+.ess_mpi_y_or_n <- function(prompt, callback){
+ .ess_mpi_send("y-or-n", prompt, callback)
+}
+
+.ess_mpi_eval <- function(expr, callback){
+ .ess_mpi_send("eval", expr, callback)
+}
+
+.ess_mpi_error <- function(msg) {
+ .ess_mpi_send("error", msg)
+}
+
--- /dev/null
+## 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)
+ }
+ }else{
+ if(is.function(thisEnv)){
+ environment(thisEnv) <- envns
+ newFunc <- c(newFunc, this)
+ }else{
+ newObjects <- c(newObjects, this)
+ }
+ .ess.assign(this, thisEnv, fallback_env)
+ }
+ }
+
+ 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)
+ 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
+}
+
+
+## Local Variables:
+## eval: (ess-set-style 'RRR t)
+## End:
--- /dev/null
+
+.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
+}
--- /dev/null
+1.4
\ No newline at end of file
--- /dev/null
+### Makefile - for scripts and icons (./etc) of ESS distribution.
+###
+
+## Before making changes here, please take a look at Makeconf
+include ../Makeconf
+
+# In ../Makefile we already construct the ESSR-VERSION file :
+# ESSR_VERSION = $(shell cat ESSR-VERSION)
+
+#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/VERSION
+ESSR_CODE_FILES = ESSR/R/*.R ESSR/R/.*.R
+# ESSR_tarball = ESSR_$(ESSR_VERSION).tar.gz
+
+all: #ESSR-VERSION $(ESSR_tarball) library/ESSR
+
+show-etc:
+ @echo $(ETCFILES)
+ ls -l $(ETCFILES)
+
+
+## happens "above" as it is need also in ../lisp/ :
+# ESSR-VERSION: $(ESSR_FILES)
+# (cd .. ; make etc/ESSR-VERSION)
+
+# $(ESSR_tarball): $(ESSR_FILES)
+# R CMD build ESSR
+# library/ESSR: $(ESSR_tarball)
+# R CMD INSTALL -l library ESSR
+
+# rel: $(ESSR_tarball)
+# [ x$$USER = xmaechler ] || (echo 'must be maechler'; exit 1 )
+# $(INSTALL) $(ESSR_tarball) $(UPLOAD_DIR)/pkgs/src/contrib
+
+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
--- /dev/null
+#### File showing off things that go wrong or *went* wrong in the past #### -- with R-mode (mostly coded in ../lisp/ess-mode.el )
+
+### NOTE: this file is indented with RRR style !!!!!
+### but do not change indentations anymore of anything in here:
+### expressions are written as we *want* them, not as ESS currently puts them
+
+options(keep.source = FALSE) # so we see R's deparse() + print() indentation
+
+
+### --- 1 --------- extraneous comment chars : This seems fixed
+
+## From: Robert Gentleman <rgentlemNOSPAMfhcrc.org>
+## To: Martin Maechler <maechlerNOSPAMstat.math.ethz.ch>
+## Subject: ESS buglet
+## Date: Sun, 01 Jul 2007 21:41:24 -0700
+
+## Hi Martin,
+## It seems that the following buglet exists (at least in what ever
+## version I am using)
+
+##a silly comment
+##and a second one
+foo <- function(x=a, abc = list("def", a=1,3,3), more.args, and, bla,
+ blu, bl,
+ another, plus, yet.another, and_mbasd,
+ lots = NULL,
+ more = NULL,
+ args = NULL) {
+ x
+}
+
+##- when the line before a function def is a comment, and adding args,
+##- then new lines, when generated have a comment char at the beginning of
+##- the line. It is slightly annoying as I have to remove the comment char.
+##-
+##- If I add a blank line after the comment line, then the problem does not
+##- occur.
+## and another ''anonymous'' function:
+function(x=a, abc = list("def", a=c(1,3,3)), more.args, and, bla, blu,
+ blo, Abc,
+ def,
+ another, and_another, and_this) {
+ ...; ...
+}
+
+## This is a "TRUE" example (from Matrix/tests/ ):
+NA.or.True <- function(x) is.na(x) | x
+
+abc <- function(x, y, ...) this.is.just.a.one.liner(x,y, z=TRUE, ...)
+
+## A more-liner function with no "{...}" -- this one even works (but not all!)
+mindiff <- function(df) df[which.min(df$diff),
+ which.max(df$daff)]
+
+## Two functions in one line - can I "send" just one of them? {no, not "simply"}
+f1 <- function(x) be.friendly(x, force=TRUE); f2 <- function(x,y) x*sin(pi*x)
+
+### --- 2 ----------------------------------------------------------------
+### --- Suggestion (Jenny Brian): --> Create a (defun ess-eval-multiline .)
+## Here is useful valid R "test code":
+
+## From 'example(plot.default)' :
+
+Speed <- cars$speed
+Distance <- cars$dist
+plot(Speed, Distance, panel.first = grid(8,8),
+ pch = 0, cex = 1.2, col = "blue")
+pp <- plot(Speed, Distance, panel.first = grid(8,8),
+ pch = 0, cex = 1.2, col = "blue")
+plot(Speed, Distance,
+ panel.first = lines(lowess(Speed, Distance), lty = "dashed"),
+ pch = 0, cex = 1.2, col = "blue")
+
+## Note: We now at least C-c C-c {ess-eval-function-or-paragraph-and-step}
+
+### --- 3 ----------------------------------------------------------------
+###--- This one (from the Matrix package) is for testing ess-roxy...,
+## i.e., C-c C-o
+
+## not exported but used more than once for "dimnames<-" method :
+## -- or do only once for all "Matrix" classes ??
+dimnamesGets <- function (x, value) {
+ d <- dim(x)
+ if (!is.list(value) || length(value) != 2 ||
+ !(is.null(v1 <- value[[1]]) || length(v1) == d[1]) ||
+ !(is.null(v2 <- value[[2]]) || length(v2) == d[2]))
+ stop(gettextf("invalid dimnames given for '%s' object", class(x)))
+ x@Dimnames <- list(if(!is.null(v1)) as.character(v1),
+ if(!is.null(v2)) as.character(v2))
+ x
+}
+
+### --- 4 ----------------------------------------------------------------
+### continued statements
+a <- function(ch) {
+ if(ch == Inf) {
+ E.cond <- numeric(nb)
+ }
+ else {
+ indic <- ifelse(jinf+1 <= 1 & jsup >= 1,1,0)
+ E.cond <- ch*(-pbinom(jinf,ni,prb) + 1-pbinom(js.n,ni,prb)) +
+ ifelse(ni == 1, prb*indic,
+ mu*(pbinom(js.n-1,pmax(ni-1,1),prb) -
+ pbinom(jinf-1,pmax(ni-1,1),prb))) / sV -
+### ^-- now here (better)
+ mu/sV*(pbinom(js.n,ni,prb) - pbinom(jinf,ni,prb))
+### ^-- now here (ok; more indentation would also be ok)
+ indic2 <- ifelse(jinf+1 <= 1 & jsup >= 1 & ni == 2,1,0)
+ }
+}
+
+
+### --- 5 ----------------------------------------------------------------
+### The beginning of function is not found correctly, and hence
+### all "ess-*-function" (C-M-a, C-M-e, ...) fail:
+
+setMeneric <-
+ ## It is clearly allowed to have comments here.
+ ## S version 4, and John Chambers in particular like it.
+ ##
+ ## BUG: M-C-e or M-C-a fails from ``here'' --
+ ## --- effectively because of ess-beginning-of-function fails
+ ## and that really relies on finding ess-function-pattern;
+ ## i.e., ess-R-function-pattern in ~/emacs/ess/lisp/ess-cust.el
+ ##
+ function(name, def = NULL, group = list(), valueClass = character(),
+ where = topenv(parent.frame()), genericFunction = NULL)
+{
+ ## comments in here are at least kept via "source" attribute
+ if(exists(name, "package:base") &&
+ typeof(get(name, "package:base")) != "closure") {
+ FALSE
+ }
+ "ABC"
+}
+
+### --- 6 ----------------------------------------------------------------
+## In one-liners without "{ ... }" body, the end-of-function is also
+## not correctly found:
+## Use C-M-e to see: In these two, the "end-of-function" is after
+## 'class' :
+## ---- these all work now (ESS version 5.3.8) :
+## no it doesn't VS[10-03-2012|ESS 12.03]:
+onelinerFails <- function(x, ...) class(x)
+
+onelinerFailsToo <-
+ function(x, ...)
+ class(x)
+
+onelinerWorks <- function(x, ...) { class(x) }
+
+onelinerWorksToo <-
+ function(x, ...) {
+ class(x)
+ }
+
+### --- 7 ----------------------------------------------------------------
+## idem:
+## this has one line more before 'function' than "typically:"
+setMethod("[", signature(x = "dgTMatrix", i = "numeric", j = "missing",
+ drop = "logical"),
+ function (x, i, j, ..., drop) { ## select rows
+ storage.mode(i) <- "integer"
+ xi <- x@i + 1:1 # 1-indexing
+ ## ...................
+ if (drop && any(nd == 1)) drop(as(x,"matrix")) else x
+ })
+
+### --- 8 ----------------------------------------------------------------
+## idem:
+## all bellow are ok VS[10-03-2012|ESS 12.03]:
+"dimnames<-.data.frame" <- function(x, value) {
+ d <- dim(x)
+ if(!is.list(value) || length(value) != 2
+ || d[[1]] != length(value[[1]])
+ || d[[2]] != length(value[[2]]))
+ stop("invalid 'dimnames' given for data frame")
+ row.names(x) <- as.character(value[[1]]) # checks validity
+ names(x) <- as.character(value[[2]])
+ x
+}
+
+'[.foo' <- function(x, i, value)
+{
+###
+ y <- x
+ y[i] <- value
+ y
+}
+
+'[[.bar' <- function(x, i, value)
+{
+ ## bla bla bla
+ y <- as.foo(x) ; y[[i]] <- value
+ y
+}
+
+"[<-.foobar" <- function(x,i,j,value) {
+ ## just something
+ x
+}
+
+"names<-.foobar" <- function(x, value) {
+ ## just something else
+ x
+}
+
+`[<-.data.frame` <- function(x, i, j, value)
+{
+ nA <- nargs() # value is never missing, so 3 or 4.
+
+###..........
+
+ class(x) <- cl
+ x
+}
+
+"[[<-.data.frame"<- function(x, i, j, value)
+{
+ cl <- oldClass(x)
+ ## delete class: Version 3 idiom
+ ## to avoid any special methods for [[<-
+ class(x) <- NULL
+
+###...........
+
+ class(x) <- cl
+ x
+}
+
+
+"$<-.data.frame" <- function(x, i, value)
+{
+ cl <- oldClass(x)
+ ## delete class: Version 3 idiom
+ ## to avoid any special methods for [[<-
+
+###...........
+
+ class(x) <- cl
+ return(x)
+}
+
+## swanky functions:
+`swank:quit-inspector` <- function(slimeConnection, sldbState) {
+ resetInspector(slimeConnection)
+ FALSE
+}
+
+'swank:quit-inspector' <- function(slimeConnection, sldbState) {
+ resetInspector(slimeConnection)
+ FALSE
+}
+
+
+### --- 9 ----------------------------------------------------------------
+## VS[03-2012|12.03]:FIXED:
+
+## From: "Sebastian P. Luque" <spluqueNOSPAMgmail.com>
+## To: ess-bugsNOSPAMstat.math.ethz.ch
+## Subject: [ESS-bugs] ess-mode 5.12; `ess-indent-line' error
+## Date: Tue, 17 Aug 2010 13:08:25 -0500
+
+## With the following input, and point on the line with "Table 8.3":
+## it was the parenthetical expression at the beg of line
+
+if (require(lme4)) {
+ ## Model in p. 213
+ (fm1 <- lmer(logFEV1 ~ age + log(height) + age0 + log(height0) + (age | id),
+ data=fev1, subset=logFEV1 > -0.5))
+ ## Table 8.3
+ VarCorr(fm1)$id * 100
+
+ ## Model in p. 216
+ (fm2 <- update(fm1, . ~ . - (age | id) + (log(height) | id)))
+}
+
+### -----
+## hitting TAB (`ess-indent-command'), which calls `ess-indent-line' I get
+## the following trace:
+
+## ....: (scan-error "Containing expression ends prematurely" 20 20)
+## scan-sexps(177 -2)
+## forward-sexp(-2)
+## ...
+## ess-continued-statement-p()
+## ......
+
+## Interestingly, if the lines 2-4 are absent, then the problem is gone.
+## The problem is also there in ESS 5.11.
+
+## I'll try to find out what is going on in `ess-continued-statement-p' but
+## given that I'm not very familiar with the stuff in ess-mode.el, I'm
+## submitting the report in case somebody can detect the issue sooner.
+
+## another example: hitting Tab at }else line
+.essDev_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)
+}
+
+
+
+### --- 10 ---------------------------------------------------------------
+## indent at 0 after }else:
+## VS:[03-2012|12.03]:FIXED:
+if (is.function(f1) && is.function(f2)){
+ !(identical(body(f1), body(f2)) && identical(args(f1), args(f2)))
+}else
+ !identical(f1, f2)
+
+
+### --- 11 ---------------------------------------------------------------
+## --------------- C-c C-c was finding the wrong "beginning of function"
+## [:FIXED:, 2011-05-28]
+foobar <- function(...) {}
+rm(list=ls())
+
+##--------> consequence of the above experiments:
+## the 2nd form is numerically "uniformly better" than the first
+##--------> 2011-05-27: Change Frank's psiInv() to
+## psiInv = function(t,theta)
+## -log1p(exp(-theta)*expm1((1-t)*theta)/expm1(-theta))
+
+### --- 12 ---------------------------------------------------------------
+##--- In the following block, in the first line, C-c C-c does *NOT* behave
+## VS[10-03-2012|ESS 12.03]: works fine for me:
+th <- 48 # now do ls() and see what happened ... the horror !!!
+d <- 3
+cpF <- list("Frank", list(th, 1:d))
+cop <- acF <- cpF$copula
+
+### --- 13 ---------------------------------------------------------------
+## VS[05-05-2012|ESS 12.04]: looks like :FIXED:
+
+## From: Aleksandar Blagotic <aca.blagoticNOSPAMgmail.com>
+## To: <ess-helpNOSPAMstat.math.ethz.ch>
+## Subject: [ESS] R-mode: forward-sexp: Scan error: "Unbalanced parentheses"
+## Date: Tue, 6 Dec 2011 01:24:11 +0100
+ #
+## Let's presuppose that I have a function like this:
+ #
+fn <- function(x, ...){
+ re <- "^#{1,6} [[:print:]]+$"
+ grepl(re, x, ...)
+}
+## As soon as I put my cursor at the end of the line with regexp, and
+## press RET, I get this error:
+
+## forward-sexp: Scan error: "Unbalanced parentheses"
+##
+##-------
+## Rodney S: I can reproduce it ...
+## Martin M: I can NOT reproduce it, neither with 'emacs -Q';
+## tried both ESS 5.14 and ESS from svn
+## VS[03-2012|12.03]: Cannot reproduce it either, solved?
+
+
+### --- 14 ---------------------------------------------------------------
+## check the behavior of ess-arg-function-offset-new-line
+
+a <- some.function(
+ arg1,
+ arg2)
+## ^--- RRR has ess-arg-function-offset-new-line (4) ==> should indent here
+
+a <- some.function(arg1,
+ arg2)
+## ^--- here
+
+
+### --- 15 --------------------------------------------------------------
+## VS[05-05-2012|ESS 12.04]:FIXED:
+## indentation of the 3rd line is wrong
+for(s in seq(10, 50, len = 5))
+ for(a in seq(.5, 1, len = 5))
+ pt_dif_plot(s, a)
+## ^-- here
+
+### --- 16 ----
+## VS[05-05-2012|ESS 12.04]:FIXED:
+## MM[2014-04-28]: added '}' before else (=> "{" after if(.))
+## so parse(<file>) works at all!
+## Gives error unbalanced para at else lines and indentation is wrong
+## error: Point is not in a function according to 'ess-function-pattern'.
+getOrCreateForm <- function(bindName, whereEnv)
+ if(exists(bindName, envir = get(".forms", envir = whereEnv))) {
+ get(bindName, envir = whereEnv)
+### ^-- here
+ } else
+ new("protoForm")
+### ^-- here
+
+
+
+parentContainer <-
+ if(is.null(.getPrototype(.Object@host))) { emptyenv()
+ } else sdf
+### ^-- here
+
+parentContainer <-
+ if(is.null(.getPrototype(.Object@host))) emptyenv()
+ else sdf
+### ^-- here
+
+### --- 17 ---
+## Indentation ----- "expression" is special
+expremmion <- c(1, 3,
+ 9876)# was always ok
+## Had wrong indentation here:
+expression <- c(2343,
+ 23874, 239487)
+
+## or here:
+foo <- function(x) {
+ expression <- c(2343,
+ 23874, 239487)
+ 10 + expression
+}
+
+## Where as here, we *do* want the indentation to
+## *NOT* go all the way to the right:
+
+{
+ my.long.Expression <- expression(
+ x[a[j]] == exp(theta[1] + theta[2]^2),
+ x[b[i]] == sin(theta[3] ~~ theta[4])
+ )
+ ausdruck <- expression
+ my.long.Expr...... <- ausdruck(
+ x[a[j]] == exp(theta[1] + theta[2]^2),
+ )
+}
+
+## VS[18-08-2012]: redundant feature. This is a feature for long subexpressions
+## imidiately folowing new line. Documented in ess-arg-function-offset-new-line
+
+### --- 18 ---
+## M-C-a (beginning of function)
+## ----- anywhere inside the following function, M-C-a must go to beginning
+Ops.x.x <- function(e1, e2)
+{
+ d <- dimCheck(e1,e2)
+ if((dens1 <- extends(c1 <- class(e1), "denseMatrix")))
+ gen1 <- extends(c1, "generalMatrix")
+ if((dens2 <- extends(c2 <- class(e2), "denseMatrix")))
+ gen2 <- extends(c2, "generalMatrix")
+ if(dens1 && dens2) { ## both inherit from ddense*
+ geM <- TRUE
+ if(!gen1) {
+ if(!gen2) { ## consider preserving "triangular" / "symmetric"
+ geM <- FALSE
+ le <- prod(d)
+ isPacked <- function(x) length(x@x) < le
+ }
+ }
+ ## now, in all cases @x should be matching & correct {only "uplo" part is used}
+ r <- callGeneric(e1@x, e2@x)
+ if(geM)
+ new(paste0(.M.kind(r), "geMatrix"), x = r, Dim = d, Dimnames = dimnames(e1))
+ else
+ new(paste0(.M.kind(r), Mclass), x = r, Dim = d, .....)
+ }
+ else {
+ r <- ....
+
+ ## criterion "2 * nnz(.) < ." as in sparseDefault() in Matrix() [./Matrix.R] :
+ if(2 * nnzero(r, na.counted = TRUE) < prod(d))
+ as(r, "sparseMatrix") else r
+ }
+}
+
+
+### --- 19 ---
+## indentation with regexp (bug in ess-backward-to-noncomment)
+parse_roc <- function(lines, match = "^\\s*+\' ?") {
+ lines <- lines[str_detect(lines, match)]
+ if (length(lines) == 0) return(NULL)
+### ^-- here (2014-11: fixed)
+}
+
+
+### --- 20 ---
+## continuation indentation must be consistent in/out {}:
+
+{
+ a <- ggplot(data = overtime.by.month,
+ aes(x="", y=Percent, fill = Overtime)) +
+ geom_bar(width = 1) +
+ xlab('') +
+ ylab(sub.txt) +
+ labs(title = title.txt) +
+ facet_wrap(~Year.Month)
+}
+
+a <- ggplot(data = overtime.by.month,
+ aes(x="", y=Percent, fill = Overtime)) +
+ geom_bar(width = 1) +
+ xlab('') +
+ ylab(sub.txt) +
+ labs(title = title.txt) +
+ facet_wrap(~Year.Month)
+### ^-- face_wrap must be here
+
+
+### --- 20b ---
+## From https://github.com/emacs-ess/ESS/issues/120
+
+mean(rnorm(100, mean = runif(1, 1, 10)), na.rm =TRUE) +
+ 2
+## ^--- 2 is here
+
+mean(rnorm(100, mean = runif(1, 1, 10)),
+ na.rm =TRUE) +
+ 2
+## ^--- 2 is here
+
+mean(rnorm(100,
+ mean = runif(1, 1, 10)), na.rm=TRUE) +
+ 2
+## ^--- 2 is here
+
+### --- 21 ---
+
+## From: Marius Hofert <marius.hofertNOSPAMmath.ethz.ch>
+## Date: Fri, 15 Mar 2013 21:00:45 +0100
+## Hi,
+## The following bug happens in ESS 12.09-2 [rev. 5395 (2013-01-10)]. Put the
+## cursor in the line before the function head and hit C-c C-c.
+
+foo <- function(x)
+ x # bar
+x <- 1:10
+
+## I'll see
+## > + > [1] 1 2 3 4 5 6 7 8 9 10
+## ESS 15.03: Error in eval(expr, .... : object 'x' not found
+
+foo <- function(x) x*x
+bar <- function(y) y
+## via C-c C-c leads to "Error: object 'bar' not found". -- fixed
+
+
+### --- 22 ----
+## now correct indentation (inspite of # {was same reason as 19})
+if (!grepl("#", x))
+ return(res)
+
+### --- 23 ----
+### three ways to indent closing parent depending on context:
+foo <-
+ function_call(
+ a,
+ b,
+ c
+ )
+### ^-- ) is here now
+
+foo <- function_call(
+ a,
+ b,
+ c
+)
+### ")" is at column 0
+
+foo <- function_call(a,
+ b,
+ c
+ )
+### ^-- ) is here
+
+### --- 24 ---
+### shift comma in function calls
+
+foo <- function_call(a
+ , b
+ , c
+### ^-- c is here
+ )
+### ^-- ) is here
+
+### --- 25 ---
+## if/else in function calls and nested
+
+function_call(abc =
+ if (test)
+ do_something
+ else
+ do_something_else)
+
+function_call(
+ abc =
+ if (test)
+ do_something
+ else
+ do_something_else)
+
+
+function_call(abc = if (test)
+ do_something
+ else
+ do_something_else)
+
+## real example is smooth.spline() source code [still (2015-04-08) wrong / bug!]
+ss <- function (x, all.knots, nknots, ...)
+{
+ if (all.knots) {
+ if (!missing(nknots) && !is.null(nknots))
+ warning("'all.knots' is TRUE; 'nknots' specification is disregarded")
+ nknots <- nx
+ } else if (is.null(nknots)) # <- for back compatibility
+ nknots <- .nknots.smspl(nx)
+ else {
+### ^ want 'else' there
+ if (is.function(nknots))
+ nknots <- nknots(nx)
+ else if (!is.numeric(nknots))
+ stop("'nknots' must be numeric (in {1,..,n})")
+ if (nknots < 1)
+ stop("'nknots' must be at least 1")
+ else if (nknots > nx)
+ stop("cannot use more inner knots than unique 'x' values")
+ }
+### ^-- want '}' there
+}
+
+## "if" conditional is an exception of the continuation rules:
+## Here, we do not want subsequently further indentation of the c1 || c2 || c3
+## part:
+t2 <- function(x) {
+ if(long.expression.of.some.size(x, pi) ||
+ another.longish.expression(sin(x)*exp(x)) ||
+ a.third.condition.under.which.A.is.chosen)
+### ^-- here
+ A
+ else
+ B
+}
+
+
+r <-
+ (some.function (x, 2342) +
+ another.f (x^3) + sdfsdf - sdfsdf +
+ and(x) + the(x) - last(x)*part(3))
+
+
+### --- 26 ----
+## This is formally correct R, though help(parse) mentions the line-length limit of
+## 4095 __when reading from the console__
+## ESS gives syntax errors ("Error: unexpected ','" ...) when evaluating this
+## because line length >= 4096 :
+##
+x <- c(1, 3.075819, 1.515999, 2.156169, 1.480742, 1.765485, 1.460206, 1.603707, 1.427429, 1.504712, 1.334528, 1.48297, 1.355308, 1.383867, 1.319241, 1.36065, 1.307467, 1.365596, 1.255259, 1.352741, 1.239381, 3.15342, 1.799889, 2.258497, 1.688312, 1.906779, 1.548203, 1.724785, 1.500873, 1.573442, 1.417137, 1.540805, 1.395945, 1.472596, 1.394247, 1.377487, 1.337394, 1.369354, 1.333378, 1.3181, 1.313813, 1.315528, 2.12777, 2.718898, 1.993509, 2.220433, 1.820585, 1.97782, 1.672455, 1.770151, 1.587478, 1.685352, 1.539295, 1.584536, 1.499487, 1.50702, 1.41952, 1.449058, 1.393042,&n72, 1.712926, 1.666956, 1.667838, 1.62077, 1.621445, 1.592891, 1.58549, 1.55603, 1.559042, 1.521501, 1.523342, 2, 3, 4)
+
+### --- 27 ----
+## Indentation after open brace
+.a.lst <-
+ list(ex1 = function(p) {
+ cMah <- qchisq(0.975, p)
+ function(d) as.numeric(d < cMah)
+### ^--- now here (less indented than prev.)
+ },
+ ex2 = function(p) {
+ cM <- qchisq(0.95, p)
+ function(d) as.numeric(d < cM)
+### ^--- here
+ })
+### ^--- '}' here
+
+
+.a.lst <- list(ex1 = function(p) {
+ cMah <- qchisq(0.975, p)
+ function(d) as.numeric(d < cMah)
+}, ## <- now at column 0 {also the next line}
+ex2 = function(p) {
+ cM <- qchisq(0.95, p)
+ function(d) as.numeric(d < cM)
+})
+
+
+.a.lst <- list(list(aa = {
+ bbb
+### ^--- here
+},
+aaa = function(p) {
+ qchisq(0.95, p)
+### ^--- here
+},
+aaaa = {
+ cccc
+### ^--- here
+}))
+
+list(function(p){
+ abc
+### ^-- here
+ ## <-- Press [Tab] before/at the first '#': should *NOT* insert '...='
+})
+### at column 0
+
+(ab) {
+ sfdsf
+### ^-- here
+}
+
+### --- 27b --- [new, 2015-04-09]
+print.MethodsFunction <- function(x, byclass = attr(x, "byclass"), ...)
+{
+ info <- attr(x, "info")
+ values <- if (byclass) {
+ unique(info$generic)
+ } else {
+ visible <- ifelse(info$visible, "", "*")
+ paste0(rownames(info), visible)
+### ^-- both lines above should start here
+ }
+### ^-- "}" here
+
+ ## 2nd version:
+ val <-
+ if (byclass) {
+ unique(info$generic)
+ } else {
+ visible <- ifelse(info$visible, "", "*")
+ paste0(rownames(info), visible)
+### ^-- both lines above should start here
+ }
+### ^-- "}" here
+ invisible(x)
+}
+
+
+
+### --- 28 --- [2015-02-17; still unfixed, 2015-11-21]
+## Indentation of end-line comments (to column 40 = 'indent-column')
+## {this is part of "real" code in Rmpfr/R/hjk.R}:
+hjk <- function(x,n) { # <--- C-M-q "on {" -- does *no longer* indent the "# .."
+ ##-- Setting steps and stepsize -----
+ nsteps <- floor(log2(1/tol)) # number of steps
+ steps <- 2^c(-(0:(nsteps-1))) # decreasing step size
+ dir <- diag(1, n, n) # orthogonal directions
+
+ x <- par # start point
+ fx <- f(x) # smallest value so far
+ fcount <- 1 # counts number of function calls
+
+ if (info) cat(sprintf("step nofc %-12s | %20s\n",
+ "fmin", "xpar"))
+
+ ##-- Start the main loop ------------
+ ns <- 0
+ while (ns < nsteps && fcount < maxfeval && abs(fx) < target) {
+ ns <- ns + 1
+ hjs <- .hjsearch(x, f, steps[ns], dir, fcount, maxfeval, target)
+ }
+ hjs
+}
+
+### --- 29 ---
+foreach(a = 1:3) %do% {
+ a^2
+### ^--- here
+}
+
+foreach(a = 1:3) %:%
+ foreach(b = 10:13) %dopar% {
+### ^--- here
+ a + b
+### ^---- here
+ }
+### ^--- here
+
+read.csv('file.csv') %>%
+ mutate(X = X+2, Y = Y/2) %>%
+### ^--- here
+ filter(X < 5)
+### ^-- here (*was* indented earlier)
+
+
+### --- 30 ---
+## a) ok:
+{
+ r <- array(if (d[3L] == 3L)
+ rgb(t(x[,,1L]), t(x[,,2L]), t(x[,,3L]), maxColorValue = max)
+ else if (d[3L] == 4L)
+ rgb(t(x[,,1L]), t(x[,,2L]), t(x[,,3L]), t(x[,,4L]), maxColorValue = max)
+ else stop("foo"),
+ dim = d[1:2])
+}
+
+## b) ok :
+{
+ obj <- obj && (condition1 || class2 %in% .BasicClasses ||
+ condition3)
+}
+
+## c) ok:
+{
+ if (any(abs(d) < .001*abs(dd) |
+ (is.na(d) & x == y)))
+ TRUE
+}
+
+
+### --- 31 --------
+## C-s "recog"; M-C-a -- should go to beginning of function, does not
+
+glmmTMB <- function (formula, data = NULL)
+{
+ ## glFormula <- function(formula, data=NULL, family = gaussian,
+ ## subset, weights, na.action, offset,
+ ## contrasts = NULL, mustart, etastart,
+ ## control = glmerControl(), ...) {
+
+ ## FIXME: check for offsets in ziformula/dispformula, throw an error
+
+ call <- mf <- mc <- match.call()
+
+ if (is.null(family$family)) {
+ print(family)
+ stop("'family' not recognized")
+ }
+}
+
+
+### --- 32 --- 2015-11-07 --- indentation again! --------
+{
+ yl <- if(strictlim) {
+ ylim
+ }
+ else {
+ range(y, ylim)
+ }
+ ## room below for weights
+ dy <- 4*dy
+}
+## -- 32 b)
+{
+ yl <- if(strictlim) {
+ ylim
+ }
+ else
+ range(y, ylim)
+ ## continue
+}
+## -- 32 c)
+{
+ U <- if(is.matrix(x))
+ apply(x, 2, foo) / (nrow(x) + 1)
+ else
+ foo(x) / (length(x) + 1)
+}
+## 'else' now aligns with 'if' (and their code too)
+
+### --- 33 -- Treat `<<-` as `<-`
+{
+ f(X <-
+ callme(arg))
+ f(X <<-
+ callme(arg))
+}
+## the 2nd callme() now indents like the first
+
+
+### --- 34 --- "eval-function" (e.g. C-c C-c) fails with this
+
+##' checking pretty():
+chkPretty <- function(x, n = 5, min.n = NULL, ..., max.D = 1) {
+ if(is.null(min.n)) {
+ ## work with both pretty.default() and greDevices::prettyDate()
+ ## *AND* these have a different default for 'min.n' we must be "extra smart":
+ min.n <-
+ if(inherits(x, "Date") || inherits(x, "POSIXt"))
+ n %/% 2 # grDevices:::prettyDate
+ else
+ n %/% 3 # pretty.default
+ }
+ pr <- pretty(x, n=n, min.n=min.n, ...)
+ ## if debugging: pr <- grDevices:::prettyDate(x, n=n, min.n=min.n, ...)
+ stopifnot(length(pr) >= (min.n+1),
+ abs(length(pr) - (n+1)) <= max.D,
+ ## must be equidistant [may need fuzz, i.e., signif(.) ?]:
+ length(pr) == 1 || length(unique(diff(pr))) == 1,
+ ## pretty(x, *) must cover range of x:
+ min(pr) <= min(x), max(x) <= max(pr))
+ invisible(pr)
+}
+
+
+### --- 35 --- indentation of conditional function definitions:
+## from a robustbase vignette:
+{
+ ## calculate robustness weights
+ lwgts <- Mwgt(lresid, lctrl$tuning.psi, lctrl$psi)
+ ## function to calculate robustified leverages
+ tfun <-
+ if (is.function(attr(estlist$design, 'gen')))
+ function(i) {
+ if (all(is.na(wi <- lwgts[i,]))) wi
+ else .lmrob.hat(lXs[,,i,lcdn[2]],wi)
+ }
+ else
+### \-<-- 'else' (and all below) should indent 4 more, 'else' matching the above 'if'
+ function(i) {
+ if (all(is.na(wi <- lwgts[i,]))) wi else .lmrob.hat(lX, wi)
+ }
+}
+
+### --- 36 --- indentation of '#' inside string plus a '#' after that, issue #446
+A <- f("abc") +
+ f("abc") + f("abc") +
+ f("abc # abc") +
+ ## The above is now ok,
+ f("abc # abc") + # <- comment w/o quotes or hashtag -- fixed now: next line was indented to beginning of line
+ f("ABCDEF") +
+ f(g(h("abc # def"), "foo ## bar")) +
+ f("another")
+
+
+### --- 37 ----------Github issue #432 ---- now fixed
+## Indentation after string with "*"
+fo4 <- function(x, ...) {
+ if(length(x) > 0)
+ warning("Result gave strings of *different* #{characters}")
+ x
+ ## 'x' was wrongly indented --here: ^
+}
+
+### --- 38 ----------Mario Bouguin to ESS-bugs, Nov 21, 2017 ----
+scored <- read.csv(scored_path, comment.char="#")
+## writes
+## When I'm on the line and execute ess-eval-region-or-function-or-paragraph-and-step (i.e. C-c C-c), R only receives this:
+##
+## > scored <- read.csv(scored_path, comment.char="
+## +
+## MM: but I don't see this, so told him to upgrade ESS (he had 16.10, Windows)
+
+
+## This is a problem only inside package code [ess-tracebug related]
+rm(old,new)
+old <- 10 # line 1, use ess-eval-line, i.e., C-c C-j
+new <- old+1 # line 2, use ess-eval-line-and-step, i.e., C-c C-n
+
+
+
+
+### Local Variables:
+### page-delimiter: "^### --- [1-9]"
+### End:
--- /dev/null
+;;;; Things that go wrong or *went* wrong in the past
+;;;; (from list side) see R-ESS-bugs.R for the R's side.
+
+
+ ;;;; 1 ess-get-words-from-vector stumbles over \"
+(ess-get-words-from-vector "c('aaa','bbb\"ccc', 'dddd')\n")
+;;-> (" " "ccc" "dddd"): SOLVED
+
+
+;;;; 2 ess-get-words-from-vector disregards max.print
+;; options(max.print=1000) (warning added to the docs)
+(length (ess-get-words-from-vector "as.character(1:10000)\n"))
+;;-> 1001 with "max.print" at the end; added a comment in the function doc
+
+;;;; 3 Inferior-ess-primary-prompt does not capture "+ + > "
+;; this hangs emacs; SOLVED
+(ess-command "tf<-function(N){
+N}\n")
+
+;;;; 4 ess-command detects the prompt prematurely
+;; this outputs str(iris) in the inferior buffer; SOLVED
+(ess-command "
+lm_test <- function (formula, data, subset, weights, na.action, method = 'qr',
+ model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
+ contrasts = NULL, offset, ...)
+{
+ cl <- match.call()
+ mf <- match.call(expand.dots = FALSE)
+ m <- match(c('formula', 'data', 'subset', 'weights', 'na.action',
+ 'offset'), names(mf), 0L)
+ mf <- mf[c(1L, m)]
+ mf$drop.unused.levels <- TRUE
+ mf[[1L]] <- as.name('model.frame')
+ mf <- eval(mf, parent.frame())
+ if (method == 'model.frame')
+ return(mf)
+ else if (method != 'qr')
+ warning(gettextf('method is not supported. Using',
+ method), domain = NA)
+ mt <- attr(mf, 'terms')
+ y <- model.response(mf, 'numeric')
+ w <- as.vector(model.weights(mf))
+ if (!is.null(w) && !is.numeric(w))
+ stop('weights must be a numeric vector')
+ offset <- as.vector(model.offset(mf))
+ if (!is.null(offset)) {
+ if (length(offset) != NROW(y))
+ stop(gettextf('number of offsets is %d, should equal %d (number of observations)',
+ length(offset), NROW(y)), domain = NA)
+ }
+ if (is.empty.model(mt)) {
+ x <- NULL
+ z <- list(coefficients = if (is.matrix(y)) matrix(, 0,
+ 3) else numeric(0L), residuals = y, fitted.values = 0 *
+ y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w !=
+ 0) else if (is.matrix(y)) nrow(y) else length(y))
+ if (!is.null(offset)) {
+ z$fitted.values <- offset
+ z$residuals <- y - offset
+ }
+ }
+ else {
+ x <- model.matrix(mt, mf, contrasts)
+ z <- if (is.null(w))
+ lm.fit(x, y, offset = offset, singular.ok = singular.ok,
+ ...)
+ else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok,
+ ...)
+ }
+ class(z) <- c(if (is.matrix(y)) 'mlm', 'lm')
+ z$na.action <- attr(mf, 'na.action')
+ z$offset <- offset
+ z$contrasts <- attr(x, 'contrasts')
+ z$xlevels <- .getXlevels(mt, mf)
+ z$call <- cl
+ z$terms <- mt
+ if (model)
+ z$model <- mf
+ if (ret.x)
+ z$x <- x
+ if (ret.y)
+ z$y <- y
+ if (!qr)
+ z$qr <- NULL
+ z
+}
+str(iris)
+")
+
+;;;; 5 double prompt > > used to stall emacs; SOLVED
+(ess-command "\n\n\n")
--- /dev/null
+
+## 1
+Error: chunk 7 (label = OP4)
+Error in disp.Rnw:656:31: unexpected symbol
+655: par(mgp = c(2.5, 1, 1), mar = c(0, 0, 0, 0),
+ 656: plt= c(0.08, 0.9, 0.25, 0.p9
+))
+
+## 2
+Browse[2]> Error in x %*% y (from models.R#46) :
+ Cholmod error 'X and/or Y have wrong dimensions' at file ../MatrixOps/cholmod_sdmult.c, line 90
+
+## 3
+Error in source("~/works/protoClasses/R/funcs.R") (from hierarchy.R#6) :
+ ~/works/protoClasses/R/funcs.R:1797:5: unexpected '[['
+1796: b[[2]] <- quote(browser())
+1797: [[
+ ^
+## 4
+source("basicModel.R")
+Error in source("basicModel.R") : basicModel.R:95:1: unexpected symbol
+94:
+95: ixQ
+ ^
+
+## 5.a
+> + Error in source(file = "/home/vitoshka/works/pbm/R/S4.R") (from #1) :
+ /home/vitoshka/works/pbm/R/S4.R:36:62: unexpected ')'
+35: }, list(vname = as.name(".pix_v")),
+36: pname = as.name(".pix_p"))))
+ ^
+
+## 5.b
+> + Error in source(file = "/home/vitoshka/works/pbm/R/S4.R") (from #1) :
+ c:/home/vitoshka/works/pbm/R/S4.R:36:62: unexpected ')'
+35: }, list(vname = as.name(".pix_v")),
+36: pname = as.name(".pix_p"))))
+ ^
+
+## 6 first line is not a pattern!
++ . + Error in base::source(file = file, echo = echo, local = local, print.eval = print.eval, (from #95) :
+ /tmp/model_mixture.R@4:5:13: unexpected symbol
+4: Mq$DATA$ixs$clust <- data$ixQ
+5: Mq
+
+## 7 don't highlight dates
+ id lat lon obs_date
+ Min. : 1.00 Min. :21.57 Min. :-179.88 01/02/1997 04:16:53: 1
+ 1st Qu.: 99.25 1st Qu.:24.36 1st Qu.:-147.38 01/02/1997 05:56:25: 1
+ Median :197.50 Median :25.64 Median :-119.64 01/04/1997 17:41:54: 1
+ Mean :197.50 Mean :27.21 Mean : -21.52 01/05/1997 17:20:07: 1
+ 3rd Qu.:295.75 3rd Qu.:27.41 3rd Qu.: 153.66 01/06/1997 04:31:13: 1
+ Max. :394.00 Max. :39.84 Max. : 179.93 01/06/1997 06:12:56: 1
+ (Other) :388
+## 8 valgrind errors
+==25269== Invalid read of size 8
+==25269== at 0x9EC363C: inner_product<double const*, double const*, double> (stl_numeric.h:183)
+==25269== by 0x9EC363C: distance(RcppParallel::RMatrix<double> const&, unsigned long, unsigned long, DistType) (rwmd.cpp:21)
+==25269== by 0x9EC90C9: RelaxedWordMoverDistanceSparse::operator()(unsigned long, unsigned long) (rwmd.cpp:137)
+
+## 9 testhat new patterns
+test_embeddings.R:20: failure: average embedding works
+embed_vocab(vocab, embs) not equal to embs[, 1:N].
+Attributes: < Length mismatch: comparison on first 1 components >
+
+test_embeddings.R:59: error: average embedding works with missing values
+no 'dimnames' attribute for array
+1: expect_equal(e[, "dd"], e[, "ee"]) at /store/Dropbox/dev/mlvocab/tests/testthat/test_embeddings.R:59
+2: quasi_label(enquo(object), label) at /tmp/Rtmp6McxD6/R.INSTALL70c948e315c6/testthat/R/expect-equality.R:51
+3: eval_bare(get_expr(quo), get_env(quo)) at /tmp/Rtmp6McxD6/R.INSTALL70c948e315c6/testthat/R/expectation.R:90
+
--- /dev/null
+
+## inspired by:
+## https://github.com/rstudio/rstudio/pull/191
+
+## nested calls should work
+df[a][, |]
+
+## matrix, list, environments
+l <- list(aaaa = 1111, bbbb = 2222)
+l[a|] ## -> "aaaa" (quoted!)
+
+## data table
+dt <- data.table(aaaa = 1111, bbbb = 22222)
+dt[, a|] # -> aaaa (unquoted!)
+
+## attributes
+x <- ""
+attr(x, "foo") <- function(alpha, beta) {}
+attr(x, "foo")(al| # -> "alpha"
+
+## chains
+mtcars %>% dplyr::select(mp| #-> mpg (unquoted))
+
+## models
+lm(mpg ~ cy| , data = mtcars) #-> cyl
+
+## "by" keyword in data.table, inner_join, etc
+inner_join(foo, bar, by = c(| # provides completions for variables in foo when
+ # on the left side of an =, and bar when on the
+ # right side of an =.
--- /dev/null
+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)
+ VERSION >= v"0.4-" ? Core.eval(@current_module(), parse("@doc $topic")) : Base.Help.help(topic)
+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
+ m = Core.eval(@current_module(), 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
+
+\f
+### 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))
+ s = string(v)
+ if 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
+
+\f
+### 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
--- /dev/null
+#!/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 </dev/tty 1>$1 2>$2 $3
+
+set -x
+stdout=$1
+stderr=$2
+shift 2
+set +x
+echo sas \</dev/tty 1\>$stdout 2\>$stderr $@
+sas </dev/tty 1>$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.
--- /dev/null
+#!/bin/sh
+
+if [ $# -eq 0 -o "$1" = "-h" -o "$1" = "-help" -o "$1" = "--help" ]
+then
+ echo "usage: gpl-check [-h|-help|--help|-2|-3|-u|-n] file1 [file2 ...]"
+ echo " -h|-help|--help print this help"
+ echo " -2 print file names found with GPLv2+"
+ echo " -3 print file names found with GPLv3+"
+ echo " -u print file names found with a GPL of unknown version"
+ echo " -n print file names with no GPL found"
+ echo " file1 [file2 ...] list of files to check"
+else
+ GPLV2=0
+ GPLV3=0
+ GPLVUNK=0
+ NOGPL=0
+
+ for i
+ do
+ case $i in
+ -2) GPLV2=1;;
+ -3) GPLV3=1;;
+ -23) GPLV2=1;GPLV3=1;;
+ -u) GPLVUNK=1;;
+ -n) NOGPL=1;;
+ -nu|-un) GPLVUNK=1;NOGPL=1;;
+ *) if [ $GPLV2 -eq 0 -a $GPLV3 -eq 0 -a $GPLVUNK -eq 0 -a $NOGPL -eq 0 ]
+ then
+ GPLV2=1
+ GPLV3=1
+ GPLVUNK=1
+ NOGPL=1
+ fi
+ if grep -l 'either version 2, or' $i > /dev/null
+ then
+ if [ $GPLV2 -eq 1 ]
+ then echo "$i GPLv2+"
+ fi
+ elif grep -l 'either version 3' $i > /dev/null
+ then
+ if [ $GPLV3 -eq 1 ]
+ then echo "$i GPLv3+"
+ fi
+ elif grep -l 'GNU General Public License' $i > /dev/null
+ then
+ if [ $GPLVUNK -eq 1 ]
+ then echo "$i GPLv unknown"
+ fi
+ else
+ if [ $NOGPL -eq 1 ]
+ then echo "$i no GPL"
+ fi
+ fi;;
+ esac
+ done
+fi
--- /dev/null
+Debian: Dirk Eddelbuettel <eddNOSPAMdebian.org>
+RPM: Tom Moertel <tomNOSPAMmoertel.com>
+SuSe: Detlef Steuer <steuerNOSPAMhsu-hh.de>
--- /dev/null
+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.
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+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 <ess-help-requestNOSPAMr-project.org>; contributions
+to the list may be mailed to <ess-helpNOSPAMr-project.org>. 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 on Emacs and XEmacs.
+ * suggestions for improvements.
+ * announcements of new releases of ESS.
+ * posting small patches to ESS.
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+;;; make-regexp.el --- generate efficient regexps to match strings.
+
+;; Copyright (C) 1994, 1995 Simon Marshall.
+
+;; Author: Simon Marshall <simonNOSPAMgnu.ai.mit.edu>
+;; Keywords: lisp, matching
+;; Version: 1.02
+
+;; LCD Archive Entry:
+;; make-regexp|Simon Marshall|simonNOSPAMgnu.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 <simonNOSPAMgnu.ai.mit.edu>
+
+;; 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
--- /dev/null
+;;; mouseme.el --- mouse menu with commands that operate on strings
+
+;; Copyright (C) 1997 by Free Software Foundation, Inc.
+
+;; Author: Howard Melman <howardNOSPAMsilverstream.com>
+;; 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:
+;; <URL:http://foo.bar.com/sss/ss.html>
+;; <http://foo.bar.com/sss/ss.html>
+;; http://foo.bar.com/sss/ss.html
+;; http://www.ditherdog.com/howard/
+;; mailto:howardNOSPAMsilverstream.com
+;; howardNOSPAMsilverstream.com
+;; <howardNOSPAMsilverstream.com>
+;; import com.sssw.srv.agents.AgentsRsrc;
+;; public AgoHttpRequestEvent(Object o, String db, Request r)
+;; <DIV><A href=3D"http://www.amazon.com/exec/obidos/ASIN/156592391X"><IMG =
+;; <A HREF="http://www.suntimes.com/ebert/ebert.html">
+;; 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
--- /dev/null
+This is news.info, produced by makeinfo version 6.5 from news.texi.
+
+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" <ess-config-here>)' 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 invokations
+ 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 commond 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 insterting 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 initialisation 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 recognised when
+ they are function definitions or function calls.
+ * ESS[R]: Backquoted names and '%op%' operators are recognised 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
+
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+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 '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 <https://github.com/emacs-ess/ESS/pull/65>
+ * 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;
+ <https://ess.r-project.org/Manual/ess.html>
+ * 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.VehtariNOSPAMhut.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:brendanNOSPAMessex.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:brahmNOSPAMalum.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.
+
+
+\1f
+Tag Table:
+\1f
+End Tag Table
--- /dev/null
+This is readme.info, produced by makeinfo version 6.5 from readme.texi.
+
+\1f
+File: readme.info, Node: General Information
+
+1 General Information: README
+*****************************
+
+This is the README file for the distribution of ESS version 18.10.2
+
+ ESS is a GNU Emacs and XEmacs mode 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
+(<rossiniNOSPAMblindglobe.net>) did the initial port to XEmacs and has been
+the primary coder. Martin Maechler (<maechlerNOSPAMstat.math.ethz.ch>) and
+Kurt Hornik (<Kurt.HornikNOSPAMR-project.org>) have assisted with the S
+family and XLispStat. Stephen Eglen (<stephenNOSPAMgnu.org>) has worked
+mostly on R support. Richard M. Heiberger (<rmhNOSPAMtemple.edu>) has
+assisted with S/S-PLUS development for Windows. Richard and Rodney A.
+Sparapani (<rsparapaNOSPAMmcw.edu>) 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::
+
+\1f
+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.
+
+\1f
+File: readme.info, Node: Installation, Next: Starting up, Prev: License, Up: General Information
+
+1.2 Installation
+================
+
+ESS supports GNU Emacs versions 24.3 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::
+
+\1f
+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.
+
+\1f
+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: <https://github.com/emacs-ess/ESS>. '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.
+
+\1f
+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.
+
+\1f
+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'.
+
+\1f
+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'.
+
+\1f
+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
+
+\1f
+File: readme.info, Node: New Features, Next: Reporting Bugs, Prev: Current Features, Up: General Information
+
+1.9 New Features
+================
+
+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" <ess-config-here>)' 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 invokations
+ 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 commond 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 insterting 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 initialisation 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 recognised when
+ they are function definitions or function calls.
+ * ESS[R]: Backquoted names and '%op%' operators are recognised 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
+
+\1f
+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 <ESS-bugsNOSPAMr-project.org>,
+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.
+
+\1f
+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 <ess-help-requestNOSPAMr-project.org>; contributions
+to the list may be mailed to <ess-helpNOSPAMr-project.org>. 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 on Emacs and XEmacs.
+ * suggestions for improvements.
+ * announcements of new releases of ESS.
+ * posting small patches to ESS.
+
+\1f
+File: readme.info, Node: Authors, Prev: Mailing Lists, Up: General Information
+
+1.12 Authors
+============
+
+ * A.J. Rossini (mailto:blindglobeNOSPAMgmail.com)
+ * Richard M. Heiberger (mailto:rmhNOSPAMtemple.edu)
+ * Kurt Hornik (mailto:Kurt.HornikNOSPAMR-project.org)
+ * Martin Maechler (mailto:maechlerNOSPAMstat.math.ethz.ch)
+ * Rodney A. Sparapani (mailto:rsparapaNOSPAMmcw.edu)
+ * Stephen Eglen (mailto:stephenNOSPAMgnu.org)
+ * Sebastian P. Luque (mailto:spluqueNOSPAMgmail.com)
+ * Henning Redestig (mailto:henning.redNOSPAMgooglemail.com)
+ * Vitalie Spinu (mailto:spinuvitNOSPAMgmail.com)
+ * Lionel Henry (mailto:lionel.hryNOSPAMgmail.com)
+ * J. Alexander Branham (mailto:alex.branhamNOSPAMgmail.com)
+
+
+\1f
+Tag Table:
+Node: General Information\7f73
+Node: License\7f1711
+Node: Installation\7f2381
+Node: Installing from a third-party repository\7f3298
+Node: Installing from source\7f4248
+Node: Activating and Loading ESS\7f5843
+Node: Check Installation\7f6920
+Node: Starting up\7f7143
+Node: Current Features\7f7526
+Node: New Features\7f9076
+Node: Reporting Bugs\7f22834
+Node: Mailing Lists\7f23732
+Node: Authors\7f24468
+\1f
+End Tag Table
--- /dev/null
+This is requires.info, produced by makeinfo version 6.5 from
+requires.texi.
+
+ESS supports GNU Emacs versions 24.3 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.
+
+\1f
+Tag Table:
+\1f
+End Tag Table