From f54b4603b40086b3aad7e1bd7bf56ede67b8cdbd Mon Sep 17 00:00:00 2001 From: aviatesk Date: Fri, 11 Oct 2019 06:00:36 +0900 Subject: [PATCH 1/9] basic setup of rename-refactor command --- lib/misc/blocks.js | 1 + lib/package/commands.coffee | 4 ++ lib/runtime.coffee | 3 +- lib/runtime/refactor.js | 75 +++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 lib/runtime/refactor.js diff --git a/lib/misc/blocks.js b/lib/misc/blocks.js index 4c281215..2a4204a0 100644 --- a/lib/misc/blocks.js +++ b/lib/misc/blocks.js @@ -132,6 +132,7 @@ export function getLocalContext (editor, row) { const context = range ? editor.getTextInBufferRange(range) : '' const startRow = range ? range[0][0] : undefined return { + range, context, startRow } diff --git a/lib/package/commands.coffee b/lib/package/commands.coffee index 72b4a7af..da58b1d5 100644 --- a/lib/package/commands.coffee +++ b/lib/package/commands.coffee @@ -52,6 +52,10 @@ module.exports = @withInk -> boot() juno.runtime.evaluation.toggleDocs() + 'julia-client:rename-refactor': => + @withInk -> + boot() + juno.runtime.refactor.refactor() # @NOTE: `'clear-workspace'` is now not handled by Atom.jl # 'julia-client:reset-workspace': => # requireClient 'reset the workspace', -> diff --git a/lib/runtime.coffee b/lib/runtime.coffee index 2eb63211..ca58718d 100644 --- a/lib/runtime.coffee +++ b/lib/runtime.coffee @@ -15,6 +15,7 @@ module.exports = debuginfo: require './runtime/debuginfo' formatter: require './runtime/formatter' goto: require './runtime/goto' + refactor: require './runtime/refactor' activate: -> @subs = new CompositeDisposable() @@ -29,7 +30,7 @@ module.exports = consumeInk: (ink) -> @evaluation.ink = ink @frontend.ink = ink - for mod in [@console, @debugger, @profiler, @linter, @goto, @outline] + for mod in [@console, @debugger, @profiler, @linter, @goto, @outline, @refactor] mod.activate(ink) for mod in [@workspace, @plots] mod.ink = ink diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js new file mode 100644 index 00000000..7a1b99d6 --- /dev/null +++ b/lib/runtime/refactor.js @@ -0,0 +1,75 @@ +'use babel' + +import { client } from '../connection' +import modules from './modules' +import { wordRegex, getWord, isValidWordToInspect } from '../misc/words' +import { getLocalContext } from '../misc/blocks' + +const { refactor: _refactor } = client.import(['refactor']) + +class Refactor { + activate (ink) { + this.ink = ink + } + + refactor () { + const editor = atom.workspace.getActiveTextEditor() + const bufferPosition = editor.getCursorBufferPosition() + + if (!client.isActive()) return + + const { word: old } = getWord(editor, bufferPosition) + if (!isValidWordToInspect(old)) return + + this.ink.showBasicModal([{ + name: 'Rename', + defaultText: old, + message: `Enter an new name to which \`${old}\` will be renamed.` + }]).then(items => { + // check the new name is a valid identifier + const _new = items['Rename'] + if (!isValidWordToInspect(_new) || _new.match(wordRegex) != _new) { + atom.notifications.addWarning('Julia Client: Rename Refactor', { + description: `\`${_new}\` is not a valid identifier` + }) + return + } + + // local context + const { column, row } = bufferPosition + const { range, context, startRow } = getLocalContext(editor, row) + + // module context + const currentModule = modules.current() + const mod = currentModule ? currentModule : 'Main' + + _refactor({ + old, + new: _new, + path: editor.getPath(), + // local context + column: column + 1, + row: row + 1, + startRow, + context, + // module context + mod, + }).then(result => { + if (result.error) { + atom.notifications.addWarning('Julia Client: Rename Refactor', { + description: result.error + }) + return + } + // local refactoring + if (result.text) { + editor.setTextInBufferRange(range, result.text) + } + }) + }).catch((err) => { + if (err) console.error(err) + }) + } +} + +export default new Refactor() From 437b6067e826532ed616c1f0e51f5fb726e2b68e Mon Sep 17 00:00:00 2001 From: aviatesk Date: Sat, 12 Oct 2019 02:08:34 +0900 Subject: [PATCH 2/9] ignore dot accessors in atom-julia-client --- lib/misc/words.js | 2 +- lib/runtime/refactor.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/misc/words.js b/lib/misc/words.js index 35776ebe..f2e9533d 100644 --- a/lib/misc/words.js +++ b/lib/misc/words.js @@ -2,7 +2,7 @@ import { Point, Range } from 'atom' -export const wordRegex = /[\u00A0-\uFFFF\w_!´\.]*@?[\u00A0-\uFFFF\w_!´]+/ +const wordRegex = /[\u00A0-\uFFFF\w_!´\.]*@?[\u00A0-\uFFFF\w_!´]+/ /** * Takes an `editor` and gets the word at current cursor position. If that is nonempty, call diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index 7a1b99d6..d15a4764 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -2,10 +2,11 @@ import { client } from '../connection' import modules from './modules' -import { wordRegex, getWord, isValidWordToInspect } from '../misc/words' +import { getWordRangeAtBufferPosition, isValidWordToInspect } from '../misc/words' import { getLocalContext } from '../misc/blocks' const { refactor: _refactor } = client.import(['refactor']) +const wordRegexWithoutDotAccessor = /@?[\u00A0-\uFFFF\w_!´]+/ class Refactor { activate (ink) { @@ -18,7 +19,9 @@ class Refactor { if (!client.isActive()) return - const { word: old } = getWord(editor, bufferPosition) + const range = getWordRangeAtBufferPosition(editor, bufferPosition, wordRegexWithoutDotAccessor) + if (range.isEmpty()) return + const old = editor.getTextInBufferRange(range) if (!isValidWordToInspect(old)) return this.ink.showBasicModal([{ @@ -28,7 +31,7 @@ class Refactor { }]).then(items => { // check the new name is a valid identifier const _new = items['Rename'] - if (!isValidWordToInspect(_new) || _new.match(wordRegex) != _new) { + if (!isValidWordToInspect(_new) || _new.match(wordRegexWithoutDotAccessor) != _new) { atom.notifications.addWarning('Julia Client: Rename Refactor', { description: `\`${_new}\` is not a valid identifier` }) From 8ed00eed0a25e45809a607d6e37d4d00bf7cb300 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Tue, 22 Oct 2019 00:42:18 +0900 Subject: [PATCH 3/9] misc refactors --- lib/runtime/profiler.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/runtime/profiler.js b/lib/runtime/profiler.js index c627c8dd..ca36fa7d 100644 --- a/lib/runtime/profiler.js +++ b/lib/runtime/profiler.js @@ -9,7 +9,7 @@ var {loadProfileTrace, saveProfileTrace} = client.import({msg: ['loadProfileTrac export function activate (ink) { pane = ink.PlotPane.fromId('Profile') - pane.getTitle = () => {return 'Profiler'} + pane.setTitle('Profiler') subs = new CompositeDisposable() subs.add(client.onDetached(() => clear())) @@ -24,7 +24,10 @@ export function activate (ink) { pane.ensureVisible({ split: atom.config.get('julia-client.uiOptions.layouts.profiler.split') }) - pane.show(new ink.Pannable(profile, {zoomstrategy: 'width', minScale: 0.5})) + pane.show(new ink.Pannable(profile, { + zoomstrategy: 'width', + minScale: 0.5 + })) } }) From 4b91ac7cd15859f422b7d32c9f5a2bd0a015c5a1 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Tue, 22 Oct 2019 05:45:06 +0900 Subject: [PATCH 4/9] better messaging & suppress field renaming --- lib/package/commands.coffee | 2 +- lib/runtime/refactor.js | 35 +++++++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/package/commands.coffee b/lib/package/commands.coffee index da58b1d5..55bdacb8 100644 --- a/lib/package/commands.coffee +++ b/lib/package/commands.coffee @@ -55,7 +55,7 @@ module.exports = 'julia-client:rename-refactor': => @withInk -> boot() - juno.runtime.refactor.refactor() + juno.runtime.refactor.renameRefactor() # @NOTE: `'clear-workspace'` is now not handled by Atom.jl # 'julia-client:reset-workspace': => # requireClient 'reset the workspace', -> diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index d15a4764..35cafb90 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -5,7 +5,7 @@ import modules from './modules' import { getWordRangeAtBufferPosition, isValidWordToInspect } from '../misc/words' import { getLocalContext } from '../misc/blocks' -const { refactor: _refactor } = client.import(['refactor']) +const renamerefactor = client.import('renamerefactor') const wordRegexWithoutDotAccessor = /@?[\u00A0-\uFFFF\w_!´]+/ class Refactor { @@ -13,7 +13,7 @@ class Refactor { this.ink = ink } - refactor () { + renameRefactor () { const editor = atom.workspace.getActiveTextEditor() const bufferPosition = editor.getCursorBufferPosition() @@ -24,6 +24,9 @@ class Refactor { const old = editor.getTextInBufferRange(range) if (!isValidWordToInspect(old)) return + const rangeFull = getWordRangeAtBufferPosition(editor, bufferPosition) + const full = editor.getTextInBufferRange(rangeFull) + this.ink.showBasicModal([{ name: 'Rename', defaultText: old, @@ -46,8 +49,9 @@ class Refactor { const currentModule = modules.current() const mod = currentModule ? currentModule : 'Main' - _refactor({ + renamerefactor({ old, + full, new: _new, path: editor.getPath(), // local context @@ -58,15 +62,30 @@ class Refactor { // module context mod, }).then(result => { - if (result.error) { + // local refactoring + if (result.text) { + editor.setTextInBufferRange(range, result.text) + } + if (result.info) { + atom.notifications.addInfo('Julia Client: Rename Refactor', { + description: result.info, + dismissable: true + }) + } + if (result.warning) { atom.notifications.addWarning('Julia Client: Rename Refactor', { + description: result.warning + }) + } + if (result.error) { + atom.notifications.addError('Julia Client: Rename Refactor', { description: result.error }) - return } - // local refactoring - if (result.text) { - editor.setTextInBufferRange(range, result.text) + if (result.success) { + atom.notifications.addSuccess('Julia Client: Rename Refactor', { + description: result.success + }) } }) }).catch((err) => { From e2be292cc445b28a989a98902450f655504a0843 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Tue, 22 Oct 2019 07:08:17 +0900 Subject: [PATCH 5/9] even better messaging --- lib/runtime/refactor.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index 35cafb90..123c621e 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -36,7 +36,7 @@ class Refactor { const _new = items['Rename'] if (!isValidWordToInspect(_new) || _new.match(wordRegexWithoutDotAccessor) != _new) { atom.notifications.addWarning('Julia Client: Rename Refactor', { - description: `\`${_new}\` is not a valid identifier` + description: `\`${_new}\` isn't a valid identifier` }) return } @@ -66,6 +66,12 @@ class Refactor { if (result.text) { editor.setTextInBufferRange(range, result.text) } + if (result.success) { + atom.notifications.addSuccess('Julia Client: Rename Refactor', { + description: result.success, + dismissable: true + }) + } if (result.info) { atom.notifications.addInfo('Julia Client: Rename Refactor', { description: result.info, @@ -82,11 +88,6 @@ class Refactor { description: result.error }) } - if (result.success) { - atom.notifications.addSuccess('Julia Client: Rename Refactor', { - description: result.success - }) - } }) }).catch((err) => { if (err) console.error(err) From d4425f0b42c6057d7b9df4ff06a5ba9bc66502c1 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Wed, 23 Oct 2019 06:34:34 +0900 Subject: [PATCH 6/9] add goto uri :tada: --- lib/runtime.coffee | 5 +-- lib/runtime/urihandler.js | 76 +++++++++++++++++++++++++-------------- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/lib/runtime.coffee b/lib/runtime.coffee index ca58718d..f3818a5f 100644 --- a/lib/runtime.coffee +++ b/lib/runtime.coffee @@ -15,6 +15,7 @@ module.exports = debuginfo: require './runtime/debuginfo' formatter: require './runtime/formatter' goto: require './runtime/goto' + urihandler: require './runtime/urihandler' refactor: require './runtime/refactor' activate: -> @@ -30,7 +31,7 @@ module.exports = consumeInk: (ink) -> @evaluation.ink = ink @frontend.ink = ink - for mod in [@console, @debugger, @profiler, @linter, @goto, @outline, @refactor] + for mod in [@console, @debugger, @profiler, @linter, @goto, @outline, @urihandler, @refactor] mod.activate(ink) for mod in [@workspace, @plots] mod.ink = ink @@ -61,4 +62,4 @@ module.exports = @subs.add(datatipDisposable) datatipDisposable - handleURI: require './runtime/urihandler' + handleURI: (parsedURI) -> @urihandler.handleURI parsedURI diff --git a/lib/runtime/urihandler.js b/lib/runtime/urihandler.js index e06a8148..9888c721 100644 --- a/lib/runtime/urihandler.js +++ b/lib/runtime/urihandler.js @@ -1,37 +1,59 @@ -"use babel" +/** @babel */ import { client } from '../connection' import { docpane, views } from '../ui' -const { moduleinfo } = client.import({ rpc: ['moduleinfo'] }) const docs = client.import('docs') +const { + gotosymbol: gotoSymbol, + moduleinfo: moduleInfo +} = client.import({ rpc: [ 'gotosymbol', 'moduleinfo' ] }) -export default function handleURI (parsedURI) { - const { query } = parsedURI +class URIHandler { + activate(ink) { + this.ink = ink + } + + handleURI (parsedURI) { + const { query } = parsedURI - if (query.open) { // open a file - atom.workspace.open(query.file, { - initialLine: Number(query.line), - pending: atom.config.get('core.allowPendingPaneItems') - }) - } else if (query.docs) { // show docs - const { word, mod } = query - docs({ word, mod }).then(result => { - if (result.error) return - const view = views.render(result) - docpane.processLinks(view.getElementsByTagName('a')) - docpane.ensureVisible() - docpane.showDocument(view, []) - }) - } else if (query.moduleinfo){ // show module info - const { mod } = query - moduleinfo({ mod }).then(({ doc, items }) => { - items.map(item => { - docpane.processItem(item) + if (query.open) { // open a file + atom.workspace.open(query.file, { + initialLine: Number(query.line), + pending: atom.config.get('core.allowPendingPaneItems') + }) + } else if (query.docs) { // show docs + const { word, mod } = query + docs({ word, mod }).then(result => { + if (result.error) return + const view = views.render(result) + docpane.processLinks(view.getElementsByTagName('a')) + docpane.ensureVisible() + docpane.showDocument(view, []) }) - const view = views.render(doc) - docpane.ensureVisible() - docpane.showDocument(view, items) - }) + } else if (query.goto) { + const { word, mod } = query + gotoSymbol({ + word, + mod + }).then(symbols => { + if (symbols.error) return + this.ink.goto.goto(symbols, { + pending: atom.config.get('core.allowPendingPaneItems') + }) + }) + } else if (query.moduleinfo){ // show module info + const { mod } = query + moduleInfo({ mod }).then(({ doc, items }) => { + items.map(item => { + docpane.processItem(item) + }) + const view = views.render(doc) + docpane.ensureVisible() + docpane.showDocument(view, items) + }) + } } } + +export default new URIHandler() From 7bdf574cdc9b047bdf0d34240e39b3a14b444562 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Wed, 23 Oct 2019 08:28:20 +0900 Subject: [PATCH 7/9] make every notifications dismissable --- lib/runtime/refactor.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index 123c621e..562c29a5 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -80,12 +80,14 @@ class Refactor { } if (result.warning) { atom.notifications.addWarning('Julia Client: Rename Refactor', { - description: result.warning + description: result.warning, + dismissable: true }) } if (result.error) { atom.notifications.addError('Julia Client: Rename Refactor', { - description: result.error + description: result.error, + dismissable: true }) } }) From 1375229ecd8e2eb7d80404cee40f50c351423189 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Thu, 24 Oct 2019 10:59:54 +0900 Subject: [PATCH 8/9] don't path an editor path --- lib/runtime/goto.js | 2 +- lib/runtime/refactor.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/runtime/goto.js b/lib/runtime/goto.js index 7c8a01f8..b8bfb317 100644 --- a/lib/runtime/goto.js +++ b/lib/runtime/goto.js @@ -101,7 +101,7 @@ class Goto { // module context const currentModule = modules.current() const mod = currentModule ? currentModule : 'Main' - const text = editor.getText() // buffer text that will be used for fallback entry + const text = editor.getText() // will be used as a fallback entry, e.g.: when in Main module gotoSymbol({ word, diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index 562c29a5..800ed488 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -1,4 +1,4 @@ -'use babel' +/** @babel */ import { client } from '../connection' import modules from './modules' @@ -53,7 +53,6 @@ class Refactor { old, full, new: _new, - path: editor.getPath(), // local context column: column + 1, row: row + 1, From 7af7f032ca8060aefedd619b2f9e5850dc5f0847 Mon Sep 17 00:00:00 2001 From: aviatesk Date: Sat, 9 Nov 2019 18:25:19 +0900 Subject: [PATCH 9/9] update to #651 --- lib/runtime/refactor.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/runtime/refactor.js b/lib/runtime/refactor.js index 800ed488..03998139 100644 --- a/lib/runtime/refactor.js +++ b/lib/runtime/refactor.js @@ -19,24 +19,26 @@ class Refactor { if (!client.isActive()) return - const range = getWordRangeAtBufferPosition(editor, bufferPosition, wordRegexWithoutDotAccessor) + const range = getWordRangeAtBufferPosition(editor, bufferPosition, { + wordRegex: wordRegexWithoutDotAccessor + }) if (range.isEmpty()) return - const old = editor.getTextInBufferRange(range) - if (!isValidWordToInspect(old)) return + const oldWord = editor.getTextInBufferRange(range) + if (!isValidWordToInspect(oldWord)) return const rangeFull = getWordRangeAtBufferPosition(editor, bufferPosition) - const full = editor.getTextInBufferRange(rangeFull) + const fullWord = editor.getTextInBufferRange(rangeFull) this.ink.showBasicModal([{ name: 'Rename', - defaultText: old, - message: `Enter an new name to which \`${old}\` will be renamed.` + defaultText: oldWord, + message: `Enter an new name to which \`${oldWord}\` will be renamed.` }]).then(items => { // check the new name is a valid identifier - const _new = items['Rename'] - if (!isValidWordToInspect(_new) || _new.match(wordRegexWithoutDotAccessor) != _new) { + const newWord = items['Rename'] + if (!isValidWordToInspect(newWord) || newWord.match(wordRegexWithoutDotAccessor) != newWord) { atom.notifications.addWarning('Julia Client: Rename Refactor', { - description: `\`${_new}\` isn't a valid identifier` + description: `\`${newWord}\` isn't a valid identifier` }) return } @@ -50,9 +52,9 @@ class Refactor { const mod = currentModule ? currentModule : 'Main' renamerefactor({ - old, - full, - new: _new, + oldWord, + fullWord, + newWord, // local context column: column + 1, row: row + 1,