Skip to content

Commit

Permalink
manually install js2-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ryangMYOB committed Oct 2, 2014
1 parent 6cf7a91 commit 4066315
Show file tree
Hide file tree
Showing 11 changed files with 1,149 additions and 1 deletion.
3 changes: 3 additions & 0 deletions github/js2-refactor-pkg.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(define-package "js2-refactor" "0.6.1"
"A JavaScript refactoring library for emacs."
'((js2-mode "20101228") (multiple-cursors "1.0.0") (dash "1.0.0") (s "1.0.0") (yasnippet "20130218")))
156 changes: 156 additions & 0 deletions github/js2-refactor.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
;;; js2-refactor.el --- The beginnings of a JavaScript refactoring library in emacs.

;; Copyright (C) 2012 Magnar Sveen

;; Author: Magnar Sveen <[email protected]>
;; 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)

;; 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.

;; * `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.
;; * `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.
;; * `eo` is `expand-object`: Converts a one line object literal to multiline.
;; * `co` is `contract-object`: Converts a multiline object literal to one line.
;; * `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. Requires yasnippets.
;; * `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.
;; * `uw` is `unwrap`: Replaces the parent statement with the selected region.

;; 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.

;; ## Todo

;; A list of some wanted improvements for the current refactorings.

;; * expand- and contract-object: should work for arrays.
;; * expand- and contract-object: should work for simple functions.
;; * 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`

;; 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)

;;; Settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defvar js2r-use-strict nil
"When non-nil, js2r inserts strict declarations in IIFEs.")

;;; Keybindings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun js2r--add-keybindings (key-fn)
(define-key js2-mode-map (funcall key-fn "eo") 'js2r-expand-object)
(define-key js2-mode-map (funcall key-fn "co") 'js2r-contract-object)
(define-key js2-mode-map (funcall key-fn "wi") 'js2r-wrap-buffer-in-iife)
(define-key js2-mode-map (funcall key-fn "ig") 'js2r-inject-global-in-iife)
(define-key js2-mode-map (funcall key-fn "ev") 'js2r-extract-var)
(define-key js2-mode-map (funcall key-fn "iv") 'js2r-inline-var)
(define-key js2-mode-map (funcall key-fn "rv") 'js2r-rename-var)
(define-key js2-mode-map (funcall key-fn "vt") 'js2r-var-to-this)
(define-key js2-mode-map (funcall key-fn "ag") 'js2r-add-to-globals-annotation)
(define-key js2-mode-map (funcall key-fn "sv") 'js2r-split-var-declaration)
(define-key js2-mode-map (funcall key-fn "ef") 'js2r-extract-function)
(define-key js2-mode-map (funcall key-fn "em") 'js2r-extract-method)
(define-key js2-mode-map (funcall key-fn "ip") 'js2r-introduce-parameter)
(define-key js2-mode-map (funcall key-fn "lp") 'js2r-localize-parameter)
(define-key js2-mode-map (funcall key-fn "tf") 'js2r-toggle-function-expression-and-declaration)
(define-key js2-mode-map (funcall key-fn "ao") 'js2r-arguments-to-object)
(define-key js2-mode-map (funcall key-fn "uw") 'js2r-unwrap)
(define-key js2-mode-map (funcall key-fn "wl") 'js2r-wrap-in-for-loop)
(define-key js2-mode-map (funcall key-fn "3i") 'js2r-ternary-to-if)
(define-key js2-mode-map (kbd "<C-S-down>") 'js2r-move-line-down)
(define-key js2-mode-map (kbd "<C-S-up>") 'js2r-move-line-up))

;;;###autoload
(defun js2r-add-keybindings-with-prefix (prefix)
(js2r--add-keybindings (-partial 'js2r--key-pairs-with-prefix prefix)))

;;;###autoload
(defun js2r-add-keybindings-with-modifier (modifier)
(js2r--add-keybindings (-partial 'js2r--key-pairs-with-modifier modifier)))

(provide 'js2-refactor)
;;; js2-refactor.el ends here
28 changes: 28 additions & 0 deletions github/js2r-conditionals.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(require 'org)

(defun js2r-ternary-to-if ()
(interactive)
(js2r--guard)
(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 (org-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)
104 changes: 104 additions & 0 deletions github/js2r-conveniences.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
;; Split a string

(defun js2r-split-string ()
(interactive)
(when (js2r--point-inside-string-p)
(if (looking-back " \"")
(progn
(forward-char -2)
(insert " +")
(forward-char -2))
(if (looking-at (regexp-quote "\" + \""))
(delete-char 5)
(insert "\" + \"")))))

;; Make sure commas are placed correctly when moving a line up or down
;; in an object or array literal.

(defun move-line-down ()
(interactive)
(let ((col (current-column)))
(save-excursion
(forward-line)
(transpose-lines 1))
(forward-line)
(move-to-column col)))

(defun move-line-up ()
(interactive)
(let ((col (current-column)))
(save-excursion
(forward-line)
(transpose-lines -1))
(move-to-column col)))

(defun js2r--current-line-is-prefixed-with-list-item-start ()
(save-excursion
(back-to-indentation)
(looking-back "\\({\\|\\[\\|,\\)\\(\s\\|\n\\)*"))) ; { or [ or , then space

(defun js2r--current-line-is-postfixed-with-list-item-end ()
(save-excursion
(end-of-line)
(or (looking-back ",\s*") ; line ends in comma
(looking-at "\\(\s\\|\n\\)*\\(\\]\\|}\\)")))) ; space then ] or }

(defun js2r--current-line-is-a-list-item ()
(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 ()
(save-excursion
(forward-line)
(js2r--current-line-is-a-list-item)))

(defun js2r--previous-line-is-a-list-item ()
(save-excursion
(forward-line -1)
(js2r--current-line-is-a-list-item)))

(defun js2r--current-line-has-comma ()
(save-excursion
(end-of-line)
(looking-back ",\s*")))

(defun js2r--previous-line-has-comma ()
(save-excursion
(forward-line -1)
(js2r--current-line-has-comma)))

(defun js2r--move-line-down-as-list-item ()
(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-line-up)
(if (not (js2r--current-line-has-comma))
(save-excursion
(end-of-line)
(insert ",")
(forward-line)
(end-of-line)
(delete-char -1))))

(defun js2r-move-line-down ()
(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)))

(defun js2r-move-line-up ()
(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)))

(provide 'js2r-conveniences)
58 changes: 58 additions & 0 deletions github/js2r-formatting.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
(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))))))

(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-object-whitespace-traverser (name func)
`(defun ,name ()
(interactive)
(save-excursion
(if (not (js2r--looking-at-object-start))
(js2r--goto-closest-object-start))
(let ((end (make-marker)))
(set-marker end (save-excursion
(forward-list)
(point)))
(forward-char)
,func
(while (< (point) end)
(while (js2r--point-inside-string-p)
(forward-char))
(when (looking-at ",")
(forward-char)
,func)
(if (looking-at "\\s(")
(forward-list)
(forward-char)))
(backward-char)
,func))))

(js2r--create-object-whitespace-traverser js2r-expand-object
(js2r--ensure-newline))

(js2r--create-object-whitespace-traverser js2r-contract-object
(js2r--ensure-just-one-space))

(provide 'js2r-formatting)
Loading

0 comments on commit 4066315

Please sign in to comment.