1- ; ;; ess-r-mode.el --- R customization
1+ ; ;; ess-r-mode.el --- R customization -*- lexical-binding : t ; -*-
22
33; ; Copyright (C) 1997-2020 Free Software Foundation, Inc.
44; ; Author: A.J. Rossini
@@ -83,18 +83,9 @@ access."
8383; ; TODO: Refactor so as to not rely on dynamic scoping. After that
8484; ; refactor, also remove the file-local-variable byte-compile-warnings
8585; ; (not lexical) at the bottom.
86- (defvar block )
8786(defvar containing-sexp )
8887(defvar indent-point )
89- (defvar infinite )
90- (defvar last-newline )
91- (defvar last-pos )
92- (defvar offset )
93- (defvar prefix-break )
9488(defvar prev-containing-sexp )
95- (defvar start-pos )
96- (defvar style )
97- (defvar type )
9889
9990(define-obsolete-variable-alias 'ess-r-versions 'ess-r-runner-prefixes " ESS 19.04" )
10091(defcustom ess-r-runner-prefixes
@@ -1516,9 +1507,7 @@ load is successful, and nil otherwise."
15161507 (let ((loader (ess-file-content (expand-file-name " ESSR/LOADREMOTE" ess-etc-directory))))
15171508 (or (with-temp-message " Fetching and loading ESSR into the remote ..."
15181509 (ess-boolean-command (format loader essr-version)))
1519- (let* ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string )))
1520- (src-dir (expand-file-name " ESSR/R" ess-etc-directory))
1521- (files (directory-files src-dir t " \\ .R\\ '" )))
1510+ (let ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string ))))
15221511 (message (format " Couldn't load or download ESSR.rds on the remote.\n Error: %s \n Injecting local copy of ESSR. " errmsg))
15231512 nil ))))
15241513
@@ -1895,10 +1884,12 @@ Returns nil if line starts inside a string, t if in a comment."
18951884 (ess-calculate-indent--args-open-delim))
18961885 ; ; Indent from attached name
18971886 ((eq type 'prev-call )
1898- (ess-calculate-indent--args-prev-call))
1887+ (ess-calculate-indent--args-prev-call block ))
18991888 ; ; Indent from previous line indentation
19001889 ((eq type 'prev-line )
1901- (ess-calculate-indent--args-prev-line))
1890+ (let ((out (ess-calculate-indent--args-prev-line type block offset)))
1891+ (setq offset (pop out))
1892+ (pop out)))
19021893 (t
19031894 (error " Malformed offset " )))))
19041895 (if max-col
@@ -1909,7 +1900,7 @@ Returns nil if line starts inside a string, t if in a comment."
19091900 (forward-char )
19101901 (current-column ))
19111902
1912- (defun ess-calculate-indent--args-prev-call ()
1903+ (defun ess-calculate-indent--args-prev-call (block )
19131904 ; ; Handle brackets chains such as ][ (cf data.table)
19141905 (ess-climb-chained-delims)
19151906 ; ; Handle call chains
@@ -1927,7 +1918,7 @@ Returns nil if line starts inside a string, t if in a comment."
19271918 (+ (ess-offset 'block ) (current-column ))
19281919 (current-column )))
19291920
1930- (defun ess-calculate-indent--args-prev-line ()
1921+ (defun ess-calculate-indent--args-prev-line (type block offset )
19311922 (ess-at-indent-point
19321923 (cond
19331924 ; ; Closing delimiters are actually not indented at
@@ -1936,13 +1927,13 @@ Returns nil if line starts inside a string, t if in a comment."
19361927 (ess-up-list -1 )
19371928 (when (looking-at " {" )
19381929 (ess-climb-block-prefix))
1939- (current-indentation ))
1930+ (list offset ( current-indentation ) ))
19401931 ; ; Function blocks need special treatment
19411932 ((and (eq type 'prev-line )
19421933 (eq block 'fun-decl ))
19431934 (goto-char containing-sexp)
19441935 (ess-climb-block-prefix)
1945- (current-indentation ))
1936+ (list offset ( current-indentation ) ))
19461937 ; ; Regular case
19471938 (t
19481939 ; ; Find next non-empty line to indent from
@@ -1958,15 +1949,16 @@ Returns nil if line starts inside a string, t if in a comment."
19581949 ; ; The following ensures that only the first line
19591950 ; ; counts. Otherwise consecutive statements would get
19601951 ; ; increasingly more indented.
1961- (when (and block
1962- containing-sexp
1963- (not (eq block 'unbraced ))
1964- (save-excursion
1965- (/= (line-number-at-pos )
1966- (progn (goto-char containing-sexp)
1967- (line-number-at-pos )))))
1968- (setq offset 0 ))
1969- (current-indentation )))))
1952+ (let ((offset (if (and block
1953+ containing-sexp
1954+ (not (eq block 'unbraced ))
1955+ (save-excursion
1956+ (/= (line-number-at-pos )
1957+ (progn (goto-char containing-sexp)
1958+ (line-number-at-pos )))))
1959+ 0
1960+ offset)))
1961+ (list offset (current-indentation )))))))
19701962
19711963; ; Indentation of arguments needs to keep track of how previous
19721964; ; arguments are indented. If one of those has a smaller indentation,
@@ -2213,118 +2205,128 @@ state.")
22132205 (setq ess-fill--style-level (1+ ess-fill--style-level))))))
22142206 ess-fill--style-level)
22152207
2216- (defun ess-fill-args (&optional style )
2217- (let ((start-pos (point-min ))
2218- (bounds (ess-args-bounds 'marker ))
2219- ; ; Set undo boundaries manually
2220- (undo-inhibit-record-point t )
2221- last-pos last-newline prefix-break
2222- infinite)
2223- (when (not bounds)
2224- (error " Could not find function bounds " ))
2225- (setq style (or style (ess-fill-style 'calls bounds)))
2226- (if (= style 0 )
2227- (progn
2228- (delete-region (car bounds) (marker-position (cadr bounds)))
2229- (insert ess-fill--orig-state)
2230- ; ; Restore the point manually. (save-excursion) wouldn't
2231- ; ; work here because we delete the text rather than just
2232- ; ; modifying it.
2233- (goto-char ess-fill--orig-pos)
2234- (message " Back to original formatting " ))
2235- (when ess-blink-refilling
2236- (ess-blink-region (nth 2 bounds)
2237- (1+ (marker-position (cadr bounds)))))
2238- (undo-boundary )
2239- (save-excursion
2240- (ess-fill--unroll-lines bounds t )
2241- (cond
2242- ; ; Some styles start with first argument on a newline
2243- ((and (memq style '(2 4 ))
2244- ess-fill-calls-newlines
2245- (not (looking-at " [ \t ]*#" )))
2246- (newline-and-indent ))
2247- ; ; Third level, start a newline after N arguments
2248- ((and (= style 3 )
2249- (not (looking-at " [ \t ]*#" )))
2250- (let ((i (if (numberp current-prefix-arg)
2251- current-prefix-arg
2252- 1 )))
2253- (while (and (> i 0 )
2254- (ess-jump-arg)
2255- (ess-jump-char " ," ))
2256- (setq i (1- i))))
2257- (newline-and-indent )))
2258- (ess-fill-args--roll-lines)
2259- ; ; Reindent surrounding context
2260- (ess-indent-call (car bounds)))
2261- ; ; Signal marker for garbage collection
2262- (set-marker (cadr bounds) nil )
2263- (undo-boundary ))))
2264-
2265- (defun ess-fill-args--roll-lines ()
2266- (while (and (not (looking-at " [])]" ))
2267- (/= (point ) (or last-pos 1 ))
2268- (not infinite))
2269- (setq prefix-break nil )
2270- ; ; Record start-pos as future breaking point to avoid breaking
2271- ; ; at `=' sign
2272- (while (looking-at " [ \t ]*[\n #]" )
2273- (forward-line )
2274- (back-to-indentation ))
2275- (setq start-pos (point ))
2276- (while (and (< (current-column ) fill-column)
2277- (not (looking-at " [])]" ))
2278- (/= (point ) (or last-pos 1 ))
2279- ; ; Break after one pass if prefix is active
2280- (not prefix-break))
2281- (when (memq style '(2 3 ))
2282- (setq prefix-break t ))
2283- (ess-jump-token " ," )
2284- (setq last-pos (point ))
2285- ; ; Jump expression and any continuations. Reindent all lines
2286- ; ; that were jumped over
2287- (let ((cur-line (line-number-at-pos ))
2288- end-line)
2289- (cond ((ess-jump-arg)
2290- (setq last-newline nil ))
2291- ((ess-token-after= " ," )
2292- (setq last-newline nil )
2293- (setq last-pos (1- (point )))))
2208+ (let (_)
2209+ ; ; FIXME: Transform these dynamic bindings to a state object
2210+ (defvar ess--infinite )
2211+ (defvar ess--prefix-break )
2212+ (defvar ess--start-pos )
2213+ (defvar ess--last-pos )
2214+ (defvar ess--last-newline )
2215+
2216+ (declare-function ess-fill-args--roll-lines " ess-r-mode" )
2217+
2218+ (defun ess-fill-args (&optional style )
2219+ (let ((ess--start-pos (point-min ))
2220+ (bounds (ess-args-bounds 'marker ))
2221+ ; ; Set undo boundaries manually
2222+ (undo-inhibit-record-point t )
2223+ ess--last-pos ess--last-newline ess--prefix-break
2224+ ess--infinite)
2225+ (when (not bounds)
2226+ (error " Could not find function bounds " ))
2227+ (setq style (or style (ess-fill-style 'calls bounds)))
2228+ (if (= style 0 )
2229+ (progn
2230+ (delete-region (car bounds) (marker-position (cadr bounds)))
2231+ (insert ess-fill--orig-state)
2232+ ; ; Restore the point manually. (save-excursion) wouldn't
2233+ ; ; work here because we delete the text rather than just
2234+ ; ; modifying it.
2235+ (goto-char ess-fill--orig-pos)
2236+ (message " Back to original formatting " ))
2237+ (when ess-blink-refilling
2238+ (ess-blink-region (nth 2 bounds)
2239+ (1+ (marker-position (cadr bounds)))))
2240+ (undo-boundary )
22942241 (save-excursion
2295- (when (< cur-line (line-number-at-pos ))
2296- (setq end-line (line-number-at-pos ))
2297- (ess-goto-line (1+ cur-line))
2298- (while (and (<= (line-number-at-pos ) end-line)
2299- (/= (point ) (point-max )))
2300- (funcall indent-line-function)
2301- (forward-line ))))))
2302- (when (or (>= (current-column ) fill-column)
2303- prefix-break
2304- ; ; Ensures closing delim on a newline
2305- (and (= style 4 )
2306- (looking-at " [ \t ]*[])]" )
2307- (setq last-pos (point ))))
2308- (if (and last-pos (/= last-pos start-pos))
2309- (goto-char last-pos)
2310- (ess-jump-char " ," ))
2311- (cond ((looking-at " [ \t ]*[#\n ]" )
2312- (forward-line )
2313- (funcall indent-line-function)
2314- (setq last-newline nil ))
2315- ; ; With levels 2 and 3, closing delim goes on a newline
2316- ((looking-at " [ \t ]*[])]" )
2317- (when (and (memq style '(2 3 4 ))
2318- ess-fill-calls-newlines
2319- (not last-newline))
2242+ (ess-fill--unroll-lines bounds t )
2243+ (cond
2244+ ; ; Some styles start with first argument on a newline
2245+ ((and (memq style '(2 4 ))
2246+ ess-fill-calls-newlines
2247+ (not (looking-at " [ \t ]*#" )))
2248+ (newline-and-indent ))
2249+ ; ; Third level, start a newline after N arguments
2250+ ((and (= style 3 )
2251+ (not (looking-at " [ \t ]*#" )))
2252+ (let ((i (if (numberp current-prefix-arg)
2253+ current-prefix-arg
2254+ 1 )))
2255+ (while (and (> i 0 )
2256+ (ess-jump-arg)
2257+ (ess-jump-char " ," ))
2258+ (setq i (1- i))))
2259+ (newline-and-indent )))
2260+ (ess-fill-args--roll-lines style)
2261+ ; ; Reindent surrounding context
2262+ (ess-indent-call (car bounds)))
2263+ ; ; Signal marker for garbage collection
2264+ (set-marker (cadr bounds) nil )
2265+ (undo-boundary ))))
2266+
2267+ (defun ess-fill-args--roll-lines (style )
2268+ (while (and (not (looking-at " [])]" ))
2269+ (/= (point ) (or ess--last-pos 1 ))
2270+ (not ess--infinite))
2271+ (setq ess--prefix-break nil )
2272+ ; ; Record ess--start-pos as future breaking point to avoid breaking
2273+ ; ; at `=' sign
2274+ (while (looking-at " [ \t ]*[\n #]" )
2275+ (forward-line )
2276+ (back-to-indentation ))
2277+ (setq ess--start-pos (point ))
2278+ (while (and (< (current-column ) fill-column)
2279+ (not (looking-at " [])]" ))
2280+ (/= (point ) (or ess--last-pos 1 ))
2281+ ; ; Break after one pass if prefix is active
2282+ (not ess--prefix-break))
2283+ (when (memq style '(2 3 ))
2284+ (setq ess--prefix-break t ))
2285+ (ess-jump-token " ," )
2286+ (setq ess--last-pos (point ))
2287+ ; ; Jump expression and any continuations. Reindent all lines
2288+ ; ; that were jumped over
2289+ (let ((cur-line (line-number-at-pos ))
2290+ end-line)
2291+ (cond ((ess-jump-arg)
2292+ (setq ess--last-newline nil ))
2293+ ((ess-token-after= " ," )
2294+ (setq ess--last-newline nil )
2295+ (setq ess--last-pos (1- (point )))))
2296+ (save-excursion
2297+ (when (< cur-line (line-number-at-pos ))
2298+ (setq end-line (line-number-at-pos ))
2299+ (ess-goto-line (1+ cur-line))
2300+ (while (and (<= (line-number-at-pos ) end-line)
2301+ (/= (point ) (point-max )))
2302+ (funcall indent-line-function)
2303+ (forward-line ))))))
2304+ (when (or (>= (current-column ) fill-column)
2305+ ess--prefix-break
2306+ ; ; Ensures closing delim on a newline
2307+ (and (= style 4 )
2308+ (looking-at " [ \t ]*[])]" )
2309+ (setq ess--last-pos (point ))))
2310+ (if (and ess--last-pos (/= ess--last-pos ess--start-pos))
2311+ (goto-char ess--last-pos)
2312+ (ess-jump-char " ," ))
2313+ (cond ((looking-at " [ \t ]*[#\n ]" )
2314+ (forward-line )
2315+ (funcall indent-line-function)
2316+ (setq ess--last-newline nil ))
2317+ ; ; With levels 2 and 3, closing delim goes on a newline
2318+ ((looking-at " [ \t ]*[])]" )
2319+ (when (and (memq style '(2 3 4 ))
2320+ ess-fill-calls-newlines
2321+ (not ess--last-newline))
2322+ (newline-and-indent )
2323+ ; ; Prevent indenting infinitely
2324+ (setq ess--last-newline t )))
2325+ ((not ess--last-newline)
23202326 (newline-and-indent )
2321- ; ; Prevent indenting infinitely
2322- (setq last-newline t )))
2323- ((not last-newline)
2324- (newline-and-indent )
2325- (setq last-newline t ))
2326- (t
2327- (setq infinite t ))))))
2327+ (setq ess--last-newline t ))
2328+ (t
2329+ (setq ess--infinite t )))))))
23282330
23292331(defun ess-fill-continuations (&optional style )
23302332 (let ((bounds (ess-continuations-bounds 'marker ))
@@ -2895,9 +2897,4 @@ given field. Options should be separated by value of
28952897
28962898(provide 'ess-r-mode )
28972899
2898- ; ;; Local variables:
2899- ; ;; mode: emacs-lisp
2900- ; ;; byte-compile-warnings: (not lexical)
2901- ; ;; End:
2902-
29032900; ;; ess-r-mode.el ends here
0 commit comments