js-emacs / js2-refactor.el Goto Github PK
View Code? Open in Web Editor NEWA JavaScript refactoring library for emacs
License: GNU General Public License v3.0
A JavaScript refactoring library for emacs
License: GNU General Public License v3.0
I'd like to know if it's possible to base this on js3-mode:
https://github.com/thomblake/js3-mode
iEdit allows more interactive and visible renaming than query-and-replace
https://github.com/victorhge/iedit
Even better if it can be made into a generic refactoring library
into which we can hook language support.
Cheers,
Yesudeep.
Since Emacs belive C-m is the RET key im not able to bind C-c C-m , Emacs is just telling me C-c RET is undefined.
Is there something im missing when using the following line of code to actually make this binding?
(js2r-add-keybindings-with-prefix "C-c C-m")
I'm using eslint, and the docs specify that the globals declaration should look like /* global ...*/
and currently when you call js2r-add-to-globals-annotation
it adds a new global declaration that doesn't have a space before global.
In a buffer like the following, being + the mark and * the point (that is, everything inside the parentheses is selected):
else if(+38 in game.keysDown*) { // Up
After M-x js2r-extract-var
this is the result:
else var name = 38 in game.keysDown;
if(name) { // Up
I don't know if it would be easy to go up to the first if statement of the "if - else if" from there.
js2-refactor is mirrored on the Emacsmirror, which is a large up-to-date collection of Emacs packages.
As the maintainer of the mirror I am trying to resolve feature conflicts that result from one package bundling libraries from another package. I suspect in most cases these libraries were included so that users would not have to find, download and install each dependency manually.
Unfortunately bundling also has negative side-effects: if the bundled libraries are also installed separately, then it is undefined which version actually gets loaded when the respective feature is required.
Initially that isn't a big problem but in many cases upstream changes are not included or only after a long delay. This can be very confusing for users who are not aware that some of the installed packages bundle libraries which are also installed separately. In other cases bugs are fixed in the bundled versions but the fixes are never submitted to upstream.
Also now that Emacs contains the package.el package manager there is a better way to not require users to manually deal with dependencies: add the package (and when that hasn't been done yet the dependencies) to the Melpa package repository. If make
is required to install your make you might want to add it to the el-get (another popular package manager) package repository instead.
Alternatively if you want to keep bundling these libraries please move them to a directory only containing bundled libraries and add the file ".nosearch" to that directory. You can then load the library using something like this:
(or (require 'bundled nil t)
(let ((load-path
(cons (expand-file-name "fallback-libs"
(or load-file-name buffer-file-name)
load-path))))
(require 'bundled)))
Of course if your version differs from the upstream version this might not be enough in which case you should make an effort to get your changes merged upstream.
js2-refactor bundles at least the following libraries:
Best regards,
Jonas
Currently js2 refactor doesn't work if you are using evil. This is because multiple cursors has issues with evil.
Though the underlying problem is with multiple cursors, when I encountered problems I wasn't even aware that js2-refactor used mutliple cursors, nor the incompatibility with evil. I don't use multiple cursors, and it was surprising
Here's a workaround ripped from the config files here. It disables evil while running in multiple cursors.
This workaround enables the js2-refactor commands.
;; =============================================================
;; Multiple cursors evil compat (use emacs mode during mc)
;; =============================================================
(defvar mc-evil-compat/evil-prev-state nil)
(defvar mc-evil-compat/mark-was-active nil)
(defun user-utils/evil-visual-or-normal-p ()
"True if evil mode is enabled, and we are in normal or visual mode."
(and (bound-and-true-p evil-mode)
(not (memq evil-state '(insert emacs)))))
(defun mc-evil-compat/switch-to-emacs-state ()
(when (user-utils/evil-visual-or-normal-p)
(setq mc-evil-compat/evil-prev-state evil-state)
(when (region-active-p)
(setq mc-evil-compat/mark-was-active t))
(let ((mark-before (mark))
(point-before (point)))
(evil-emacs-state 1)
(when (or mc-evil-compat/mark-was-active (region-active-p))
(goto-char point-before)
(set-mark mark-before)))))
(defun mc-evil-compat/back-to-previous-state ()
(when mc-evil-compat/evil-prev-state
(unwind-protect
(case mc-evil-compat/evil-prev-state
((normal visual) (evil-force-normal-state))
(t (message "Don't know how to handle previous state: %S"
mc-evil-compat/evil-prev-state)))
(setq mc-evil-compat/evil-prev-state nil)
(setq mc-evil-compat/mark-was-active nil))))
(add-hook 'multiple-cursors-mode-enabled-hook
'mc-evil-compat/switch-to-emacs-state)
(add-hook 'multiple-cursors-mode-disabled-hook
'mc-evil-compat/back-to-previous-state)
(defun mc-evil-compat/rectangular-switch-state ()
(if rectangular-region-mode
(mc-evil-compat/switch-to-emacs-state)
(setq mc-evil-compat/evil-prev-state nil)))
;; When running edit-lines, point will return (position + 1) as a
;; result of how evil deals with regions
(defadvice mc/edit-lines (before change-point-by-1 activate)
(when (user-utils/evil-visual-or-normal-p)
(if (> (point) (mark))
(goto-char (1- (point)))
(push-mark (1- (mark))))))
(add-hook 'rectangular-region-mode-hook 'mc-evil-compat/rectangular-switch-state)
(defvar mc--default-cmds-to-run-once nil)
Hi I'm new to emacs, so this is probably a configuration failure on my behalf, but I can't figure it out and I am looking for advise.
I installed js2-refactor tonight, but when I mark an area and or move the point to a variable and try to execute a command I get the error No JavaScript AST available
in the minbuffer. Opening the Messages I see the error in the is issue name.
How is the JavaScript AST built? What would cause it not to build?
I've tried extract variable, extract method, split var, split string and rename variable. I've also tried via the keybindings and using M-x js2r-...
Should have a function to universally expand/contract array, object, function, etc.
I've made a PR #79
Please review.
I end up passing in a lot of callbacks in JS, so it would be very useful to be able to go from:
foo()
to
function() { foo() }
What do you think? I'm still exploring js2-refactor, so forgive me if this is already possible.
I think it would be a really useful feature when refactoring code. While knowing the actual String literal* of an expression is impossible without dynamic analysis (running the script in its proper context), refactoring a String concatenation to a String template literal is possible given that we take into account priority of operations. By a template literal, I mean the new ECMA-Script 6 feature that allows us to do:
var str1 = 'Hello';
var str2 = 'World';
var message = str1 + ' ' + str2 + '!';
// message = 'Hello World!'
With the following syntax:
var str1 = 'Hello';
var str2 = 'World';
var message = `${str1} ${str2}!';
// message = 'Hello World!'
Given a concatenation (with +
operator), it should be possible to transform both form to the other form.
*This is also the case about knowing the actual concatenation result.
Hi there. I've written a function for adding declarations to multi-line var
statements. I developed it in the js2-mode
repo and submitted a PR for it there, but now I see that this might be a better home for it.
If you're interested, I could port it to this project. It is pretty well-tested in the js2-mode
repo. Maybe I can do some regular expression replacements to convert the tests into your format.
This is an question open for discussion, I don't know the answer.
In paredit, when killing, the entire list will be killed, even on several lines. In js2r, the node is killed only if the end on the node is on the same line.
js2r-kill
could behave like this:
foo|({
bar: 2
});
baz();
Killing would kill up to the end of the node foo, including the closing parenthesis, like the following:
foo|
baz();
I most of the time (if not all the time), I expect this behavior. But I'm also very used to the way it works in paredit, so..
hi Sveen,
I've got the following error while requiring js2-refactor
:
File error: Cannot open load file, bang
Can't figure out why
I often forget one or two possible refactorings of js2-refactor. Then I have to go to the Help of the mode to find out which one I want.
Using makey would greatly improve discoverability. If it makes sense to add it, I'd be willing to spend some time on it and send a PR :)
To use this package with Melpa-stable, we need to bump the version number and create a new tag, so that this fix #56 is included in the package distributed by Melpa-stable.
--> installing javascript:js2-refactor... [4/9]
An error occurred while installing js2-refactor
(error: (cl-assertion-failed (or (= (buffer-size tar-data-buffer) (buffer-size)) (eq tar-data-swapped (> (buffer-size tar-data-buffer) (buffer-size))))))
Windows 10
GNU Emacs 24.5.1 (i686-pc-mingw32)
I ran into an case where rename-variable doesn't work as expected. Consider the code below. Renaming the module-scoped var a
will also change the names of the formal parameter a
and the inner function-scoped var a
.
In this case, I'm reverse-engineering from minified source so inner scopes often use the same names. So while "not reusing variable names" is good advice that I would generally agree with, in this case it wasn't an option.
My workaround for now is to rename from inner scope out when possible.
(function () {
var a;
a=1;
function renameVarDoesNotRespectInnerFunctionParameterNames(a){
a = "";
}
function renameVariableDoesNotRespectIndependentInnerScopes() {
var a = [];
a.push({key: "value"});
}
}());
Could ef
not presume a clj-context when running extract-function?
The regexps in js2r--current-line-is-prefixed-with-list-item-start
and js2r--current-line-is-postfixed-with-list-item-end
don't take tabs into account.
It would be awesome to have paredit-like killing in js2r, just like there's barfing and slurping.
I'll try to do something and send a PR if you think it could be useful.
Feature creep request :)
Would be really nice to be able to do "M-3 C-c C-m s l" instead of:
"C-c C-m s l" followed by "C-x z z z". It would work similar to how kill-line and delete-char works.
I'm fairly new to emacs, so this could be a simple fix and I'm not yet sophisticated enough as a user to figure it out. I presume the workaround would be to dl and compile from sources? Any insight would be helpful.
Is it possible to enable this mode in other major mode to enjoy them?
Right now a lot of the refactors assume that I want to refactor with ES5 syntax.
Most of my codebases are using ES6 at this point, so I often have to change vars and functions. It would be nice to have a setting that would convert var
s to let
s or const
s and function()
s to () =>
s.
I'd be more than happy to implement something like this myself if there's interest in the features.
Hi! I'm working on some ES6 code and just noticed that inline var'ing leaves behind a onst ;
or et ;
when inlining a variable declared with either const
or let
. Example:
// before
const test = function() {
const thing = 'Thing';
console.log(thing);
};
// after
const test = function() onst ;
console.log('Thing');
};
A similar thing happens with let
.
I'm happy to try to work on a patch though I'm somewhere between total notice and reckless amateur when it comes to elisp and it'd be helpful if you pointed me in the general direction of the relevant code :)
Currently,
const foo = true ? 1: 2;
console.log(foo);
expands to:
if (true) {
const foo = 1;
} else {
const foo = 2;
}
console.log(foo); // error
Not the error on the next line since foo is no longer defined in that scope.
Would it be possible to change the behavior to support expansion like this:
let foo;
if (true) {
foo = 1;
} else {
foo = 2
}
console.log(foo); // ok
Hi,
I really love the js2r-kill feature! There is one bug though: When the cursor (visualized by |
in this report) is right ahead of a quotation block: "
or '
, it kills only to the exiting quotation. Example:
console.log(|"My string that I want to delete...");
// Running js2r-kill with cursor at the | results in:
console.log(|");
// But should be:
console.log(|);
// And even worse, if you run js2r-kill again, it doesn't know
// what to do (unbalanced quote), so it ends up with normal kill:
console.log(|
The problem occurs only when the cursor is right ahead of the quote. So these scenarios works fine:
console.log(| "This string comes after a space");
console.log(|otherArg, "StringArg");
// both results correctly:
console.log(|);
beforeEach(function () {
spyOn(Foo, 'bar').andReturn('baz');
)};
When I try to run jsr-extract-var
on 'baz'
:
beforeEach(function () var name = '1';
{
spyOn(Foo, 'bar').andReturn(name);
});
Could add function to expand / contract function arguments
?
It's important if writing mithril.js
Like below source code:
view: function (ctrl) {
return m('table.overlay', {style:{border:0, padding:0, margin:0, width:ctrl.width+'px', height:ctrl.height+'px', backgroundColor:'rgba(0,0,0,0.5)'}},
m('tr', m('td', {align:'center'}, m('div', {style:{width:'200px'}}, "some text"))))
}
If can format the arguments for m
function, it's perfect.
Hi Magnar! I've got provisional code for expand-function
, contract-function
, expand-array
, and contract-array
in my fork, implemented via further abstraction of the js2r--create-object-whitespace-traverser
macro. I'd be interested to know what you think before I submit a pull request. Thanks!
would js2-refactor work with typescript-mode or is it only for js/js2 mode?
I would love to see this module having command to add jsdoc style function/method documentation based on customizable template. Something similar to https://github.com/mooz/js-doc/blob/master/js-doc.el
It would be great it some commands could detect whethe there is jsdoc for refactored function and amend it. For example it would be cool to have @param tag added once you call introduce-parameter, or have it removed when you call localize-parameter.
Currently I am working on project, which has very strict jsdoc guidelines and such helpers would save me fair bit of time.
If you think it is something worth adding to package, I am happy to spend some time on working on it. Anny suggestions about implementation, especially binding it to existing functions are highly appreciated.
js3-refactor is a fork of this repo. I see js2-refactor has gone ahead. Can these projects be merged?
Alternatively can this be made to work with js3-mode?
Another feature I'd love to see: the ability to require a variable at point. From
foo.bar()
to
var foo = require('foo');
foo.bar();
we could take the 'foo' from the symbol at point, or scan the enclosing directory, or scan the node_modules directory.
Is there a reason the keys are added exclusively to the js2-mode-map?
If js2-refactor also works when only using the js2-minor-mode, it would make sense to set up keybindings there as well.
same as #23, I think it would be really cool to have :)
When collapsing arrays, call-args, and objects, a space is inserted between the brackets and items.
For example, starting with
[
1,
2,
3,
4,
5
]
Collapsing gives us
[ 1, 2, 3, 4, 5 ]
while my desired output is
[1, 2, 3, 4, 5]
It would be useful to expose an option to omit or include these extra spaces per list type. I can open a PR with this change.
I'm in the process of writing a function that distributes a long string across lines, adding and removing pluses as necessary. Is this something that could be included in this package?
Feature request :)
I used lots of class in my project, is it possible to use introduce-parameter for a method like this:
var MyClass = {
foo: function() {
var varToIntroduced = ...
},
};
and:
var MyClass = _.extend(Object.create(BaseClass), {
foo: function() {
var varToIntroduced = ...
},
});
When extracting a variable, I end up with only one cursor, so renaming the new variable doesn't rename it in both places.
The weird thing is that when I instrument js2r--extract-var-between
and evaluate it using edebug, I do get multiple-cursors.
I'm using multiple-cursors-20131215.1047, js2-mode-20131219.658 and js2-refactor-20130622.1117 from melpa.
Hey magnars
I use js3 mode, and they go off of the jslint globals comment annotation on whether or not to show the "Undefined variable" warning. The annotation is a comment that looks like this at the top of the file
/* globals $ Backbone MyGlobal */
I wrote a small defun to add the word at point to that list, and create the list if its not already there, and also supports that comment being multi line. I figured since it is sort of a js convention, it may fit in this project. If you agree, here it is :)
(defun add-to-js-globals ()
(interactive)
(let ((var (word-at-point)))
(save-excursion
(beginning-of-buffer)
(when (not (string-match "^/\\* global " (current-line)))
(newline)
(previous-line)
(insert "/* global */"))
(while (not (string-match "*/" (current-line)))
(next-line))
(end-of-line)
(delete-char -2)
(insert (concat var " */")))))
Inlining asdfg (set cursor on it & M-x js2r-inline-var)
function xxx() {
return asdfg;
}
var asdfg = "xx", qwe = "yy";
leads to code
function xxx() {
return "xx";
}
var awe = "yy";
so asdfg declaration isn't removed properly.
GNU Emacs 24.4.1 with pkg versions (from elpa/melpa/marmalade):
dash-20150311.2355
js2-mode-20150406.1341
js2-refactor-20150308.1235
multiple-cursors-20150307.2322
s-20140910.334
yasnippet-20150405.1526
js2r-expand-array
etc., using below use case:
var a = [
// 1 , 2
3, 4
]
will result in below:
var a = [
// 1 ,
2
3,
4
]
The subexpr-str
part should check in comments case.
WIth the following code (the cursor being |), killing doesn't work as expected (it should kill the function):
// test
|var hello = function(test) {
};
When i extract function it changes the marked text to the function calls, but does'nt create the function.
Error:
Debugger entered--Lisp error: (wrong-type-argument arrayp nil)
js2-node-abs-pos(nil)
js2r--extract-fn("sdfkjl" #[nil "\300 ?\205\f^@\301\302\303!!b\207" [js2r--looking-at$
js2r-extract-function("sdfkjl")
call-interactively(js2r-extract-function nil nil)
This should be a pretty basic emacs 24.2.1 install with only js2-mode and js2-refactor installed via Melpa
Hi,
When I run the tests, they all fail with the info "No JavaScript AST available". Example output from one of the failing tests:
Scenario: Values
Given I insert "abc(123, 4 + 5, 'hello');"
And I turn on js2-mode
And I turn on js2-refactor-mode
When I go to the end of the word "abc"
And I press "C-c C-m ao"
No JavaScript AST available
Then I should see:
"""
abc({
key: 123,
key: 4 + 5,
key: 'hello'
});
"""
If any one have any ideas how I can proceed debugging it, please let me know!
Running osx and emacs 24.5.1.
When js2r-add-keybindings-with-prefix
add a prefix, it should also save that prefix as a global or local variable for reference by other function, e.g., want to extend js2r shortcuts using existing prefix.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.