From 3559a5b2c106f95ca46b10176d6af5fab74153b7 Mon Sep 17 00:00:00 2001 From: Chris Wendt Date: Mon, 5 Sep 2016 12:36:49 -0600 Subject: [PATCH] Add support for filling holes using ghc-mod's auto command --- README.md | 1 + lib/ghc-mod/ghc-modi-process.coffee | 21 +++++++++++++++++++ lib/upi-consumer.coffee | 20 ++++++++++++++++++ lib/views/suggestion-list-view.coffee | 30 +++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 lib/views/suggestion-list-view.coffee diff --git a/README.md b/README.md index eb31154..c78346a 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ You can edit Atom keybindings by opening 'Edit → Open Your Keymap'. Here is a 'ctrl-alt-i': 'haskell-ghc-mod:show-info' #this is an example binding 'ctrl-alt-T': 'haskell-ghc-mod:insert-type' #this is an example binding '': 'haskell-ghc-mod:case-split' + '': 'haskell-ghc-mod:hole-fill' '': 'haskell-ghc-mod:sig-fill' '': 'haskell-ghc-mod:show-info-fallback-to-type' '': 'haskell-ghc-mod:show-type-fallback-to-info' diff --git a/lib/ghc-mod/ghc-modi-process.coffee b/lib/ghc-mod/ghc-modi-process.coffee index 6b34707..d2c105e 100644 --- a/lib/ghc-mod/ghc-modi-process.coffee +++ b/lib/ghc-mod/ghc-modi-process.coffee @@ -340,6 +340,27 @@ class GhcModiProcess ] replacement: text + doHoleFill: (buffer, crange) => + return Promise.resolve [] unless buffer.getUri()? + crange = Util.tabShiftForRange(buffer, crange) + @queueCmd 'typeinfo', + interactive: @caps?.interactiveCaseSplit ? false + buffer: buffer + command: 'auto', + uri: buffer.getUri() + text: buffer.getText() if buffer.isModified() + args: [crange.start.row + 1, crange.start.column + 1] + .then (lines) -> + return null if lines.length == 0 or lines[1] == "" + + [line_, rowstart, colstart, rowend, colend, text] = lines[0].match(/^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/) + + range: Range.fromObject [ + [parseInt(rowstart) - 1, parseInt(colstart) - 1], + [parseInt(rowend) - 1, parseInt(colend) - 1] + ] + suggestions: lines[1..] + doSigFill: (buffer, crange) => return Promise.resolve [] unless buffer.getUri()? crange = Util.tabShiftForRange(buffer, crange) diff --git a/lib/upi-consumer.coffee b/lib/upi-consumer.coffee index 2c0f570..8eb7a42 100644 --- a/lib/upi-consumer.coffee +++ b/lib/upi-consumer.coffee @@ -1,5 +1,6 @@ {CompositeDisposable} = require 'atom' ImportListView = require './views/import-list-view' +SuggestionListView = require './views/suggestion-list-view' module.exports = class UPIConsumer @@ -24,6 +25,7 @@ class UPIConsumer 'haskell-ghc-mod:show-type': @tooltipCommand @typeTooltip 'haskell-ghc-mod:show-info': @tooltipCommand @infoTooltip 'haskell-ghc-mod:case-split': @caseSplitCommand + 'haskell-ghc-mod:hole-fill': @holeFillCommand 'haskell-ghc-mod:sig-fill': @sigFillCommand 'haskell-ghc-mod:go-to-declaration': @goToDeclCommand 'haskell-ghc-mod:show-info-fallback-to-type': @tooltipCommand @infoTypeTooltip @@ -40,6 +42,7 @@ class UPIConsumer {label: 'Show Info', command: 'haskell-ghc-mod:show-info'} {label: 'Show Type And Info', command: 'haskell-ghc-mod:show-type-and-info'} {label: 'Case Split', command: 'haskell-ghc-mod:case-split'} + {label: 'Hole Fill', command: 'haskell-ghc-mod:hole-fill'} {label: 'Sig Fill', command: 'haskell-ghc-mod:sig-fill'} {label: 'Insert Type', command: 'haskell-ghc-mod:insert-type'} {label: 'Insert Import', command: 'haskell-ghc-mod:insert-import'} @@ -146,6 +149,23 @@ class UPIConsumer res.forEach ({range, replacement}) -> editor.setTextInBufferRange(range, replacement) + holeFillCommand: ({target, detail}) => + editor = target.getModel() + @upi.withEventRange {editor, detail}, ({crange}) => + @process.doHoleFill(editor.getBuffer(), crange) + .then (res) -> + return null unless res? + + {range, suggestions} = res + + if suggestions.length == 1 + editor.setTextInBufferRange(range, suggestions[0]) + else + new SuggestionListView + items: suggestions + onConfirmed: (suggestion) -> + editor.setTextInBufferRange(range, suggestion) + sigFillCommand: ({target, detail}) => editor = target.getModel() @upi.withEventRange {editor, detail}, ({crange}) => diff --git a/lib/views/suggestion-list-view.coffee b/lib/views/suggestion-list-view.coffee new file mode 100644 index 0000000..2d1ff93 --- /dev/null +++ b/lib/views/suggestion-list-view.coffee @@ -0,0 +1,30 @@ +{SelectListView} = require 'atom-space-pen-views' + +module.exports= +class SuggestionListView extends SelectListView + initialize: ({@onConfirmed, items}) -> + super + @panel = atom.workspace.addModalPanel + item: this + visible: false + @addClass 'ide-haskell' + @show items + + cancelled: -> + @panel.destroy() + + getFilterKey: -> + "text" + + show: (list) -> + @setItems list + @panel.show() + @storeFocusedElement() + @focusFilterEditor() + + viewForItem: (mod) -> + "
  • #{mod}
  • " + + confirmed: (mod) -> + @onConfirmed? mod + @cancel()