Add new packages installed

This commit is contained in:
Mateus Pinto Rodrigues
2018-03-27 20:52:59 -03:00
parent e684741609
commit 2362e805bd
1493 changed files with 172412 additions and 4636 deletions

View File

@@ -0,0 +1,50 @@
;;; js2-refactor-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "js2-refactor" "js2-refactor.el" (23201 22398
;;;;;; 638114 561000))
;;; Generated autoloads from js2-refactor.el
(autoload 'js2-refactor-mode "js2-refactor" "\
Minor mode providing JavaScript refactorings.
\(fn &optional ARG)" t nil)
(autoload 'js2r-add-keybindings-with-prefix "js2-refactor" "\
Add js2r keybindings using the prefix PREFIX.
\(fn PREFIX)" nil nil)
(autoload 'js2r-add-keybindings-with-modifier "js2-refactor" "\
Add js2r keybindings using the modifier MODIFIER.
\(fn MODIFIER)" nil nil)
;;;***
;;;### (autoloads nil "js2r-vars" "js2r-vars.el" (23201 22398 588114
;;;;;; 487000))
;;; Generated autoloads from js2r-vars.el
(autoload 'js2r-extract-var "js2r-vars" "\
\(fn)" t nil)
;;;***
;;;### (autoloads nil nil ("js2-refactor-pkg.el" "js2r-conditionals.el"
;;;;;; "js2r-conveniences.el" "js2r-formatting.el" "js2r-functions.el"
;;;;;; "js2r-helpers.el" "js2r-iife.el" "js2r-paredit.el" "js2r-wrapping.el")
;;;;;; (23201 22398 628114 552000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; js2-refactor-autoloads.el ends here

View File

@@ -0,0 +1,10 @@
(define-package "js2-refactor" "20180118.251" "A JavaScript refactoring library for emacs."
'((js2-mode "20101228")
(s "1.9.0")
(multiple-cursors "1.0.0")
(dash "1.0.0")
(s "1.0.0")
(yasnippet "0.9.0.1")))
;; Local Variables:
;; no-byte-compile: t
;; End:

View File

@@ -0,0 +1,221 @@
;;; js2-refactor.el --- The beginnings of a JavaScript refactoring library in emacs. -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This is a collection of small refactoring functions to further the idea of a
;; JavaScript IDE in Emacs that started with js2-mode.
;; ## Installation
;; Start by installing the dependencies:
;; * js2-mode https://github.com/mooz/js2-mode/
;; * dash https://github.com/magnars/dash.el
;; * multiple-cursors https://github.com/magnars/multiple-cursors.el
;; It is also recommended to get
;; [expand-region](https://github.com/magnars/expand-region.el) to more easily mark
;; vars, method calls and functions for refactorings.
;; Then add this to your Emacs settings:
;; (require 'js2-refactor)
;; (add-hook 'js2-mode-hook #'js2-refactor-mode)
;; (js2r-add-keybindings-with-prefix "C-c C-m")
;; Note: I am working on a smoother installation path through package.el,
;; but I haven't had the time to whip this project into that sort of
;; structure - yet.
;; ## Usage
;; All refactorings start with `C-c C-m` and then a two-letter mnemonic shortcut.
;; * `ee` is `expand-node-at-point`: Expand bracketed list according to node type at point (array, object, function, call args).
;; * `cc` is `contract-node-at-point`: Contract bracketed list according to node type at point (array, object, function, call args).
;; * `ef` is `extract-function`: Extracts the marked expressions out into a new named function.
;; * `em` is `extract-method`: Extracts the marked expressions out into a new named method in an object literal.
;; * `tf` is `toggle-function-expression-and-declaration`: Toggle between function name() {} and var name = function ();
;; * `ta` is `toggle-arrow-function-and-expression`: Toggle between function expression to arrow function.
;; * `ip` is `introduce-parameter`: Changes the marked expression to a parameter in a local function.
;; * `lp` is `localize-parameter`: Changes a parameter to a local var in a local function.
;; * `wi` is `wrap-buffer-in-iife`: Wraps the entire buffer in an immediately invoked function expression
;; * `ig` is `inject-global-in-iife`: Creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expression
;; * `ag` is `add-to-globals-annotation`: Creates a `/*global */` annotation if it is missing, and adds the var at point to it.
;; * `ev` is `extract-var`: Takes a marked expression and replaces it with a var.
;; * `iv` is `inline-var`: Replaces all instances of a variable with its initial value.
;; * `rv` is `rename-var`: Renames the variable on point and all occurrences in its lexical scope.
;; * `vt` is `var-to-this`: Changes local `var a` to be `this.a` instead.
;; * `ao` is `arguments-to-object`: Replaces arguments to a function call with an object literal of named arguments.
;; * `3i` is `ternary-to-if`: Converts ternary operator to if-statement.
;; * `sv` is `split-var-declaration`: Splits a `var` with multiple vars declared, into several `var` statements.
;; * `ss` is `split-string`: Splits a `string`.
;; * `uw` is `unwrap`: Replaces the parent statement with the selected region.
;; * `lt` is `log-this`: Adds a console.log() statement for what is at point (or region). With a prefix argument, use JSON pretty-printing.
;; * `dt` is `debug-this`: Adds a debug() statement for what is at point (or region).
;; * `sl` is `forward-slurp`: Moves the next statement into current function, if-statement, for-loop or while-loop.
;; * `ba` is `forward-barf`: Moves the last child out of current function, if-statement, for-loop or while-loop.
;; * `k` is `kill`: Kills to the end of the line, but does not cross semantic boundaries.
;; There are also some minor conveniences bundled:
;; * `C-S-down` and `C-S-up` moves the current line up or down. If the line is an
;; element in an object or array literal, it makes sure that the commas are
;; still correctly placed.
;; * `k` `kill-line`: Like `kill-line` but respecting the AST.
;; ## Todo
;; A list of some wanted improvements for the current refactorings.
;; * expand- and contract-array: should work recursively with nested object literals and nested arrays.
;; * expand- and contract-function: should deal better with nested object literals, array declarations, and statements terminated only by EOLs (without semicolons).
;; * wrap-buffer-in-iife: should skip comments and namespace initializations at buffer start.
;; * extract-variable: could end with a query-replace of the expression in its scope.
;; ## Contributions
;; * [Matt Briggs](https://github.com/mbriggs) contributed `js2r-add-to-globals-annotation`
;; * [Alex Chamberlain](https://github.com/apchamberlain) contributed contracting and expanding arrays and functions.
;; * [Nicolas Petton](https://github.com/NicolasPetton) contributed `js2r-kill`
;; Thanks!
;; ## Contribute
;; This project is still in its infancy, and everything isn't quite sorted out
;; yet. If you're eager to contribute, please add an issue here on github and we
;; can discuss your changes a little before diving into the elisp :-).
;; To fetch the test dependencies:
;; $ cd /path/to/multiple-cursors
;; $ git submodule init
;; $ git submodule update
;; Run the tests with:
;; $ ./util/ecukes/ecukes features
;;; Code:
(require 'js2-mode)
(require 'js2r-helpers)
(require 'js2r-formatting)
(require 'js2r-iife)
(require 'js2r-vars)
(require 'js2r-functions)
(require 'js2r-wrapping)
(require 'js2r-conditionals)
(require 'js2r-conveniences)
(require 'js2r-paredit)
(defvar js2-refactor-mode-map
(make-sparse-keymap)
"Keymap for js2-refactor.")
(defvar js2-refactor-keybinding-prefix
nil
"Store keybinding prefix used by js2-refactor.")
;;;###autoload
(define-minor-mode js2-refactor-mode
"Minor mode providing JavaScript refactorings."
:lighter " js2r"
:keymap js2-refactor-mode-map
(when js2-refactor-mode
(yas-minor-mode-on)))
;;; Settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defgroup js2-refactor nil
"Minor mode providing JavaScript refactorings."
:group 'tools
:prefix "js2r-"
:link '(url-link :tag "Repository" "https://github.com/magnars/js2-refactor.el"))
(defcustom js2r-use-strict nil
"When non-nil, js2r inserts strict declarations in IIFEs."
:group 'js2-refactor
:type 'boolean)
(defcustom js2r-prefered-quote-type 1
"The prefered quote style for strings."
:group 'js2-refactor
:type '(choice (const :tag "Double" 1)
(const :tag "Single" 2)))
(defcustom js2r-always-insert-parens-around-arrow-function-params nil
"When non-nil, js2r always inserts parenthesis around arrow function params.
This only affects arrow functions with one parameter."
:group 'js2-refactor
:type 'boolean)
(defcustom js2r-prefer-let-over-var nil
"When non-nil, js2r uses let constructs over var when performing refactorings.")
;;; Keybindings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun js2r--add-keybindings (key-fn)
"Add js2r refactoring keybindings to `js2-mode-map' using KEY-FN to create each keybinding."
(define-key js2-refactor-mode-map (funcall key-fn "ee") #'js2r-expand-node-at-point)
(define-key js2-refactor-mode-map (funcall key-fn "cc") #'js2r-contract-node-at-point)
(define-key js2-refactor-mode-map (funcall key-fn "wi") #'js2r-wrap-buffer-in-iife)
(define-key js2-refactor-mode-map (funcall key-fn "ig") #'js2r-inject-global-in-iife)
(define-key js2-refactor-mode-map (funcall key-fn "ev") #'js2r-extract-var)
(define-key js2-refactor-mode-map (funcall key-fn "iv") #'js2r-inline-var)
(define-key js2-refactor-mode-map (funcall key-fn "rv") #'js2r-rename-var)
(define-key js2-refactor-mode-map (funcall key-fn "vt") #'js2r-var-to-this)
(define-key js2-refactor-mode-map (funcall key-fn "ag") #'js2r-add-to-globals-annotation)
(define-key js2-refactor-mode-map (funcall key-fn "sv") #'js2r-split-var-declaration)
(define-key js2-refactor-mode-map (funcall key-fn "ss") #'js2r-split-string)
(define-key js2-refactor-mode-map (funcall key-fn "ef") #'js2r-extract-function)
(define-key js2-refactor-mode-map (funcall key-fn "em") #'js2r-extract-method)
(define-key js2-refactor-mode-map (funcall key-fn "ip") #'js2r-introduce-parameter)
(define-key js2-refactor-mode-map (funcall key-fn "lp") #'js2r-localize-parameter)
(define-key js2-refactor-mode-map (funcall key-fn "tf") #'js2r-toggle-function-expression-and-declaration)
(define-key js2-refactor-mode-map (funcall key-fn "ta") #'js2r-toggle-arrow-function-and-expression)
(define-key js2-refactor-mode-map (funcall key-fn "ao") #'js2r-arguments-to-object)
(define-key js2-refactor-mode-map (funcall key-fn "uw") #'js2r-unwrap)
(define-key js2-refactor-mode-map (funcall key-fn "wl") #'js2r-wrap-in-for-loop)
(define-key js2-refactor-mode-map (funcall key-fn "3i") #'js2r-ternary-to-if)
(define-key js2-refactor-mode-map (funcall key-fn "lt") #'js2r-log-this)
(define-key js2-refactor-mode-map (funcall key-fn "dt") #'js2r-debug-this)
(define-key js2-refactor-mode-map (funcall key-fn "sl") #'js2r-forward-slurp)
(define-key js2-refactor-mode-map (funcall key-fn "ba") #'js2r-forward-barf)
(define-key js2-refactor-mode-map (funcall key-fn "k") #'js2r-kill)
(define-key js2-refactor-mode-map (kbd "<C-S-down>") #'js2r-move-line-down)
(define-key js2-refactor-mode-map (kbd "<C-S-up>") #'js2r-move-line-up))
;;;###autoload
(defun js2r-add-keybindings-with-prefix (prefix)
"Add js2r keybindings using the prefix PREFIX."
(setq js2-refactor-keybinding-prefix (read-kbd-macro prefix))
(js2r--add-keybindings (-partial #'js2r--key-pairs-with-prefix prefix)))
;;;###autoload
(defun js2r-add-keybindings-with-modifier (modifier)
"Add js2r keybindings using the modifier MODIFIER."
(js2r--add-keybindings (-partial #'js2r--key-pairs-with-modifier modifier)))
(provide 'js2-refactor)
;;; js2-refactor.el ends here

Binary file not shown.

View File

@@ -0,0 +1,57 @@
;;; js2r-conditionals.el --- Conditional refactoring functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 's)
(require 'js2r-helpers)
(defun js2r-ternary-to-if ()
"Convert a ternary operator to an if-statement."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(save-excursion
(let* ((ternary (js2r--closest 'js2-cond-node-p))
(test-expr (js2-node-string (js2-cond-node-test-expr ternary)))
(true-expr (js2-node-string (js2-cond-node-true-expr ternary)))
(false-expr (js2-node-string (js2-cond-node-false-expr ternary)))
(stmt (js2-node-parent-stmt ternary))
(stmt-pre (buffer-substring (js2-node-abs-pos stmt) (js2-node-abs-pos ternary)))
(stmt-post (s-trim (buffer-substring (js2-node-abs-end ternary) (js2-node-abs-end stmt))))
(beg (js2-node-abs-pos stmt)))
(goto-char beg)
(delete-char (js2-node-len stmt))
(insert "if (" test-expr ") {")
(newline)
(insert stmt-pre true-expr stmt-post)
(newline)
(insert "} else {")
(newline)
(insert stmt-pre false-expr stmt-post)
(newline)
(insert "}")
(indent-region beg (point))))))
(provide 'js2r-conditionals)
;;; js2r-conditionals ends here

Binary file not shown.

View File

@@ -0,0 +1,230 @@
;;; js2r-conveniences.el --- Convenience functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Convenience functions for logging statements by inserting
;; `console.log' statements and moving lines respecting object
;; literal syntax.
;;; Code:
(require 'js2r-helpers)
(defun js2r-log-this (arg)
"Log of the node at point, adding a 'console.log()' statement.
With a prefix argument ARG, use JSON pretty-printing for logging."
(interactive "P")
(js2r--guard)
(js2r--wait-for-parse
(let* ((log-info (js2r--figure-out-what-to-log-where))
(stmt (car log-info))
(pos (cdr log-info)))
(save-excursion
(goto-char pos)
(when (looking-at "[;{]")
(forward-char 1))
(newline-and-indent)
(if arg
(progn (insert "console.log(\"" stmt " = \");")
(newline-and-indent)
(insert "console.dir(" stmt ", { depth:null, colors: true });"))
(insert "console.log(\"" stmt " = \", " stmt ");"))))))
(defun js2r-debug-this ()
"Debug the node at point, adding a 'debug()' statement."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(let* ((log-info (js2r--figure-out-what-to-log-where))
(stmt (car log-info))
(pos (cdr log-info)))
(save-excursion
(goto-char pos)
(when (looking-at "[;{]")
(forward-char 1))
(newline-and-indent)
(insert "debug(" (js2r--wrap-text stmt " = %s") ", " stmt ");")))))
(defun js2r--figure-out-what-to-log-where ()
"Return a dotted pair containing the statement to log and the
position where the log should be inserted."
(let ((parent-stmt (js2-node-parent-stmt (js2-node-at-point))))
(if (use-region-p)
(cons (buffer-substring (region-beginning) (region-end))
(js2r--find-suitable-log-position-around parent-stmt))
(let* ((node (js2r--name-node-at-point))
(parent (js2-node-parent node)))
(cond
((js2-function-node-p parent)
(cons (js2-name-node-name node)
(js2-node-abs-pos (js2-function-node-body parent))))
((js2-prop-get-node-p parent)
(cons (buffer-substring (js2-node-abs-pos parent) (js2-node-abs-end parent))
(js2r--find-suitable-log-position-around parent-stmt)))
(:else
(cons (js2-name-node-name node)
(js2r--find-suitable-log-position-around parent-stmt))))))))
(defun js2r--find-suitable-log-position-around (parent-stmt)
"Return the position close to PARENT-STMT where the log statement should be inserted."
(if (js2-return-node-p parent-stmt)
(save-excursion
(goto-char (js2-node-abs-pos parent-stmt))
(beginning-of-line)
(forward-char -1)
(point))
(js2-node-abs-end parent-stmt)))
(defun js2r-split-string ()
"Split the string node at point. If the string is already split, join it instead."
(interactive)
(when (js2r--point-inside-string-p)
(let ((delimiter (js2r--string-delimiter (js2-node-at-point))))
(if (looking-back " \"")
(progn
(forward-char -2)
(insert " +")
(forward-char -2))
(if (looking-at (regexp-quote (format "%s + %s" delimiter delimiter)))
(delete-char 5)
(insert (format "%s + %s" delimiter delimiter)))))))
(defun js2r--string-delimiter (node)
"Return the delimiter character of the string node NODE.
It can be a single or double quote."
(save-excursion
(goto-char (js2-node-abs-pos node))
(char-to-string (following-char))))
(defun move-line-down ()
"Move the current line down one line."
(interactive)
(let ((col (current-column)))
(save-excursion
(forward-line)
(transpose-lines 1))
(forward-line)
(move-to-column col)))
(defun move-line-up ()
"Move the current line up one line."
(interactive)
(let ((col (current-column)))
(transpose-lines 1)
(forward-line -2)
(move-to-column col)))
(defun js2r-move-line-down ()
"Move the current line down one line.
Make sure commas are placed correctly when moving a line up or
down in an object or array literal."
(interactive)
(if (and (js2r--current-line-is-a-list-item)
(js2r--next-line-is-a-list-item))
(js2r--move-line-down-as-list-item)
(move-line-down))
(funcall indent-line-function))
(defun js2r-move-line-up ()
"Move the current line up one line.
Make sure commas are placed correctly when moving a line up or
down in an object or array literal."
(interactive)
(if (and (js2r--current-line-is-a-list-item)
(js2r--previous-line-is-a-list-item))
(js2r--move-line-up-as-list-item)
(move-line-up))
(funcall indent-line-function))
(defun js2r--current-line-is-prefixed-with-list-item-start ()
"Return whether the current line is prefixed with '{' or '['."
(save-excursion
(back-to-indentation)
(looking-back "\\({\\|\\[\\|,\\)\\(\s\\|\n\\|\t\\)*")))
(defun js2r--current-line-is-postfixed-with-list-item-end ()
"Return whether the current line is postfixed with '{' or '['."
(save-excursion
(end-of-line)
(or (looking-back ",\s*") ; line ends in comma
(looking-at "\\(\s\\|\n\\|\t\\)*\\(\\]\\|}\\)"))))
(defun js2r--current-line-is-a-list-item ()
"Return whether the current line contain an array or object literal."
(and (js2r--current-line-is-prefixed-with-list-item-start)
(js2r--current-line-is-postfixed-with-list-item-end)))
(defun js2r--next-line-is-a-list-item ()
"Return whether the current line contain an array or object literal."
(save-excursion
(forward-line)
(js2r--current-line-is-a-list-item)))
(defun js2r--previous-line-is-a-list-item ()
"Return whether the previous line contain an array or object literal, and only that."
(save-excursion
(forward-line -1)
(js2r--current-line-is-a-list-item)))
(defun js2r--current-line-has-comma ()
"Return whether the current line ends with a comma."
(save-excursion
(end-of-line)
(looking-back ",\s*")))
(defun js2r--previous-line-has-comma ()
"Return whether the previous line ends with a comma."
(save-excursion
(forward-line -1)
(js2r--current-line-has-comma)))
(defun js2r--move-line-down-as-list-item ()
"Move the current line containing a list literal down one line, and also move the comma."
(move-line-down)
(if (not (js2r--previous-line-has-comma))
(save-excursion
(end-of-line)
(delete-char -1)
(forward-line -1)
(end-of-line)
(insert ","))))
(defun js2r--move-line-up-as-list-item ()
"Move the current line containing a list literal up one line, and also move the comma."
(move-line-up)
(if (not (js2r--current-line-has-comma))
(save-excursion
(end-of-line)
(insert ",")
(forward-line)
(end-of-line)
(delete-char -1))))
(provide 'js2r-conveniences)
;;; js2r-conveniences.el ends here

Binary file not shown.

View File

@@ -0,0 +1,251 @@
;;; js2r-formatting.el --- Private helper functions for formatting -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(defun js2r--ensure-newline ()
(if (and (not (looking-at "\s*\n"))
(not (looking-back "\n\s*")))
(newline-and-indent)))
(defun js2r--ensure-just-one-space ()
(interactive)
(while (or (looking-at "\s*\n")
(looking-back "\n\s*"))
(when (looking-at "\n")
(delete-char 1))
(when (looking-back "\n\s")
(backward-char)
(delete-char -1))
(just-one-space))
(just-one-space))
(defmacro js2r--create-bracketed-whitespace-traverser
(name ws-fix-func looking-at-start-func
goto-closest-start-func subexpr-str)
"Build a function to expand or contract a given type of
bracketed expression, i.e., function body, object literal, or
array (any of which may be nested).
Parameters:
name: name of the function to be built
ws-fix-func: function to adjust whitespace at point
looking-at-start-func: returns t if point is at
the start of the bracketed
thing we want to act on
goto-closest-start-func: moves point if necessary
until looking-at-start-func
is true
subexpr-str: literal delimiter of parts of the
thing to be expanded or contracted"
`(defun ,name ()
(interactive)
(save-excursion
(if (not ,looking-at-start-func)
,goto-closest-start-func)
(let ((end (make-marker)))
(set-marker end (save-excursion
(forward-list)
(point)))
(forward-char)
,ws-fix-func
(while (< (point) end)
(while (js2r--point-inside-string-p)
(forward-char))
(when (looking-at ,subexpr-str)
(forward-char)
(unless (js2-comment-node-p (js2-node-at-point))
,ws-fix-func))
(if (looking-at "\\s(")
(forward-list)
(forward-char)))
(backward-char)
,ws-fix-func))))
(defun js2r--looking-at-object-start ()
(and (looking-at "{")
(not (looking-back ")[\s\n]*"))))
(defun js2r--goto-closest-object-start ()
(while (not (js2r--looking-at-object-start))
(if (eq (car (syntax-ppss)) 0)
(error "Cursor is not on an object")
(goto-char (nth 1 (syntax-ppss))))))
(js2r--create-bracketed-whitespace-traverser js2r-expand-object
(js2r--ensure-newline)
(js2r--looking-at-object-start)
(js2r--goto-closest-object-start)
",")
(js2r--create-bracketed-whitespace-traverser js2r-contract-object
(js2r--ensure-just-one-space)
(js2r--looking-at-object-start)
(js2r--goto-closest-object-start)
",")
(defun js2r--looking-at-array-start ()
(looking-at "\\["))
(defun js2r--goto-closest-array-start ()
(while (not (js2r--looking-at-array-start))
(if (eq (car (syntax-ppss)) 0)
(error "Cursor is not on an array")
(goto-char (nth 1 (syntax-ppss))))))
(js2r--create-bracketed-whitespace-traverser js2r-expand-array
(js2r--ensure-newline)
(js2r--looking-at-array-start)
(js2r--goto-closest-array-start)
",")
(js2r--create-bracketed-whitespace-traverser js2r-contract-array
(js2r--ensure-just-one-space)
(js2r--looking-at-array-start)
(js2r--goto-closest-array-start)
",")
;; (defun js2r--looking-at-function-start ()
;; (or
;; (and (looking-at "{")
;; (looking-back
;; ;; This horrible-looking regexp is actually pretty simple. It
;; ;; matches "function <optional_name> (<optional_parameters,...>)"
;; ;; allowing for whitespace. TODO: support Unicode in function and
;; ;; parameter names.
;; (concat "function[\s\n]*"
;; "\\\([a-zA-Z_$][a-zA-Z_$0-9]*[\s\n]*\\\)?"
;; "\(\\\([a-zA-Z_$][a-zA-Z_$0-9]*"
;; "[\s\n]*,[\s\n]*\\\)*[\s\n]*"
;; "\\\([a-zA-Z_$][a-zA-Z_$0-9]*[\s\n]*\\\)*"
;; "[\s\n]*\)[\s\n]*")))
;; ;; arrow functions
;; (and (looking-at "{")
;; (looking-back "=>[\s\n]*")
;; (not (js2r--point-inside-string-p)))))
(defun js2r--looking-at-function-start ()
"Return non-nil if the point is at the start of a function body."
(let* ((node (js2-node-at-point))
(parent (js2-node-parent node)))
(and (looking-at "{")
(js2-block-node-p node)
(js2-function-node-p parent))))
(defun js2r--goto-closest-function-start ()
(while (not (js2r--looking-at-function-start))
(if (eq (car (syntax-ppss)) 0)
(error "Cursor is not on a function body")
(goto-char (nth 1 (syntax-ppss))))))
(js2r--create-bracketed-whitespace-traverser js2r-expand-function
(js2r--ensure-newline)
(js2r--looking-at-function-start)
(js2r--goto-closest-function-start)
";")
;; TODO: It'd be great if js2r-contract-function could recognize
;; newlines that are implied statement terminators and insert
;; semicolons correctly, but that would probably mean not using the
;; same macro as the other "contract" function definitions.
(js2r--create-bracketed-whitespace-traverser js2r-contract-function
(js2r--ensure-just-one-space)
(js2r--looking-at-function-start)
(js2r--goto-closest-function-start)
";")
(defun js2r--looking-at-call-start ()
(looking-at "("))
(defun js2r--goto-closest-call-start ()
(while (not (js2r--looking-at-call-start))
(if (eq (car (syntax-ppss)) 0)
(error "Cursor is not on a call")
(goto-char (nth 1 (syntax-ppss))))))
(js2r--create-bracketed-whitespace-traverser js2r-expand-call-args
(js2r--ensure-newline)
(js2r--looking-at-call-start)
(js2r--goto-closest-call-start)
",")
(js2r--create-bracketed-whitespace-traverser js2r-contract-call-args
(js2r--ensure-just-one-space)
(js2r--looking-at-call-start)
(js2r--goto-closest-call-start)
",")
(defun js2r--expand-contract-node-at-point (&optional is-contract)
"Expand or contract bracketed list according to node type in point.
Currently working on array, object, function and call args node types.
With argument, contract closest expression, otherwise expand."
(let ((pos (point))
(array-start (point-max))
(object-start (point-max))
(function-start (point-max))
(call-start (point-max)))
(save-excursion
(ignore-errors
(js2r--goto-closest-array-start)
(setq array-start (- pos (point)))))
(save-excursion
(ignore-errors
(js2r--goto-closest-object-start)
(setq object-start (- pos (point)))))
(save-excursion
(ignore-errors
(js2r--goto-closest-function-start)
(setq function-start (- pos (point)))))
(save-excursion
(ignore-errors
(js2r--goto-closest-call-start)
(setq call-start (- pos (point)))))
(setq pos (-min (list array-start object-start function-start call-start)))
(when (= pos array-start)
(if is-contract
(js2r-contract-array)
(js2r-expand-array)))
(when (= pos object-start)
(if is-contract
(js2r-contract-object)
(js2r-expand-object)))
(when (= pos function-start)
(if is-contract
(js2r-contract-function)
(js2r-expand-function)))
(when (= pos call-start)
(if is-contract
(js2r-contract-call-args)
(js2r-expand-call-args)))))
(defun js2r-expand-node-at-point ()
"Expand bracketed list according to node type at point."
(interactive)
(js2r--expand-contract-node-at-point))
(defun js2r-contract-node-at-point ()
"Contract bracketed list according to node type at point."
(interactive)
(js2r--expand-contract-node-at-point t))
(provide 'js2r-formatting)
;;; js2-formatting.el ends here

Binary file not shown.

View File

@@ -0,0 +1,524 @@
;;; js2r-functions.el --- Function manipulation functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 'dash)
(require 'yasnippet)
(require 'js2r-helpers)
(defun js2r-localize-parameter ()
"Turn parameter into local var in local function."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(if (js2-name-node-p (js2-node-at-point))
(js2r--localize-parameter-pull)
(js2r--localize-parameter-push))))
(defun js2r--localize-parameter-push ()
(let* ((node (js2-node-at-point))
(arg-node (or (js2r--closest-node-where 'js2r--parent-is-call-node node)
(error "Place cursor on argument to localize")))
(call-node (js2-node-parent arg-node))
(value (js2-node-string arg-node))
(target (js2-call-node-target call-node))
(fn (if (js2-name-node-p target)
(js2r--local-fn-from-name-node target)
(error "Can only localize parameter for local functions")))
(usages (js2r--function-usages fn))
(index (car (--keep (when (eq arg-node it) it-index)
(js2-call-node-args call-node))))
(name (js2-name-node-name (nth index (js2-function-node-params fn)))))
(js2r--localize-parameter fn usages index name value)))
(defun js2r--localize-parameter-pull ()
(let* ((name-node (js2-node-at-point))
(name (if (js2-name-node-p name-node)
(js2-name-node-name name-node)
(error "Place cursor on parameter to localize")))
(fn (or (js2r--closest-node-where #'js2r--is-local-function name-node)
(error "Can only localize parameter in local functions")))
(index (or (js2r--param-index-for name fn)
(error "%S isn't a parameter to this function" name)))
(usages (js2r--function-usages fn))
(examples (-distinct (--map (js2r--argument index it) usages)))
(value (js2r--choose-one "Value: " examples)))
(js2r--localize-parameter fn usages index name value)))
(defun js2r--localize-parameter (fn usages index name value)
(save-excursion
(js2r--goto-fn-body-beg fn)
(save-excursion
(--each usages (js2r--remove-argument-at-index index it)))
(newline-and-indent)
(insert "var " name " = " value ";")
(js2r--remove-parameter-at-index index fn)))
(defun js2r--parent-is-call-node (node)
(js2-call-node-p (js2-node-parent node)))
(defun js2r--local-fn-from-name-node (name-node)
(->> name-node
(js2r--local-usages-of-name-node)
(-map #'js2-node-parent)
(-first #'js2-function-node-p)))
(defun js2r--param-index-for (name fn)
(car (--keep (when (equal name (js2-name-node-name it)) it-index)
(js2-function-node-params fn))))
(defun js2r--argument (index call-node)
(js2-node-string (nth index (js2-call-node-args call-node))))
(defun js2r--remove-parameter-at-index (index fn)
(js2r--delete-node-in-params (nth index (js2-function-node-params fn))))
(defun js2r--remove-argument-at-index (index call-node)
(js2r--delete-node-in-params (nth index (js2-call-node-args call-node))))
(defun js2r--delete-node-in-params (node)
(goto-char (js2-node-abs-pos node))
(delete-char (js2-node-len node))
(if (and (looking-back "(")
(looking-at ", "))
(delete-char 2)
(when (looking-back ", ")
(delete-char -2))))
(defun js2r--choose-one (prompt options)
(when options
(if (cdr options)
(completing-read prompt options)
(car options))))
(defun js2r-introduce-parameter ()
"Introduce a parameter in a local function."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(if (use-region-p)
(js2r--introduce-parameter-between (region-beginning) (region-end))
(let ((node (js2r--closest-extractable-node)))
(js2r--introduce-parameter-between (js2-node-abs-pos node)
(js2-node-abs-end node))))))
(defun js2r--introduce-parameter-between (beg end)
(unless (js2r--single-complete-expression-between-p beg end)
(error "Can only introduce single, complete expressions as parameter"))
(let ((fn (js2r--closest-node-where #'js2r--is-local-function (js2-node-at-point))))
(unless fn
(error "Can only introduce parameter in local functions"))
(save-excursion
(let ((name (read-string "Parameter name: "))
(val (buffer-substring beg end))
(usages (js2r--function-usages fn)))
(goto-char beg)
(save-excursion
(-each usages (-partial #'js2r--add-parameter val)))
(delete-char (- end beg))
(insert name)
(js2r--add-parameter name fn)
(query-replace val name nil (js2-node-abs-pos fn) (js2r--fn-body-end fn))))))
(defun js2r--function-usages (fn)
(-map #'js2-node-parent (js2r--function-usages-name-nodes fn)))
(defun js2r--function-usages-name-nodes (fn)
(let ((name-node (or (js2-function-node-name fn)
(js2-var-init-node-target (js2-node-parent fn)))))
(remove name-node (js2r--local-usages-of-name-node name-node))))
(defun js2r--add-parameter (name node)
(save-excursion
(js2r--goto-closing-paren node)
(unless (looking-back "(")
(insert ", "))
(insert name)))
(defun js2r--goto-closing-paren (node)
(goto-char (js2-node-abs-pos node))
(search-forward "(")
(forward-char -1)
(forward-list)
(forward-char -1))
(defun js2r--goto-fn-body-beg (fn)
(goto-char (js2-node-abs-pos fn))
(search-forward "{"))
(defun js2r--fn-body-end (fn)
(save-excursion
(js2r--goto-fn-body-beg fn)
(forward-char -1)
(forward-list)
(point)))
(defun js2r--is-local-function (node)
(or (js2r--is-var-function-expression node)
(js2r--is-function-declaration node)))
(defun js2r--is-method (node)
(and (js2-function-node-p node)
(js2-object-prop-node-p (js2-node-parent node))))
(defun js2r--is-var-function-expression (node)
(and (js2-function-node-p node)
(js2-var-init-node-p (js2-node-parent node))))
(defun js2r--is-assigned-function-expression (node)
(and (js2-function-node-p node)
(js2-assign-node-p (js2-node-parent node))))
(defun js2r--is-function-declaration (node)
(let ((parent (js2-node-parent node)))
(and (js2-function-node-p node)
(not (js2-assign-node-p parent))
(not (js2-var-init-node-p parent))
(not (js2-object-prop-node-p parent)))))
(defun js2r-arguments-to-object ()
"Change from a list of arguments to a parameter object."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(let ((node (js2-node-at-point)))
(unless (and (looking-at "(")
(or (js2-function-node-p node)
(js2-call-node-p node)
(js2-new-node-p node)))
(error "Place point right before the opening paren in the call or function"))
(-when-let* ((target (js2r--node-target node))
(fn (and (js2-name-node-p target)
(js2r--local-fn-from-name-node target))))
(setq node fn))
(if (js2-function-node-p node)
(js2r--arguments-to-object-for-function node)
(js2r--arguments-to-object-for-args-with-unknown-function (js2r--node-args node))))))
(defun js2r--arguments-to-object-for-function (function-node)
(let ((params (js2-function-node-params function-node)))
(when (null params)
(error "No params to convert"))
(save-excursion
(js2r--execute-changes
(-concat
;; change parameter list to just (params)
(list
(list :beg (+ (js2-node-abs-pos function-node) (js2-function-node-lp function-node))
:end (+ (js2-node-abs-pos function-node) (js2-function-node-rp function-node) 1)
:contents "(params)"))
;; add params. in front of function local param usages
(let* ((local-param-name-nodes (--mapcat (-> it
(js2-node-abs-pos)
(js2r--local-name-node-at-point)
(js2r--local-usages-of-name-node))
params))
(local-param-name-usages (--remove (js2-function-node-p (js2-node-parent it))
local-param-name-nodes))
(local-param-name-positions (-map #'js2-node-abs-pos local-param-name-usages)))
(--map
(list :beg it :end it :contents "params.")
local-param-name-positions))
;; update usages of function
(let ((names (-map #'js2-name-node-name params))
(usages (js2r--function-usages function-node)))
(--map
(js2r--changes/arguments-to-object it names)
usages)))))))
(defun js2r--changes/arguments-to-object (node names)
(let ((args (js2r--node-args node)))
(list :beg (+ (js2-node-abs-pos node) (js2r--node-lp node))
:end (+ (js2-node-abs-pos node) (js2r--node-rp node) 1)
:contents (js2r--create-object-with-arguments names args))))
(defun js2r--arguments-to-object-for-args-with-unknown-function (args)
(when (null args)
(error "No arguments to convert"))
(let ((names (--map-indexed
(format "${%d:%s}"
(1+ it-index)
(if (js2-name-node-p it)
(js2-name-node-name it)
"key"))
args)))
(yas-expand-snippet (js2r--create-object-with-arguments names args)
(point)
(save-excursion (forward-list) (point)))))
(defun js2r--create-object-with-arguments (names args)
(let (arg key result)
(--dotimes (length args)
(setq arg (nth it args))
(setq key (nth it names))
(setq result
(concat result
(format " %s: %s,\n"
key
(buffer-substring (js2-node-abs-pos arg)
(js2-node-abs-end arg))))))
(concat "({\n" (substring result 0 -2) "\n})")))
(defun js2r-extract-function (name)
"Extract a function from the closest statement expression from the point."
(interactive "sName of new function: ")
(js2r--extract-fn
name
(lambda ()
(unless (js2r--looking-at-function-declaration)
(goto-char (js2-node-abs-pos (js2r--closest #'js2-expr-stmt-node-p)))))
"%s(%s);"
"function %s(%s) {\n%s\n}\n\n"))
(defun js2r-extract-method (name)
"Extract a method from the closest statement expression from the point."
(interactive "sName of new method: ")
(js2r--extract-fn
name
(lambda ()
(goto-char (js2-node-abs-pos (js2r--closest #'js2-object-prop-node-p))))
"this.%s(%s);"
"%s: function (%s) {\n%s\n},\n\n"))
(defun js2r--extract-fn (name goto-position call-template function-template)
(js2r--guard)
(js2r--wait-for-parse
(unless (use-region-p)
(error "Mark the expressions to extract first"))
(save-excursion
(let* ((parent (js2r--first-common-ancestor-in-region (region-beginning) (region-end)))
(block (js2r--closest-node-where #'js2-block-node-p parent))
(fn (js2r--closest-node-where #'js2-function-node-p block))
(exprs (js2r--marked-expressions-in-block block))
(vars (-mapcat #'js2r--name-node-decendants exprs))
(local (--filter (js2r--local-to-fn-p fn it) vars))
(names (-distinct (-map 'js2-name-node-name local)))
(declared-in-exprs (-map #'js2r--var-init-node-target-name (-mapcat #'js2r--var-init-node-decendants exprs)))
(outside-exprs (-difference (js2-block-node-kids block) exprs))
(outside-var-uses (-map #'js2-name-node-name (-mapcat #'js2r--name-node-decendants outside-exprs)))
(declared-in-but-used-outside (-intersection declared-in-exprs outside-var-uses))
(export-var (car declared-in-but-used-outside))
(params (-difference names declared-in-exprs))
(params-string (mapconcat #'identity (reverse params) ", "))
(first (car exprs))
(last (car (last exprs)))
(beg (js2-node-abs-pos (car exprs)))
(end (js2-node-abs-end last))
(contents (buffer-substring beg end)))
(goto-char beg)
(delete-region beg end)
(when (js2-return-node-p last)
(insert "return "))
(when export-var
(setq contents (concat contents "\nreturn " export-var ";"))
(insert "var " export-var " = "))
(insert (format call-template name params-string))
(goto-char (js2-node-abs-pos fn))
(funcall goto-position)
(let ((start (point)))
(insert (format function-template name params-string contents))
(indent-region start (1+ (point))))))))
(defun js2r--var-init-node-target-name (node)
(js2-name-node-name
(js2-var-init-node-target node)))
(defun js2r--function-around-region ()
(or
(js2r--closest-node-where #'js2-function-node-p
(js2r--first-common-ancestor-in-region
(region-beginning)
(region-end)))
(error "This only works when you mark stuff inside a function")))
(defun js2r--marked-expressions-in-block (fn)
(-select #'js2r--node-is-marked (js2-block-node-kids fn)))
(defun js2r--node-is-marked (node)
(and
(<= (region-beginning) (js2-node-abs-end node))
(>= (region-end) (js2-node-abs-pos node))))
(defun js2r--name-node-decendants (node)
(-select #'js2-name-node-p (js2r--decendants node)))
(defun js2r--var-init-node-decendants (node)
(-select #'js2-var-init-node-p (js2r--decendants node)))
(defun js2r--decendants (node)
(let (vars)
(js2-visit-ast node
(lambda (node end-p)
(unless end-p
(setq vars (cons node vars)))))
vars))
(defun js2r--local-to-fn-p (fn name-node)
(let* ((name (js2-name-node-name name-node))
(scope (js2-node-get-enclosing-scope name-node))
(scope (js2-get-defining-scope scope name)))
(eq fn scope)))
(defun js2r-toggle-arrow-function-and-expression ()
"Toggle between function expression to arrow function."
(interactive)
(save-excursion
(js2r--find-closest-function)
(cond ((js2r--arrow-function-p)
(js2r--transform-arrow-function-to-expression))
((and (js2r--function-start-p) (not (js2r--looking-at-function-declaration)))
(js2r--transform-function-expression-to-arrow))
(t (error "Can only toggle between function expressions and arrow function")))))
;; Toggle between function name() {} and var name = function ();
(defun js2r-toggle-function-expression-and-declaration ()
(interactive)
(save-excursion
(js2r--find-closest-function)
(cond
((js2r--looking-at-var-function-expression)
(when (js2r--arrow-function-p) (js2r--transform-arrow-function-to-expression))
(js2r--transform-function-expression-to-declaration))
((js2r--looking-at-function-declaration)
(js2r--transform-function-declaration-to-expression))
(t (error "Can only toggle between function declarations and free standing function expressions")))))
(defun js2r--arrow-function-p ()
(interactive)
(save-excursion
(ignore-errors
(js2r--find-closest-function)
(and (looking-at "(?[,[:space:][:word:]]*)?[[:space:]]*=>")
(not (js2r--point-inside-string-p))))))
(defun js2r--transform-arrow-function-to-expression ()
(when (js2r--arrow-function-p)
(let (has-parenthesis)
(save-excursion
(js2r--find-closest-function)
(let ((end (make-marker)))
(save-excursion
(search-forward "=>")
(set-marker end (js2-node-abs-end (js2-node-at-point))))
(setq has-parenthesis (looking-at "\\s-*("))
(insert "function ")
(if has-parenthesis
(forward-list)
(insert "("))
(search-forward "=>")
(delete-char -2)
(js2r--ensure-just-one-space)
(unless has-parenthesis
(backward-char 1)
(insert ")"))
(unless (looking-at "\\s-*{")
(js2r--ensure-just-one-space)
(insert "{ return ")
(js2r--ensure-just-one-space)
(goto-char (marker-position end))
(insert "; }")))))))
(defun js2r--transform-function-expression-to-arrow ()
(when (not (js2r--arrow-function-p))
(save-excursion
(js2r--find-closest-function)
(let ((pos (point))
(params
(js2-function-node-params (js2-node-at-point)))
parenthesis-start
parenthesis-end)
(when (js2r--looking-at-function-declaration)
(error "Can not convert function declarations to arrow function"))
(search-forward "(")
(backward-char 1)
(delete-region pos (point))
(setq parenthesis-start (point))
(forward-list)
(setq parenthesis-end (point))
(insert " => ")
(js2r--ensure-just-one-space)
(when (and (= 1 (length params))
(not js2r-always-insert-parens-around-arrow-function-params))
(goto-char parenthesis-end)
(backward-delete-char 1)
(goto-char parenthesis-start)
(delete-char 1))))))
(defun js2r--function-start-p()
(let* ((fn (js2r--closest #'js2-function-node-p)))
(and fn
(= (js2-node-abs-pos fn) (point)))))
(defun js2r--find-closest-function ()
(when (not (js2r--function-start-p))
(let* ((fn (js2r--closest #'js2-function-node-p)))
(goto-char (js2-node-abs-pos fn)))))
(defun js2r--looking-at-method ()
(and (js2r--function-start-p)
(looking-back ": ?")))
(defun js2r--looking-at-function-declaration ()
(and (js2r--function-start-p)
(looking-back "^ *")))
(defun js2r--looking-at-var-function-expression ()
(and (js2r--function-start-p)
(looking-back "^ *var[\s\n]*[a-z_$]+[\s\n]*=[\s\n]*")))
(defun js2r--transform-function-expression-to-declaration ()
(when (js2r--looking-at-var-function-expression)
(delete-char 9)
(forward-list)
(forward-list)
(delete-char 1)
(backward-list)
(backward-list)
(delete-backward-char 3)
(back-to-indentation)
(delete-char 4)
(insert "function ")))
(defun js2r--transform-function-declaration-to-expression ()
(when (js2r--looking-at-function-declaration)
(delete-char 9)
(insert "var ")
(search-forward "(")
(backward-char 1)
(insert " = function ")
(forward-list)
(forward-list)
(insert ";")))
(provide 'js2r-functions)
;;; js2-functions.el ends here

Binary file not shown.

View File

@@ -0,0 +1,220 @@
;;; js2r-helpers.el --- Private helper functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 'dash)
(require 's)
(require 'js2-mode)
(defmacro js2r--wait-for-parse (&rest body)
"Evaluate BODY once the current buffer has been parsed."
`(js2-mode-wait-for-parse (lambda () ,@body)))
(defun js2r--wrap-text (&rest text)
"Wrap TEXT with the prefered quotes. The prefered quotes is set with `js2r-prefered-quote-type'."
(let ((prefered-quotes "\""))
(when (= 2 js2r-prefered-quote-type)
(setq prefered-quotes "'"))
(concat prefered-quotes (apply 'concat text) prefered-quotes)))
(defun js2r--fix-special-modifier-combinations (key)
(case key
("C-s-i" "s-TAB")
("C-s-m" "s-RET")
(otherwise key)))
(defun js2r--key-pairs-with-modifier (modifier keys)
(->> (string-to-list keys)
(--map (js2r--fix-special-modifier-combinations
(concat modifier (char-to-string it))))
(s-join " ")
(read-kbd-macro)))
(defun js2r--key-pairs-with-prefix (prefix keys)
(read-kbd-macro (concat prefix " " keys)))
(defun js2r--guard ()
(when js2-parsed-errors
(error "Can't refactor while buffer has parse errors")))
(defun js2r--current-quotes-char ()
"The char that is the current quote delimiter"
(nth 3 (syntax-ppss)))
(defalias 'js2r--point-inside-string-p 'js2r--current-quotes-char)
(defun js2r--closest-node-where (p node)
(if (or (null node)
(apply p node nil))
node
(js2r--closest-node-where p (js2-node-parent node))))
(defun js2r--closest (p)
(save-excursion
(cond
((bolp) (back-to-indentation))
((looking-at ";") (forward-char -1))
((looking-back ";") (forward-char -2))
((looking-back "}") (forward-char -1)))
(js2r--closest-node-where p (js2-node-at-point))))
(defun js2r--goto-and-delete-node (node)
(goto-char (js2-node-abs-pos node))
(delete-char (js2-node-len node)))
(defun js2r--path-to-root (node)
(when node
(cons node (js2r--path-to-root (js2-node-parent node)))))
(defun js2r--first-common-ancestor (node1 node2)
(if (eq node1 node2)
node1
(let ((path1 (reverse (js2r--path-to-root node1)))
(path2 (reverse (js2r--path-to-root node2)))
(last-common nil))
(while (eq (car path1) (car path2))
(setq last-common (car path1))
(setq path1 (cdr path1))
(setq path2 (cdr path2)))
last-common)))
(defun js2r--first-common-ancestor-in-region (beg end)
(js2r--first-common-ancestor (js2-node-at-point beg)
(js2-node-at-point end)))
;; abstract away node type on some common property getters
(defun js2r--node-target (node)
(cond
((js2-call-node-p node) (js2-call-node-target node))
((js2-new-node-p node) (js2-new-node-target node))
(:else nil)))
(defun js2r--node-args (node)
(cond
((js2-call-node-p node) (js2-call-node-args node))
((js2-new-node-p node) (js2-new-node-args node))
(:else nil)))
(defun js2r--node-lp (node)
(cond
((js2-call-node-p node) (js2-call-node-lp node))
((js2-new-node-p node) (js2-new-node-lp node))
(:else nil)))
(defun js2r--node-rp (node)
(cond
((js2-call-node-p node) (js2-call-node-rp node))
((js2-new-node-p node) (js2-new-node-rp node))
(:else nil)))
(defun js2r--node-kids (node)
(cond
((js2-function-node-p node) (js2-block-node-kids (js2-function-node-body node)))
((js2-if-node-p node) (js2-scope-kids (js2-if-node-then-part node)))
((js2-for-node-p node) (js2-block-node-kids (js2-for-node-body node)))
((js2-while-node-p node) (js2-block-node-kids (js2-while-node-body node)))))
;; finding expressions and arguments
(defun js2r--closest-extractable-node ()
"Return the most appropriate node the be extracted into a variable or paramter.
Lookup the closest expression node from the point, or the closest literal node instead.
If no node is found, signal an error."
(or (or (js2r--closest #'js2r--expression-p)
(js2r--closest #'js2r--literal-node-p))
(error "Cannot perform refactoring: Nothing to extract at point")))
(defun js2r--closest-stmt-node ()
"Return the closest standalone statement node.
Special care is taken for if branch nodes: if a statement node is
part of an if branch node (like 'else if' nodes), return the
parent node."
(let* ((node (js2-node-parent-stmt (js2-node-at-point)))
(parent (js2-node-parent node)))
(if (and (js2-if-node-p node)
(js2-if-node-p parent))
parent
node)))
(defun js2r--argument-p (node)
(let ((parent (js2-node-parent node)))
(and (js2-call-node-p parent)
(member node (js2-call-node-args parent)))))
(defun js2r--expression-p (node)
(or (js2-call-node-p node)
(js2r--argument-p node)
(and (js2-prop-get-node-p node)
(not (js2-call-node-p (js2-node-parent node))))))
(defun js2r--literal-node-p (node)
(or (js2-object-node-p node)
(js2-string-node-p node)
(js2-number-node-p node)
(js2r--boolean-node-p node)))
(defun js2r--boolean-node-p (node)
(let* ((beg (js2-node-abs-pos node))
(end (js2-node-abs-end node))
(content (buffer-substring beg end)))
(and (js2-keyword-node-p node)
(member content '("true" "false")))))
(defun js2r--single-complete-expression-between-p (beg end)
(let ((ancestor (js2r--first-common-ancestor-in-region beg (- end 1))))
(and (= beg (js2-node-abs-pos ancestor))
(= end (js2-node-abs-end ancestor)))))
;; executing a list of changes
;; ensures changes are executed from last to first
(defun js2r--by-end-descending (change1 change2)
(> (plist-get change1 :end)
(plist-get change2 :end)))
(defun js2r--any-overlapping-changes (sorted-changes)
(--any?
(let ((one (car it))
(two (cadr it)))
(< (plist-get one :beg)
(plist-get two :end)))
(-partition-in-steps 2 1 sorted-changes)))
(defun js2r--execute-changes (changes)
(when changes
(let ((sorted-changes (sort changes 'js2r--by-end-descending)))
(when (js2r--any-overlapping-changes sorted-changes)
(error "These changes overlap, cannot execute properly."))
(let ((abs-end (set-marker (make-marker) (1+ (plist-get (car sorted-changes) :end))))
(abs-beg (plist-get (car (last sorted-changes)) :beg)))
(--each sorted-changes
(goto-char (plist-get it :beg))
(delete-char (- (plist-get it :end) (plist-get it :beg)))
(insert (plist-get it :contents)))
(indent-region abs-beg abs-end)
(set-marker abs-end nil)))))
(provide 'js2r-helpers)
;;; js2-helpers.el ends here

Binary file not shown.

View File

@@ -0,0 +1,92 @@
;;; js2r-iife.el --- IIFE wrapping functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 'js2r-helpers)
(defvar js2r--iife-regexp "^(function (")
(defun js2r-wrap-buffer-in-iife ()
"Wrap the entire buffer in an immediately invoked function expression"
(interactive)
(save-excursion
(when (ignore-errors (search-backward-regexp js2r--iife-regexp))
(error "Buffer already contains an immediately invoked function expression."))
(goto-char (point-min))
(insert "(function () {\n")
(when js2r-use-strict (insert "\"use strict\";\n"))
(insert "\n")
(goto-char (point-max))
(insert "\n")
(delete-blank-lines)
(insert "\n}());")
(indent-region (point-min) (point-max))))
(defun js2r--selected-name-positions ()
"Returns the (beginning . end) of the name at cursor, or active region."
(let ((current-node (js2-node-at-point))
beg end)
(unless (js2-name-node-p current-node)
(setq current-node (js2-node-at-point (- (point) 1))))
(if (not (and current-node (js2-name-node-p current-node)))
(error "Point is not on an identifier."))
(if (use-region-p)
(cons (region-beginning) (region-end))
(progn
(setq end (+ (js2-node-abs-pos current-node)
(js2-node-len current-node)))
(skip-syntax-backward ".w_")
(cons (point) end)))))
(defun js2r-inject-global-in-iife ()
"Create shortcut for marked global by injecting it in the wrapping IIFE"
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(save-excursion
(let* ((name-pos (js2r--selected-name-positions))
(name-beg (car name-pos))
(name-end (cdr name-pos))
(name (buffer-substring-no-properties name-beg name-end))
(short (buster--global-shortcut name))
beg end)
(unless (search-backward-regexp js2r--iife-regexp)
(error "No immediately invoked function expression found."))
(deactivate-mark)
(forward-char 11)
(insert short)
(unless (looking-at ")")
(insert ", "))
(search-forward "{")
(setq beg (point))
(backward-char)
(forward-list)
(forward-char)
(setq end (point))
(insert name)
(unless (looking-at ")")
(insert ", "))
(replace-string name short t beg end)))))
(provide 'js2r-iife)
;;; js2-iife.el ends here

Binary file not shown.

View File

@@ -0,0 +1,227 @@
;;; js2r-paredit.el --- Paredit-like extensions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 'dash)
(require 'js2r-helpers)
(defun js2r--nesting-node-p (node)
(or (js2-function-node-p node)
(js2-if-node-p node)
(js2-for-node-p node)
(js2-while-node-p node)))
(defun js2r--standalone-node-p (node)
(or (js2-stmt-node-p node)
(and (js2-function-node-p node)
(eq 'FUNCTION_STATEMENT (js2-function-node-form node)))))
(defun js2r-kill ()
"Kill a line like `kill-line' but tries to respect node boundaries.
Falls back to `kill-line' if the buffer has parse errors.
if(|foo) {bar();} -> if() {bar();}
function foo() {|2 + 3} -> function foo() {}
// some |comment -> // some
'this is a| string' -> 'this is a'
"
(interactive)
(if js2-parsed-errors
(progn
(message "Buffer has parse errors. Killing the line")
(kill-line))
(condition-case error
(js2r--kill-line)
(progn
(message "Error occured while trying to kill AST node. Killing the line.")
(kill-line)))))
(defun js2r--kill-line ()
"Kill a line, but respecting node boundaries."
(let ((node (js2r--next-node)))
(cond
((js2-comment-node-p node) (kill-line))
((js2-string-node-p node) (js2r--kill-line-in-string))
(t (js2r--kill-line-in-sexp)))))
(defun js2r--next-node ()
"Return the node at point, or the node after the point if the
point is at the exact end of a node."
(save-excursion
(when (= (js2-node-abs-end (js2-node-at-point))
(point))
(forward-char 1))
(js2-node-at-point)))
(defun js2r--kill-line-in-sexp ()
"Kill a line, but only kills until the closest outer sexp on
the current line, delimited with \")}]\". If no sexp is found
on the current line, falls back to
`js2r--kill-line-with-inner-sexp'."
(condition-case error
(let* ((beg (point))
(end (save-excursion
(up-list)
(forward-char -1)
(point))))
(if (js2-same-line end)
(kill-region beg end)
(js2r--kill-line-with-inner-sexp)))
(scan-error
(js2r--kill-line-with-inner-sexp))))
(defun js2r--kill-line-with-inner-sexp ()
"Kill a line, but respecting inner killed sexps, ensuring that
we kill up to the end to the next inner sexp if it starts in
the current line.
If the parentheses are unbalanced, fallback to `kill-line' and
warn the user."
(condition-case error
(let* ((beg (point))
(end (save-excursion
(forward-visible-line 1)
(point)))
(beg-of-sexp (save-excursion
(js2r--goto-last-sexp-on-line)
(point)))
(end-of-sexp (save-excursion
(goto-char beg-of-sexp)
(forward-list)
;; Kill all remaining semi-colons as well
(while (looking-at ";")
(forward-char))
(point))))
(if (js2-same-line beg-of-sexp)
(kill-region beg (max end end-of-sexp))
(kill-line)))
(scan-error
(message "Unbalanced parentheses. Killing the line.")
(kill-line))))
(defun js2r--goto-last-sexp-on-line ()
"Move the cursor to the opening of the last sexp on the current
line, or to the end of the line if no sexp is found."
(let ((pos (point)))
(down-list)
(backward-char 1)
(forward-list)
(if (js2-same-line pos)
(js2r--goto-last-sexp-on-line)
(backward-list))))
(defun js2r--kill-line-in-string ()
"Kill a line in a string node, respecting the node boundaries.
When at the beginning of the node, kill from outside of it."
(let* ((node (js2-node-at-point))
(beg (point))
(node-start (js2-node-abs-pos node))
(node-end (js2-node-abs-end node)))
(if (= beg node-start)
(js2r--kill-line-in-sexp)
(kill-region beg (1- node-end)))))
(defun js2r-forward-slurp (&optional arg)
"Add the expression following the current function into it.
The addition is performed by moving the closing brace of the
function down.
When called with a prefix argument ARG, slurp ARG expressions
following the current function."
(interactive "p")
(js2r--guard)
(js2r--wait-for-parse
(let* ((nesting (js2r--closest 'js2r--nesting-node-p))
(standalone (if (js2r--standalone-node-p nesting)
nesting
(js2-node-parent-stmt nesting)))
(next-sibling (js2-node-next-sibling standalone))
(beg (js2-node-abs-pos next-sibling))
(last-sibling (if (wholenump arg)
(let ((num arg)
(iter-sibling next-sibling))
(while (> num 1) ;; Do next-sibling arg nbr of times
(setq iter-sibling (js2-node-next-sibling iter-sibling))
(setq num (1- num)))
iter-sibling)
next-sibling)) ;; No optional arg. Just use next-sibling
(end (js2-node-abs-end last-sibling))
(text (buffer-substring beg end)))
(save-excursion
(delete-region beg end)
;; Delete newline character if the deleted AST node was at the end of the line
(goto-char beg)
(when (and (eolp)
(not (eobp)))
(delete-char 1))
(goto-char (js2-node-abs-end nesting))
(forward-char -1)
(when (looking-back "{ *")
(newline))
(setq beg (point))
(insert text)
(when (looking-at " *}")
(newline))
(setq end (point))
(indent-region beg end)))))
(defun js2r-forward-barf (&optional arg)
(interactive "p")
(js2r--guard)
(js2r--wait-for-parse
(let* ((nesting (js2r--closest 'js2r--nesting-node-p))
(standalone (if (js2r--standalone-node-p nesting)
nesting
(js2-node-parent-stmt nesting)))
(standalone-end (js2-node-abs-end standalone))
(last-child (car (last (if (js2-if-node-p nesting)
(js2-scope-kids (js2r--closest 'js2-scope-p))
(js2r--node-kids nesting)))))
(first-barf-child (if (wholenump arg)
(let ((num arg)
(iter-child last-child))
(while (> num 1) ;; Do prev-sibling arg nbr of times
(setq iter-child (js2-node-prev-sibling iter-child))
(setq num (1- num)))
iter-child)
last-child)) ; No optional arg. Just use last-child
(last-child-beg (save-excursion
(goto-char (js2-node-abs-pos first-barf-child))
(skip-syntax-backward " ")
(while (looking-back "\n") (backward-char))
(point)))
(last-child-end (js2-node-abs-end last-child))
(text (buffer-substring last-child-beg last-child-end)))
(save-excursion
(js2r--execute-changes
(list
(list :beg last-child-beg :end last-child-end :contents "")
(list :beg standalone-end :end standalone-end :contents text)))))))
(provide 'js2r-paredit)
;;; js2r-paredit.el ends here

Binary file not shown.

View File

@@ -0,0 +1,348 @@
;;; js2r-vars.el --- Variable declaration manipulation functions for js2-refactor -*- lexical-binding: t; -*-
;; Copyright (C) 2012-2014 Magnar Sveen
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
;; Author: Magnar Sveen <magnars@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
;; Keywords: conveniences
;; 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 <http://www.gnu.org/licenses/>.
;;; Code:
(require 'multiple-cursors-core)
(require 'dash)
(require 'js2r-helpers)
;; Helpers
(defun js2r--name-node-at-point (&optional pos)
(setq pos (or pos (point)))
(let ((current-node (js2-node-at-point pos)))
(unless (js2-name-node-p current-node)
(setq current-node (js2-node-at-point (- (point) 1))))
(if (not (and current-node (js2-name-node-p current-node)))
(error "Point is not on an identifier.")
current-node)))
(defun js2r--local-name-node-at-point (&optional pos)
(setq pos (or pos (point)))
(let ((current-node (js2r--name-node-at-point pos)))
(unless (js2r--local-name-node-p current-node)
(error "Point is not on a local identifier"))
current-node))
(defun js2r--local-name-node-p (node)
(let ((parent (js2-node-parent node)))
(and parent (js2-name-node-p node)
;; is not foo in { foo: 1 }
(not (and (js2-object-prop-node-p parent)
(eq node (js2-object-prop-node-left parent))
;; could be { foo } though, in which case the node
;; is parent's both left and right.
(not (eq node (js2-object-prop-node-right parent)))))
;; is not foo in x.foo
(not (and (js2-prop-get-node-p parent)
(eq node (js2-prop-get-node-right parent))))
;; is not foo in import { foo as bar } from ...
;; could be bar, though.
(not (and (js2-export-binding-node-p parent)
(eq node (js2-export-binding-node-extern-name parent))
(not (eq node (js2-export-binding-node-local-name parent))))))))
(defun js2r--name-node-defining-scope (name-node)
(unless (js2r--local-name-node-p name-node)
(error "Node is not on a local identifier"))
(js2-get-defining-scope
(js2-node-get-enclosing-scope name-node)
(js2-name-node-name name-node)))
(defun js2r--local-usages-of-name-node (name-node)
(unless (js2r--local-name-node-p name-node)
(error "Node is not on a local identifier"))
(let* ((name (js2-name-node-name name-node))
(scope (js2r--name-node-defining-scope name-node))
(result nil))
(js2-visit-ast
scope
(lambda (node end-p)
(when (and (not end-p)
(js2r--local-name-node-p node)
(string= name (js2-name-node-name node))
(eq scope (js2r--name-node-defining-scope node)))
(add-to-list 'result node))
t))
result))
(defun js2r--local-var-positions (name-node)
(-map 'js2-node-abs-pos (js2r--local-usages-of-name-node name-node)))
(defun js2r--var-defining-node (var-node)
(unless (js2r--local-name-node-p var-node)
(error "Node is not on a local identifier"))
(let* ((name (js2-name-node-name var-node))
(scope (js2r--name-node-defining-scope var-node)))
(js2-symbol-ast-node
(js2-scope-get-symbol scope name))))
;; Add to jslint globals annotation
(defun current-line-contents ()
"Find the contents of the current line, minus indentation."
(buffer-substring (save-excursion (back-to-indentation) (point))
(save-excursion (end-of-line) (point))))
(require 'thingatpt)
(defun js2r-add-to-globals-annotation ()
(interactive)
(let ((var (thing-at-point 'symbol)))
(save-excursion
(beginning-of-buffer)
(when (not (string-match "^/\\* *global " (current-line-contents)))
(newline)
(forward-line -1)
(insert "/* global */")
(newline)
(forward-line -1))
(while (not (string-match "*/" (current-line-contents)))
(forward-line))
(end-of-line)
(delete-char -2)
(unless (looking-back "global ")
(while (looking-back " ")
(delete-char -1))
(insert ", "))
(insert (concat var " */")))))
;; Rename variable
(defun js2r-rename-var ()
"Renames the variable on point and all occurrences in its lexical scope."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(let* ((current-node (js2r--local-name-node-at-point))
(len (js2-node-len current-node))
(current-start (js2-node-abs-pos current-node))
(current-end (+ current-start len)))
(save-excursion
(mapc (lambda (beg)
(when (not (= beg current-start))
(goto-char beg)
(set-mark (+ beg len))
(mc/create-fake-cursor-at-point)))
(js2r--local-var-positions current-node)))
(push-mark current-end)
(goto-char current-start)
(activate-mark))
(mc/maybe-multiple-cursors-mode)))
(add-to-list 'mc--default-cmds-to-run-once 'js2r-rename-var)
;; Change local variable to use this. instead
(defun js2r-var-to-this ()
"Changes the variable on point to use this.var instead."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(save-excursion
(let ((node (js2-node-at-point)))
(when (js2-var-decl-node-p node)
(let ((kids (js2-var-decl-node-kids node)))
(when (cdr kids)
(error "Currently does not support converting multivar statements."))
(goto-char (js2-node-abs-pos (car kids))))))
(--each (js2r--local-var-positions (js2r--local-name-node-at-point))
(goto-char it)
(cond ((looking-back "var ") (delete-char -4))
((looking-back "let ") (delete-char -4))
((looking-back "const ") (delete-char -6)))
(insert "this.")))))
;; Inline var
(defun js2r-inline-var ()
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(save-excursion
(let* ((current-node (js2r--local-name-node-at-point))
(definer (js2r--var-defining-node current-node))
(definer-start (js2-node-abs-pos definer))
(var-init (js2-node-parent definer))
(initializer (js2-var-init-node-initializer
var-init)))
(unless initializer
(error "Var is not initialized when defined."))
(let* ((var-len (js2-node-len current-node))
(init-beg (js2-node-abs-pos initializer))
(init-end (+ init-beg (js2-node-len initializer)))
(var-init-beg (copy-marker (js2-node-abs-pos var-init)))
(var-init-end (copy-marker (+ var-init-beg (js2-node-len var-init))))
(contents (buffer-substring init-beg init-end)))
(mapc (lambda (beg)
(when (not (= beg definer-start))
(goto-char beg)
(delete-char var-len)
(insert contents)))
(js2r--local-var-positions current-node))
(js2r--delete-var-init var-init-beg var-init-end))))))
(defun js2r--was-single-var ()
(save-excursion
(goto-char (point-at-bol))
(or (looking-at "^[[:space:]]*\\(var\\|const\\|let\\)[[:space:]]?;?$")
(looking-at "^[[:space:]]*,[[:space:]]*$"))))
(defun js2r--was-starting-var ()
(or (looking-back "var ")
(looking-back "const ")
(looking-back "let ")))
(defun js2r--was-ending-var ()
(looking-at ";"))
(defun js2r--delete-var-init (beg end)
(goto-char beg)
(delete-char (- end beg))
(cond
((js2r--was-single-var)
(delete-region (point-at-bol) (point-at-eol))
(delete-blank-lines))
((js2r--was-starting-var)
(delete-char 1)
(if (looking-at " ")
(delete-char 1)
(join-line -1)))
((js2r--was-ending-var)
(if (looking-back ", ")
(delete-char -1)
(join-line)
(delete-char 1))
(delete-char -1))
(t (delete-char 2))))
;; two cases
;; - it's the only var -> remove the line
;; - there are several vars -> remove the node then clean up commas
;; Extract variable
(defun js2r--start-of-parent-stmt ()
(js2-node-abs-pos (js2r--closest-stmt-node)))
(defun js2r--object-literal-key-behind (pos)
(save-excursion
(goto-char pos)
(when (looking-back "\\sw: ?")
(backward-char 2)
(js2-name-node-name (js2r--name-node-at-point)))))
(defun js2r--line-above-is-blank ()
(save-excursion
(forward-line -1)
(string= "" (current-line-contents))))
;;;###autoload
(defun js2r-extract-var ()
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(if (use-region-p)
(js2r--extract-var-between (region-beginning) (region-end))
(let ((node (js2r--closest-extractable-node)))
(js2r--extract-var-between (js2-node-abs-pos node)
(js2-node-abs-end node))))))
(add-to-list 'mc--default-cmds-to-run-once 'js2r-extract-var)
(defun js2r--extract-var-between (beg end)
(interactive "r")
(unless (js2r--single-complete-expression-between-p beg end)
(error "Can only extract single, complete expressions to var"))
(let ((deactivate-mark nil)
(expression (buffer-substring beg end))
(orig-var-end (make-marker))
(new-var-end (make-marker))
(name (or (js2r--object-literal-key-behind beg) "name")))
(delete-region beg end)
(insert name)
(set-marker orig-var-end (point))
(goto-char (js2r--start-of-parent-stmt))
(js2r--insert-var name)
(set-marker new-var-end (point))
(insert " = " expression ";")
(when (or (js2r--line-above-is-blank)
(string-match-p "^function " expression))
(newline))
(newline)
(indent-region new-var-end orig-var-end)
(save-excursion
(goto-char new-var-end)
(set-mark (- (point) (length name)))
(mc/create-fake-cursor-at-point))
(goto-char orig-var-end)
(set-mark (- (point) (length name)))
(set-marker orig-var-end nil)
(set-marker new-var-end nil))
(mc/maybe-multiple-cursors-mode))
(defun js2r--insert-var (name)
"Insert a var definition for NAME."
(let ((keyword (if js2r-prefer-let-over-var
"let"
"var")))
(insert (format "%s %s" keyword name))))
(defun js2r-split-var-declaration ()
"Split a variable declaration into separate variable
declarations for each declared variable."
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(save-excursion
(let* ((declaration (or (js2r--closest #'js2-var-decl-node-p) (error "No var declaration at point.")))
(kids (js2-var-decl-node-kids declaration))
(stmt (js2-node-parent-stmt declaration)))
(goto-char (js2-node-abs-end stmt))
(mapc (lambda (kid)
(js2r--insert-var (js2-node-string kid))
(insert ";")
(newline)
(if (save-excursion
(goto-char (js2-node-abs-end kid))
(looking-at ", *\n *\n"))
(newline)))
kids)
(delete-char -1) ;; delete final newline
(let ((end (point)))
(js2r--goto-and-delete-node stmt)
(indent-region (point) end))))))
(provide 'js2r-vars)
;;; js2-vars.el ends here

Binary file not shown.

View File

@@ -0,0 +1,76 @@
;;; js2r-wrapping.el --- Helper functions for wrapping/unwrapping -*- lexical-binding: t; -*-
;; Copyright (C) 2017 Nicolas Petton
;; Author: Nicolas Petton
;; 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 <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'yasnippet)
(require 'js2r-helpers)
(defvar js2r--space-str " \t\n")
(defun js2r--skip-region-whitespace ()
(let ((p-first (< (point) (mark))))
(unless p-first
(exchange-point-and-mark))
(skip-chars-forward js2r--space-str)
(exchange-point-and-mark)
(skip-chars-backward js2r--space-str)
(when p-first
(exchange-point-and-mark))))
(defun js2r-unwrap ()
(interactive)
(js2r--guard)
(js2r--wait-for-parse
(let (beg end)
(if (use-region-p)
(progn
(js2r--skip-region-whitespace)
(setq beg (min (point) (mark)))
(setq end (max (point) (mark))))
(let ((stmt (js2-node-parent-stmt (js2-node-at-point))))
(setq beg (js2-node-abs-pos stmt))
(setq end (js2-node-abs-end stmt))))
(let* ((ancestor (js2-node-parent-stmt
(js2r--first-common-ancestor-in-region beg end)))
(abeg (js2-node-abs-pos ancestor))
(aend (js2-node-abs-end ancestor)))
(save-excursion
(goto-char end)
(delete-char (- aend end))
(goto-char abeg)
(delete-char (- beg abeg)))
(indent-region (point-min) (point-max))))))
(defun js2r-wrap-in-for-loop (beg end)
(interactive "r")
(js2r--skip-region-whitespace)
(setq beg (min (point) (mark)))
(setq end (max (point) (mark)))
(let ((yas-wrap-around-region t))
(yas-expand-snippet "for (var i = 0, l = ${1:length}; i < l; i++) {\n$0\n}"
beg end)))
(provide 'js2r-wrapping)
;;; js2r-wrapping.el ends here

Binary file not shown.