Port indentation code from js2-mode to js-mode
* lisp/progmodes/js.el (js-auto-indent-flag): Remove, was unused. (js-switch-indent-offset): New option. (js--proper-indentation): Use it. And handle the case when "default" is actually a key in an object literal. (js--same-line): New function. (js--multi-line-declaration-indentation): Use it. (js--indent-in-array-comp, js--array-comp-indentation): New functions. (js--proper-indentation): Use them, to handle array comprehension continuations.
This commit is contained in:
parent
3629130880
commit
47e59c666a
4 changed files with 152 additions and 25 deletions
11
etc/NEWS
11
etc/NEWS
|
@ -661,6 +661,17 @@ whether it is safe to use Bash's --noediting option. These days
|
|||
|
||||
*** Add more Ruby file types to `auto-mode-alist'.
|
||||
|
||||
** JS Mode
|
||||
|
||||
*** Better indentation of multiple-variable declarations.
|
||||
If declaration spans several lines, variables on the following lines
|
||||
are lined up to the first one.
|
||||
|
||||
*** We now recognize and better indent continuations in array
|
||||
comprehensions.
|
||||
|
||||
*** New option `js-switch-indent-offset`.
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 24.4
|
||||
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
2013-12-08 Dmitry Gutov <dgutov@yandex.ru>
|
||||
|
||||
* progmodes/js.el (js-auto-indent-flag): Remove, was unused.
|
||||
(js-switch-indent-offset): New option.
|
||||
(js--proper-indentation): Use it. And handle the case when
|
||||
"default" is actually a key in an object literal.
|
||||
(js--same-line): New function.
|
||||
(js--multi-line-declaration-indentation): Use it.
|
||||
(js--indent-in-array-comp, js--array-comp-indentation): New
|
||||
functions.
|
||||
(js--proper-indentation): Use them, to handle array comprehension
|
||||
continuations.
|
||||
|
||||
2013-12-08 Leo Liu <sdl.web@gmail.com>
|
||||
|
||||
* progmodes/flymake.el (flymake-highlight-line): Re-write.
|
||||
|
|
|
@ -459,12 +459,13 @@ The value must be no less than minus `js-indent-level'."
|
|||
:group 'js
|
||||
:version "24.1")
|
||||
|
||||
(defcustom js-auto-indent-flag t
|
||||
"Whether to automatically indent when typing punctuation characters.
|
||||
If non-nil, the characters {}();,: also indent the current line
|
||||
in Javascript mode."
|
||||
:type 'boolean
|
||||
:group 'js)
|
||||
(defcustom js-switch-indent-offset 0
|
||||
"Number of additional spaces for indenting the contents of a switch block.
|
||||
The value must not be negative."
|
||||
:type 'integer
|
||||
:safe 'integerp
|
||||
:group 'js
|
||||
:version "24.4")
|
||||
|
||||
(defcustom js-flat-functions nil
|
||||
"Treat nested functions as top-level functions in `js-mode'.
|
||||
|
@ -1766,6 +1767,10 @@ nil."
|
|||
(list (cons 'c js-comment-lineup-func))))
|
||||
(c-get-syntactic-indentation (list (cons symbol anchor)))))
|
||||
|
||||
(defun js--same-line (pos)
|
||||
(and (>= pos (point-at-bol))
|
||||
(<= pos (point-at-eol))))
|
||||
|
||||
(defun js--multi-line-declaration-indentation ()
|
||||
"Helper function for `js--proper-indentation'.
|
||||
Return the proper indentation of the current line if it belongs to a declaration
|
||||
|
@ -1788,8 +1793,7 @@ statement spanning multiple lines; otherwise, return nil."
|
|||
(looking-at js--indent-operator-re)
|
||||
(js--backward-syntactic-ws))
|
||||
(not (eq (char-before) ?\;)))
|
||||
(and (>= pos (point-at-bol))
|
||||
(<= pos (point-at-eol)))))))
|
||||
(js--same-line pos)))))
|
||||
(condition-case nil
|
||||
(backward-sexp)
|
||||
(scan-error (setq at-opening-bracket t))))
|
||||
|
@ -1797,23 +1801,68 @@ statement spanning multiple lines; otherwise, return nil."
|
|||
(goto-char (match-end 0))
|
||||
(1+ (current-column)))))))
|
||||
|
||||
(defun js--indent-in-array-comp (bracket)
|
||||
"Return non-nil if we think we're in an array comprehension.
|
||||
In particular, return the buffer position of the first `for' kwd."
|
||||
(let ((end (point)))
|
||||
(save-excursion
|
||||
(goto-char bracket)
|
||||
(when (looking-at "\\[")
|
||||
(forward-char 1)
|
||||
(js--forward-syntactic-ws)
|
||||
(if (looking-at "[[{]")
|
||||
(let (forward-sexp-function) ; Use Lisp version.
|
||||
(forward-sexp) ; Skip destructuring form.
|
||||
(js--forward-syntactic-ws)
|
||||
(if (and (/= (char-after) ?,) ; Regular array.
|
||||
(looking-at "for"))
|
||||
(match-beginning 0)))
|
||||
;; To skip arbitrary expressions we need the parser,
|
||||
;; so we'll just guess at it.
|
||||
(if (and (> end (point)) ; Not empty literal.
|
||||
(re-search-forward "[^,]]* \\(for\\) " end t)
|
||||
;; Not inside comment or string literal.
|
||||
(not (nth 8 (parse-partial-sexp bracket (point)))))
|
||||
(match-beginning 1)))))))
|
||||
|
||||
(defun js--array-comp-indentation (bracket for-kwd)
|
||||
(if (js--same-line for-kwd)
|
||||
;; First continuation line.
|
||||
(save-excursion
|
||||
(goto-char bracket)
|
||||
(forward-char 1)
|
||||
(skip-chars-forward " \t")
|
||||
(current-column))
|
||||
(save-excursion
|
||||
(goto-char for-kwd)
|
||||
(current-column))))
|
||||
|
||||
(defun js--proper-indentation (parse-status)
|
||||
"Return the proper indentation for the current line."
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(cond ((nth 4 parse-status)
|
||||
(cond ((nth 4 parse-status) ; inside comment
|
||||
(js--get-c-offset 'c (nth 8 parse-status)))
|
||||
((nth 8 parse-status) 0) ; inside string
|
||||
((js--ctrl-statement-indentation))
|
||||
((js--multi-line-declaration-indentation))
|
||||
((nth 3 parse-status) 0) ; inside string
|
||||
((eq (char-after) ?#) 0)
|
||||
((save-excursion (js--beginning-of-macro)) 4)
|
||||
;; Indent array comprehension continuation lines specially.
|
||||
((let ((bracket (nth 1 parse-status))
|
||||
beg)
|
||||
(and bracket
|
||||
(not (js--same-line bracket))
|
||||
(setq beg (js--indent-in-array-comp bracket))
|
||||
;; At or after the first loop?
|
||||
(>= (point) beg)
|
||||
(js--array-comp-indentation bracket beg))))
|
||||
((js--ctrl-statement-indentation))
|
||||
((js--multi-line-declaration-indentation))
|
||||
((nth 1 parse-status)
|
||||
;; A single closing paren/bracket should be indented at the
|
||||
;; same level as the opening statement. Same goes for
|
||||
;; "case" and "default".
|
||||
(let ((same-indent-p (looking-at
|
||||
"[]})]\\|\\_<case\\_>\\|\\_<default\\_>"))
|
||||
(let ((same-indent-p (looking-at "[]})]"))
|
||||
(switch-keyword-p (looking-at "default\\_>\\|case\\_>[^:]"))
|
||||
(continued-expr-p (js--continued-expression-p)))
|
||||
(goto-char (nth 1 parse-status)) ; go to the opening char
|
||||
(if (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)")
|
||||
|
@ -1821,17 +1870,26 @@ statement spanning multiple lines; otherwise, return nil."
|
|||
(skip-syntax-backward " ")
|
||||
(when (eq (char-before) ?\)) (backward-list))
|
||||
(back-to-indentation)
|
||||
(cond (same-indent-p
|
||||
(current-column))
|
||||
(continued-expr-p
|
||||
(+ (current-column) (* 2 js-indent-level)
|
||||
js-expr-indent-offset))
|
||||
(t
|
||||
(+ (current-column) js-indent-level
|
||||
(pcase (char-after (nth 1 parse-status))
|
||||
(?\( js-paren-indent-offset)
|
||||
(?\[ js-square-indent-offset)
|
||||
(?\{ js-curly-indent-offset))))))
|
||||
(let* ((in-switch-p (unless same-indent-p
|
||||
(looking-at "\\_<switch\\_>")))
|
||||
(same-indent-p (or same-indent-p
|
||||
(and switch-keyword-p
|
||||
in-switch-p)))
|
||||
(indent
|
||||
(cond (same-indent-p
|
||||
(current-column))
|
||||
(continued-expr-p
|
||||
(+ (current-column) (* 2 js-indent-level)
|
||||
js-expr-indent-offset))
|
||||
(t
|
||||
(+ (current-column) js-indent-level
|
||||
(pcase (char-after (nth 1 parse-status))
|
||||
(?\( js-paren-indent-offset)
|
||||
(?\[ js-square-indent-offset)
|
||||
(?\{ js-curly-indent-offset)))))))
|
||||
(if in-switch-p
|
||||
(+ indent js-switch-indent-offset)
|
||||
indent)))
|
||||
;; If there is something following the opening
|
||||
;; paren/bracket, everything else should be indented at
|
||||
;; the same level.
|
||||
|
|
45
test/indent/js.js
Normal file
45
test/indent/js.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
var a = 1;
|
||||
b = 2;
|
||||
|
||||
let c = 1,
|
||||
d = 2;
|
||||
|
||||
var e = 100500,
|
||||
+ 1;
|
||||
|
||||
var f = bar('/protocols/')
|
||||
baz();
|
||||
|
||||
var h = 100500
|
||||
1;
|
||||
|
||||
const i = 1,
|
||||
j = 2;
|
||||
|
||||
var k = 1,
|
||||
l = [
|
||||
1, 2,
|
||||
3, 4
|
||||
],
|
||||
m = 5;
|
||||
|
||||
var n = function() {
|
||||
return 7;
|
||||
},
|
||||
o = 8;
|
||||
|
||||
foo(bar, function() {
|
||||
return 2;
|
||||
});
|
||||
|
||||
switch (b) {
|
||||
case "a":
|
||||
2;
|
||||
default:
|
||||
3;
|
||||
}
|
||||
|
||||
var ;
|
||||
|
||||
var evens = [e for each (e in range(0, 21))
|
||||
if (ed % 2 == 0)];
|
Loading…
Add table
Reference in a new issue