From 1bf55744d20c8af718b940ecbfad7432473f8635 Mon Sep 17 00:00:00 2001 From: Varanas Date: Fri, 29 Jan 2016 15:36:23 +0100 Subject: [PATCH 01/11] Implement a modal goto panel --- lib/gotodef.coffee | 88 ++++++++++++++++++++++++++++++++++++++++++++++ lib/ink.coffee | 2 ++ package.json | 3 +- 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 lib/gotodef.coffee diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee new file mode 100644 index 00000000..390b562b --- /dev/null +++ b/lib/gotodef.coffee @@ -0,0 +1,88 @@ +{$$, SelectListView} = require 'atom-space-pen-views' +fuzzaldrinPlus = require 'fuzzaldrin-plus' + +# ## GoToDef-Panel +# +# `goto` takes a promise as its argument, which can either be fulfilled or rejected. +# Both modes will be handled by `goto` as follows: +# On fulfillment, a `goToView` will be shown and populated by the array `items` +# returned by the promise. +# `items` conatins objects with the fields: +# .text: Displayed text, searchable. +# .file: File in which this method is defined, not displayed. +# .line: Line of definition. +# .dispfile: Humanized file path, displayed. +# +# On rejection, the `goToView` will only shown the error message provided. + +module.exports = +goto: (promise) -> + @view ?= new MethodView() + @view.setLoading "Loading..." + @view.show() + promise.then (items) -> @view.setItems(items), + (error) -> @view.setError(error) + +class goToView extends SelectListView + initialize: -> + super + @panel = atom.workspace.addModalPanel(item: this, visible: false) + @addClass('command-palette') + @addClass('method-panel') + + destroy: -> + @cancel() + @panel.destroy() + + # Create the view for one item. + viewForItem: ({text, dispfile, line}) -> + # the highlighting is taken verbatim from https://github.com/atom/command-palette + filterQuery = @getFilterQuery() + matches = fuzzaldrinPlus.match(text, filterQuery) + + $$ -> + highlighter = (command, matches, offsetIndex) => + lastIndex = 0 + matchedChars = [] # Build up a set of matched chars to be more semantic + + for matchIndex in matches + matchIndex -= offsetIndex + continue if matchIndex < 0 # If marking up the basename, omit command matches + unmatched = command.substring(lastIndex, matchIndex) + if unmatched + @span matchedChars.join(''), class: 'character-match' if matchedChars.length + matchedChars = [] + @text unmatched + matchedChars.push(command[matchIndex]) + lastIndex = matchIndex + 1 + + @span matchedChars.join(''), class: 'character-match' if matchedChars.length + + # Remaining characters are plain text + @text command.substring(lastIndex) + + @li class: 'two-lines', => + @div class: 'primary-line', -> highlighter(text, matches, 0) + @div dispfile + ":" + line, class: 'secondary-line' + + # Only `item.text` is searchable. + getFilterKey: -> 'text' + + # Show the goto-panel and store the previously focused element. + show: () -> + @storeFocusedElement() + @panel.show() + @focusFilterEditor() + + hide: () -> + @panel?.hide() + + # Jump to `item.file` at line `item.line`, when an item was selected. + confirmed: (item) -> + atom.workspace.open item.file, + initialLine: item.line + @hide() + + # Return to previously focused element when the modal panel is cancelled. + cancelled: -> + @hide() diff --git a/lib/ink.coffee b/lib/ink.coffee index 4cd7501b..0d6554cb 100644 --- a/lib/ink.coffee +++ b/lib/ink.coffee @@ -8,6 +8,7 @@ Console = require './console/console' PlotPane = require './plots/pane' Workspace = require './workspace/workspace' tree = require './tree' +goto = require './gotodef' module.exports = Ink = activate: -> @@ -38,3 +39,4 @@ module.exports = Ink = PlotPane: PlotPane highlights: highlights tree: tree + goto: goto diff --git a/package.json b/package.json index d2aafa78..7b624ec5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "atom": ">=1.0.0 <2.0.0" }, "dependencies": { - "atom-space-pen-views": "^2.0.0" + "atom-space-pen-views": "^2.0.0", + "fuzzaldrin-plus": "^0.1.0" }, "providedServices": { "ink": { From 4d2a1b88e4365807b3beb7bdb7926dec7b3ac46d Mon Sep 17 00:00:00 2001 From: Varanas Date: Fri, 29 Jan 2016 15:54:53 +0100 Subject: [PATCH 02/11] cs syntax is a bit confusing sometimes :) --- lib/gotodef.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index 390b562b..e67e2f87 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -20,8 +20,8 @@ goto: (promise) -> @view ?= new MethodView() @view.setLoading "Loading..." @view.show() - promise.then (items) -> @view.setItems(items), - (error) -> @view.setError(error) + promise.then ((items) -> @view.setItems items), + (error) -> @view.setError error class goToView extends SelectListView initialize: -> From 19595a0e9995824704f77bfc68e8777e08b93ce1 Mon Sep 17 00:00:00 2001 From: Varanas Date: Sun, 31 Jan 2016 11:30:53 +0100 Subject: [PATCH 03/11] styling --- lib/gotodef.coffee | 2 +- styles/ink.less | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index e67e2f87..13db73fa 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -28,7 +28,7 @@ class goToView extends SelectListView super @panel = atom.workspace.addModalPanel(item: this, visible: false) @addClass('command-palette') - @addClass('method-panel') + @addClass('gotodef-panel') destroy: -> @cancel() diff --git a/styles/ink.less b/styles/ink.less index 031a4415..748a0a5c 100644 --- a/styles/ink.less +++ b/styles/ink.less @@ -116,3 +116,18 @@ atom-text-editor::shadow { ink-console .ink.tree > .icon { position: absolute; } + +.gotodef-panel { + .two-lines { + padding: 0.2em 0.75em 0.2em 1em !important; + .primary-line, .secondary-line { + line-height: 1.8em; + } + } + .error-message { + color: @text-color-error; + } + .character-match { + font-weight: bold; + } +} From c346258c5c6efb3b791753e8b42a62692acf8845 Mon Sep 17 00:00:00 2001 From: Varanas Date: Mon, 1 Feb 2016 19:59:43 +0100 Subject: [PATCH 04/11] bit of refactoring --- lib/gotodef.coffee | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index 13db73fa..ab01f0ec 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -1,5 +1,6 @@ {$$, SelectListView} = require 'atom-space-pen-views' fuzzaldrinPlus = require 'fuzzaldrin-plus' +loading = require 'util/loading' # ## GoToDef-Panel # @@ -13,17 +14,24 @@ fuzzaldrinPlus = require 'fuzzaldrin-plus' # .line: Line of definition. # .dispfile: Humanized file path, displayed. # -# On rejection, the `goToView` will only shown the error message provided. +# On rejection, the `GotoView` will only shown the error message provided. module.exports = goto: (promise) -> - @view ?= new MethodView() - @view.setLoading "Loading..." - @view.show() - promise.then ((items) -> @view.setItems items), - (error) -> @view.setError error + @view ?= new GotoView() -class goToView extends SelectListView + promise + .then (items) -> + if items.length == 1 + GotoView.openItem items[0] + else if items.length > 1 + @view.setItems items + @view.show() + + .catch (error) -> + @view.setError error + +class GotoView extends SelectListView initialize: -> super @panel = atom.workspace.addModalPanel(item: this, visible: false) @@ -79,10 +87,13 @@ class goToView extends SelectListView # Jump to `item.file` at line `item.line`, when an item was selected. confirmed: (item) -> - atom.workspace.open item.file, - initialLine: item.line + @openItem item @hide() # Return to previously focused element when the modal panel is cancelled. cancelled: -> @hide() + + @openItem: (item) -> + atom.workspace.open item.file, + initialLine: item.line From bf72480225aebe8708afa8d6d417358b5b672c4a Mon Sep 17 00:00:00 2001 From: Varanas Date: Mon, 1 Feb 2016 20:02:13 +0100 Subject: [PATCH 05/11] keeps docs up to date --- lib/gotodef.coffee | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index ab01f0ec..e1570dd2 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -1,20 +1,20 @@ {$$, SelectListView} = require 'atom-space-pen-views' fuzzaldrinPlus = require 'fuzzaldrin-plus' -loading = require 'util/loading' # ## GoToDef-Panel # # `goto` takes a promise as its argument, which can either be fulfilled or rejected. # Both modes will be handled by `goto` as follows: -# On fulfillment, a `goToView` will be shown and populated by the array `items` -# returned by the promise. +# On fulfillment, a `GotoView` will be shown and populated by the array `items` +# returned by the promise if there's more than one item in it. Otherwise, Atom +# jumps straight to the definition. # `items` conatins objects with the fields: # .text: Displayed text, searchable. # .file: File in which this method is defined, not displayed. # .line: Line of definition. # .dispfile: Humanized file path, displayed. # -# On rejection, the `GotoView` will only shown the error message provided. +# On rejection, the `GotoView` will only show the error message provided. module.exports = goto: (promise) -> @@ -30,6 +30,7 @@ goto: (promise) -> .catch (error) -> @view.setError error + @view.show() class GotoView extends SelectListView initialize: -> From e816daf392fafa58166aa5247f89cd5cc2e730a9 Mon Sep 17 00:00:00 2001 From: Varanas Date: Mon, 29 Feb 2016 21:55:11 +0100 Subject: [PATCH 06/11] update error mode yes, that's much less elegant than before --- lib/gotodef.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index e1570dd2..8e33c18e 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -14,24 +14,24 @@ fuzzaldrinPlus = require 'fuzzaldrin-plus' # .line: Line of definition. # .dispfile: Humanized file path, displayed. # -# On rejection, the `GotoView` will only show the error message provided. +# If the Promise errors, it should contain an object with the field error, which +# will subsequently be displayed in a modal panel. module.exports = goto: (promise) -> @view ?= new GotoView() promise - .then (items) -> + .then (items) => + if items.error? + @view.setError items.error + @view.show() if items.length == 1 GotoView.openItem items[0] else if items.length > 1 @view.setItems items @view.show() - .catch (error) -> - @view.setError error - @view.show() - class GotoView extends SelectListView initialize: -> super From 7c65e686df72c29958d9e2b674c4598a041e1eff Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Thu, 24 Mar 2016 11:21:42 +0100 Subject: [PATCH 07/11] update this again --- lib/gotodef.coffee | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index 8e33c18e..0c84eba5 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -5,31 +5,33 @@ fuzzaldrinPlus = require 'fuzzaldrin-plus' # # `goto` takes a promise as its argument, which can either be fulfilled or rejected. # Both modes will be handled by `goto` as follows: -# On fulfillment, a `GotoView` will be shown and populated by the array `items` -# returned by the promise if there's more than one item in it. Otherwise, Atom -# jumps straight to the definition. -# `items` conatins objects with the fields: -# .text: Displayed text, searchable. -# .file: File in which this method is defined, not displayed. -# .line: Line of definition. -# .dispfile: Humanized file path, displayed. +# On fulfillment, a `result` object is returned which contains two fields: # -# If the Promise errors, it should contain an object with the field error, which -# will subsequently be displayed in a modal panel. +# - `result.error`: Boolean. If true, the contents of `result.items` will be +# shown as an error. +# +# - `result.items` - Array that contains objects with the fields +# - `.text` - Displayed text, searchable. +# - `.file` - File in which this method is defined, not displayed. +# - `.line` - Line of definition. +# - `.dispfile` - Humanized file path, displayed. +# +# or a plain text string if `result.error` is true. + module.exports = goto: (promise) -> @view ?= new GotoView() promise - .then (items) => - if items.error? - @view.setError items.error + .then (result) => + if result.error + @view.setError result.items @view.show() - if items.length == 1 - GotoView.openItem items[0] - else if items.length > 1 - @view.setItems items + else if result.items.length == 1 + GotoView.openItem result.items[0] + else if result.items.length > 1 + @view.setItems result.items @view.show() class GotoView extends SelectListView @@ -88,7 +90,7 @@ class GotoView extends SelectListView # Jump to `item.file` at line `item.line`, when an item was selected. confirmed: (item) -> - @openItem item + GotoView.openItem item @hide() # Return to previously focused element when the modal panel is cancelled. From 87aa503ecf704eeec5c6a5811d14e4d1e7f44098 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Thu, 24 Mar 2016 13:44:23 +0100 Subject: [PATCH 08/11] whitespace --- lib/gotodef.coffee | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index 0c84eba5..3d416ae4 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -23,16 +23,15 @@ module.exports = goto: (promise) -> @view ?= new GotoView() - promise - .then (result) => - if result.error - @view.setError result.items - @view.show() - else if result.items.length == 1 - GotoView.openItem result.items[0] - else if result.items.length > 1 - @view.setItems result.items - @view.show() + promise.then (result) => + if result.error + @view.setError result.items + @view.show() + else if result.items.length == 1 + GotoView.openItem result.items[0] + else if result.items.length > 1 + @view.setItems result.items + @view.show() class GotoView extends SelectListView initialize: -> From 9209ee61ba86c32b52bdc88f93705c9f6422dcd5 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Thu, 21 Apr 2016 13:25:35 +0200 Subject: [PATCH 09/11] whitespace --- lib/ink.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ink.coffee b/lib/ink.coffee index 0d6554cb..bb5751eb 100644 --- a/lib/ink.coffee +++ b/lib/ink.coffee @@ -8,7 +8,7 @@ Console = require './console/console' PlotPane = require './plots/pane' Workspace = require './workspace/workspace' tree = require './tree' -goto = require './gotodef' +goto = require './gotodef' module.exports = Ink = activate: -> From a614bb564b1d1ef023cb82d4a1ffa71021102ed9 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Sun, 24 Apr 2016 11:45:44 +0200 Subject: [PATCH 10/11] allow both promises and symbolTables as input also light refactoring --- lib/gotodef.coffee | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index 3d416ae4..e9054038 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -3,34 +3,38 @@ fuzzaldrinPlus = require 'fuzzaldrin-plus' # ## GoToDef-Panel # -# `goto` takes a promise as its argument, which can either be fulfilled or rejected. -# Both modes will be handled by `goto` as follows: -# On fulfillment, a `result` object is returned which contains two fields: +# `goto` either takes a `symbolTable` as its argument, or a Promise which returns a +# `symbolTable`. # -# - `result.error`: Boolean. If true, the contents of `result.items` will be -# shown as an error. +# A `symbolTable` is specified by having the following fields: # -# - `result.items` - Array that contains objects with the fields +# - `symbolTable.error`: Boolean. If true, the contents of `result.items` will +# be shown as an error. +# +# - `symbolTable.items` - Array that contains objects with the fields # - `.text` - Displayed text, searchable. # - `.file` - File in which this method is defined, not displayed. # - `.line` - Line of definition. # - `.dispfile` - Humanized file path, displayed. # -# or a plain text string if `result.error` is true. +# or a plain text string if `symbolTable.error` is true. module.exports = -goto: (promise) -> +goto: (symbolTable) -> @view ?= new GotoView() - promise.then (result) => - if result.error - @view.setError result.items + # this allows either a promise or a result as the input + promise = Promise.resolve symbolTable + + promise.then (symbolTable) => + if symbolTable.error + @view.setError symbolTable.items @view.show() - else if result.items.length == 1 - GotoView.openItem result.items[0] - else if result.items.length > 1 - @view.setItems result.items + else if symbolTable.items.length == 1 + GotoView.openItem symbolTable.items[0] + else if symbolTable.items.length > 1 + @view.setItems symbolTable.items @view.show() class GotoView extends SelectListView From a3ee8762401bf75e9be49d0d8f92afc0fd792e81 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Sun, 24 Apr 2016 11:47:30 +0200 Subject: [PATCH 11/11] rename stuff --- lib/gotodef.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gotodef.coffee b/lib/gotodef.coffee index e9054038..e17c9c94 100644 --- a/lib/gotodef.coffee +++ b/lib/gotodef.coffee @@ -21,11 +21,11 @@ fuzzaldrinPlus = require 'fuzzaldrin-plus' module.exports = -goto: (symbolTable) -> +goto: (symbolTableOrPromise) -> @view ?= new GotoView() - # this allows either a promise or a result as the input - promise = Promise.resolve symbolTable + # this allows either a promise or a symbolTable as the input + promise = Promise.resolve symbolTableOrPromise promise.then (symbolTable) => if symbolTable.error