Subject: bug#27503: closed (Re: bug#27503: 26.0.50; Not lining up Javascript arguments)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 03 Jul 2017 21:02:02 +0000

Your bug report

#27503: 26.0.50; Not lining up Javascript arguments

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
27503: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=27503
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#27503: 26.0.50; Not lining up Javascript arguments
From: Dmitry Gutov <[email-masked]>
To: Ingo Lohmar <[email-masked]>
Cc: [email-masked], James Nguyen <[email-masked]>, [email-masked]
Date: Tue, 4 Jul 2017 00:01:07 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

Version: 26.1

On 7/3/17 9:21 PM, Ingo Lohmar wrote:
> tags 27503 fixed
> close 27503 26.1
> quit

The capricious bug tracker doesn't want to understand this: the bug was 
still open. Should be closed now (see the first Cc: address).

Subject: 26.0.50; Not lining up Javascript arguments
From: James Nguyen <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Date: Mon, 26 Jun 2017 18:49:59 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

I'd like to have js-mode line up arguments normally instead of lining up
arg-wise.

For example:

function functionName(arg1,
                                     arg2) {}

vs

function functionName(arg1,
  arg2)

I think js-mode only support the former at this point. The latter seems
to be fairly common so it'd be great if we could support it.

Following this:
https://emacs.stackexchange.com/questions/29973/stop-javascript-mode-from-lining-up-function-parameters-after-newline/29975#29975

seems to give accurate indentation similar to other editors.

(defun javascript/indent-args (parse-status)
    "Return the proper indentation for the current line."
    (save-excursion
      (back-to-indentation)
      (cond ((nth 4 parse-status)    ; inside comment
             (js--get-c-offset 'c (nth 8 parse-status)))
            ((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--chained-expression-p))
            ((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 "[]})]"))
                   (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
               (progn ; nothing following the opening paren/bracket
                 (skip-syntax-backward " ")
                 (when (eq (char-before) ?\)) (backward-list))
                 (back-to-indentation)
                 (js--maybe-goto-declaration-keyword-end parse-status)
                 (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)))))

            ((js--continued-expression-p)
             (+ js-indent-level js-expr-indent-offset))
            (t (prog-first-column)))))

  (advice-add 'js--proper-indentation :override 'javascript/indent-args)
  
1. This removes an entire if block check. That is probably doing
something I'm not aware of.

2. We probably want to make it configuration either way (something
similar to js-comment-lineup-func (but that seems to only be for comments.))

Some source code to play with is:

  #+begin_src mhtml :tangle yes
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Lifecycle</title>
    <style>
      body, textarea {
        font-family: Courier;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <!-- my app renders here -->
    </div>
    <script src="react/build/react.js"></script>
    <script src="react/build/react-dom.js"></script>
    <script>
      var logMixin = {
        _log: function(methodName, args) {
          console.log(this.name + '::' + methodName, args);
        },
        componentWillUpdate:  function() {this._log('componentWillUpdate',  arguments);},
        componentDidUpdate:   function() {this._log('componentDidUpdate',   arguments);},
        componentWillMount:   function() {this._log('componentWillMount',   arguments);},
        componentDidMount:    function() {this._log('componentDidMount',    arguments);},
        componentWillUnmount: function() {this._log('componentWillUnmount', arguments);},
      };

      var TextAreaCounter = React.createClass({
        name: 'TextAreaCounter',
        mixins: [logMixin],

        propTypes: {
          defaultValue: React.PropTypes.string,
        },

        getInitialState: function() {
          return {
            text: this.props.defaultValue,
          };
        },

        _textChange: function(ev) {
          this.setState({
            text: ev.target.value,
          });
        },

        render: function() {
          return React.DOM.div(null,
            React.DOM.textarea({
              value: this.state.text,
              onChange: this._textChange,
            }),
            React.DOM.h3(null, this.state.text.length)
          );
        }
      });

      var myTextAreaCounter = ReactDOM.render(
        React.createElement(TextAreaCounter, {
          defaultValue: "Bob",
        }),
        document.getElementById("app")
      );
    </script>
  </body>
</html>
  #+end_src
  
More specifically:

  #+begin_src mhtml :tangle yes
        render: function() {
          return React.DOM.div(null,
            React.DOM.textarea({
              value: this.state.text,
              onChange: this._textChange,
            }),
            React.DOM.h3(null, this.state.text.length)
          );
        }
  #+end_src
  
With the current indent settings, we get:

  #+begin_src mhtml :tangle yes
        render: function() {
          return React.DOM.div(null,
                               React.DOM.textarea({
                                 value: this.state.text,
                                 onChange: this._textChange,
                               }),
                               React.DOM.h3(null, this.state.text.length)
                              );
        }
  #+end_src
  
With the above advice:

#+begin_src mhtml :tangle yes
        render: function() {
          return React.DOM.div(null,
            React.DOM.textarea({
              value: this.state.text,
              onChange: this._textChange,
            }),
            React.DOM.h3(null, this.state.text.length)
          );
        }
#+end_src

In GNU Emacs 26.0.50 (build 4, x86_64-apple-darwin16.5.0, NS appkit-1504.82 Version 10.12.4 (Build 16E195))
of 2017-06-24 built on jamesretina.local
Repository revision: 16d2695674a4c8abbec846c427fe8abef97e07ef
Windowing system distributor 'Apple', version 10.3.1504
Recent messages:
The following feature was found in load-path, please check if that’s correct:
(obarray)
Successfully reloaded Org
Org-mode version 8.2.10 (release_8.2.10 @ /Users/james/Code/emacs/nextstep/Emacs.app/Contents/Resources/lisp/org/)
Mark set
Configuring package helm...
Configuring package tramp...done
Configuring package helm...done (0.310s)
Configuring package helm-flx...done
Configuring package helm-fuzzier...done

Configured using:
'configure --with-ns'

Configured features:
JPEG RSVG NOTIFY ACL GNUTLS LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Org

Minor modes in effect:
  helm-fuzzier-mode: t
  helm-flx-mode: t
  helm-mode: t
  helm-autoresize-mode: t
  helm--remap-mouse-mode: t
  shell-dirtrack-mode: t
  focus-autosave-mode: t
  company-quickhelp-mode: t
  company-quickhelp-local-mode: t
  eval-sexp-fu-flash-mode: t
  flycheck-pos-tip-mode: t
  shackle-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  global-company-mode: t
  company-mode: t
  global-evil-surround-mode: t
  evil-surround-mode: t
  global-evil-visualstar-mode: t
  evil-visualstar-mode: t
  global-evil-matchit-mode: t
  evil-matchit-mode: t
  evil-mode: t
  evil-local-mode: t
  global-undo-tree-mode: t
  undo-tree-mode: t
  recentf-mode: t
  ivy-mode: t
  smartparens-global-mode: t
  smartparens-mode: t
  global-hungry-delete-mode: t
  hungry-delete-mode: t
  ws-butler-global-mode: t
  ws-butler-mode: t
  show-paren-mode: t
  global-auto-revert-mode: t
  winner-mode: t
  override-global-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  mouse-wheel-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
/Users/james/.emacs.d/elpa/26/color-theme-solarized-20160626.743/solarized-theme hides /Users/james/.emacs.d/elpa/26/solarized-theme-20170430.800/solarized-theme
~/.emacs.d/fork/evil/evil hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil
~/.emacs.d/fork/evil/evil-vars hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-vars
~/.emacs.d/fork/evil/evil-types hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-types
~/.emacs.d/fork/evil/evil-states hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-states
~/.emacs.d/fork/evil/evil-search hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-search
~/.emacs.d/fork/evil/evil-repeat hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-repeat
~/.emacs.d/fork/evil/evil-pkg hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-pkg
~/.emacs.d/fork/evil/evil-maps hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-maps
~/.emacs.d/fork/evil/evil-macros hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-macros
~/.emacs.d/fork/evil/evil-jumps hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-jumps
~/.emacs.d/fork/evil/evil-integration hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-integration
~/.emacs.d/fork/evil/evil-ex hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-ex
~/.emacs.d/fork/evil/evil-digraphs hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-digraphs
~/.emacs.d/fork/evil/evil-core hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-core
~/.emacs.d/fork/evil/evil-common hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-common
~/.emacs.d/fork/evil/evil-commands hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-commands
~/.emacs.d/fork/evil/evil-command-window hides /Users/james/.emacs.d/elpa/26/evil-20170615.1320/evil-command-window

Features:
(shadow sort mail-extr emacsbug message rfc822 mml mml-sec epa epg
mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils
mailheader sendmail helm-fuzzier helm-flx helm-smex helm-command
helm-elisp helm-eval helm-mode helm-files image-dired tramp tramp-compat
tramp-loaddefs trampver parse-time dired-x dired-aux helm-buffers
helm-tags helm-bookmark helm-adaptive helm-info bookmark pp helm-locate
helm-grep helm-regexp helm-external helm-net helm-utils compile
helm-help helm-types helm helm-source eieio-compat helm-multi-match
helm-lib async smex ido loadhist solarized-light-theme solarized add-log
server pulse shell tabify org-element org-rmail org-mhe org-irc org-info
org-gnus org-docview doc-view image-mode dired dired-loaddefs org-bibtex
bibtex org-bbdb org-w3m org org-macro org-footnote org-pcomplete
pcomplete org-list org-faces org-entities org-version ob-emacs-lisp ob
ob-tangle ob-ref ob-lob ob-table ob-exp org-src ob-keys ob-comint comint
ansi-color ob-core ob-eval org-compat org-macs org-loaddefs JJ-org
cursor-sensor mhtml-mode rainbow-mode xterm-color css-mode smie eww puny
mm-url gnus nnheader gnus-util rmail rmail-loaddefs rfc2047 rfc2045
ietf-drums mail-utils mm-util mail-prsvr url-queue url url-proxy
url-privacy url-expand url-methods url-history url-cookie url-domsuf
url-util mailcap shr svg xml browse-url format-spec js cc-mode cc-fonts
cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs
smartparens-html sgml-mode dom JJ-web focus-autosave-mode JJ-security
colir color counsel jka-compr esh-util rainbow-delimiters
evil-cleverparens evil-cleverparens-text-objects evil-cleverparens-util
paredit lispyville lispy swiper iedit iedit-lib multiple-cursors-core
lispy-inline avy semantic/db eieio-base semantic/util-modes
semantic/util semantic semantic/tag semantic/lex semantic/fw mode-local
cedet ediff-merg ediff-wind ediff-diff ediff-mult ediff-help ediff-init
ediff-util ediff help-fns radix-tree lispy-tags elisp-slime-nav
eval-sexp-fu company-quickhelp warnings highlight font-lock+
flycheck-pos-tip pos-tip flycheck json map find-func shackle
JJ-extra-lang make-mode JJ-elisp edebug-x edebug which-func imenu
JJ-autocomplete elixir-yasnippets yasnippet company-oddmuse
company-keywords company-etags etags xref project company-gtags
company-files company-capf company-cmake company-xcode company-clang
company-semantic company-eclim company-template company-css company-nxml
company-dabbrev-code company-dabbrev company-yasnippet company-bbdb
company JJ-evil evil-surround evil-visualstar evil-matchit evil
evil-integration evil-maps evil-commands flyspell ispell evil-jumps
evil-command-window evil-types evil-search evil-ex evil-macros
evil-repeat evil-states evil-core evil-common derived rect evil-digraphs
evil-vars undo-tree diff JJ-project recentf tree-widget wid-edit ivy flx
delsel ivy-overlay ffap JJ-pair-editing smartparens-config smartparens
thingatpt JJ-misc fold-dwim-org fold-dwim hideshow noutline outline
windmove hungry-delete ws-butler JJ-platform exec-path-from-shell
ls-lisp JJ-defaults paren whitespace autorevert filenotify winner
JJ-theme foggy-night-theme cl-extra help-mode theme-changer solar
cal-dst cal-menu calendar cal-loaddefs cl JJ-dependencies hydra ring lv
s dash JJ-funcs subr-x use-package diminish bind-key easy-mmode
finder-inf edmacro kmacro rx advice slime-autoloads info package
easymenu epg-config url-handlers url-parse auth-source cl-seq eieio
eieio-core cl-macs eieio-loaddefs password-cache url-vars seq byte-opt
gv bytecomp byte-compile cconv cl-loaddefs pcase cl-lib time-date
tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type
mwheel term/ns-win ns-win ucs-normalize mule-util term/common-win
tool-bar dnd fontset image regexp-opt fringe tabulated-list replace
newcomment text-mode elisp-mode lisp-mode prog-mode register page
menu-bar rfn-eshadow isearch timer select scroll-bar mouse jit-lock
font-lock syntax facemenu font-core term/tty-colors frame cl-generic
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite charscript charprop
case-table epa-hook jka-cmpr-hook help simple abbrev obarray minibuffer
cl-preloaded nadvice loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote kqueue cocoa ns
multi-tty make-network-process emacs)

Memory information:
((conses 16 892577 534002)
(symbols 48 60548 281)
(miscs 40 882 3402)
(strings 32 161034 279476)
(string-bytes 1 5481778)
(vectors 16 98335)
(vector-slots 8 2434861 513384)
(floats 8 884 2213)
(intervals 56 6906 1373)
(buffers 976 24))