]> git.r.bdr.sh - rbdr/dotfiles/blob - atom/packages/vim-mode-visual-block/lib/main.coffee
61cfe761b0ab66792541855a60fd284990903873
[rbdr/dotfiles] / atom / packages / vim-mode-visual-block / lib / main.coffee
1 _ = require 'underscore-plus'
2 {CompositeDisposable} = require 'atom'
3
4 Config =
5 debug:
6 type: 'boolean'
7 default: false
8
9 module.exports =
10 disposables: null
11 active: false
12 prefix: 'vim-mode-visual-block'
13
14 activate: (state) ->
15 @disposables = new CompositeDisposable
16 blockwiseCommands = {}
17 # [TODO] remove 'h', 'l' after some period.
18 commands = 'jkhloDCIA'.split('')
19 commands.push 'escape', 'ctrl-v'
20 for command in commands
21 do (command) =>
22 name = "#{@prefix}:#{command}"
23 blockwiseCommands[name] = (event) => @blockOperation(event, command)
24
25 blockwiseCommands["#{@prefix}:toggle-debug"] = => @toggleDebug()
26 @disposables.add atom.commands.add('atom-text-editor', blockwiseCommands)
27 @reset()
28
29 deactivate: ->
30 @disposables.dispose()
31
32 consumeVimMode: (@vimModeService) ->
33
34 reset: ->
35 @startRow = null
36
37 getEditor: ->
38 atom.workspace.getActiveTextEditor()
39
40 isVisualBlockMode: (vimState) ->
41 (vimState.mode is 'visual') and (vimState.submode is 'blockwise')
42
43 getVimEditorState: (editor) ->
44 @vimModeService.getEditorState editor
45
46 adjustSelections: (editor, options) ->
47 for selection in editor.getSelections()
48 range = selection.getBufferRange()
49 selection.setBufferRange range, options
50
51 blockOperation: (event, command) ->
52 editor = @getEditor()
53 vimState = @getVimEditorState editor
54
55 unless @isVisualBlockMode vimState
56 event.abortKeyBinding()
57 @reset()
58 return
59
60 # May be non-continuous execution.
61 if editor.getCursors().length is 1
62 @reset()
63
64 currentRow = editor.getLastCursor()?.getBufferRow()
65 @startRow ?= currentRow
66 # @debug "@startRow = #{@startRow}"
67
68 switch command
69 when 'o'
70 @startRow = currentRow
71 when 'D', 'C'
72 vimState.activateCommandMode()
73 event.abortKeyBinding()
74 when 'escape', 'ctrl-v'
75 vimState.activateCommandMode()
76 editor.clearSelections()
77 when 'j', 'k'
78 cursorPositions = editor.getCursorsOrderedByBufferPosition()
79 cursorTop = _.first cursorPositions
80 cursorBottom = _.last cursorPositions
81
82 if (command is 'j' and cursorTop.getBufferRow() >= @startRow) or
83 (command is 'k' and cursorBottom.getBufferRow() <= @startRow)
84 lastSelection = editor.getLastSelection()
85
86 if command is 'j'
87 editor.addSelectionBelow()
88 else
89 editor.addSelectionAbove()
90
91 # [FIXME]
92 # When addSelectionAbove(), addSelectionBelow() doesn't respect
93 # reversed stated, need improved.
94 #
95 # and one more..
96 #
97 # When selection is NOT empty and add selection by addSelectionAbove()
98 # and then move right, selection range got wrong, maybe this is bug..
99 @adjustSelections editor, reversed: lastSelection.isReversed()
100 else
101 # [FIXME]
102 # Guard to not destroying last cursor
103 # This guard is no longer needed
104 # Remove unnecessary code after re-think.
105 if (editor.getCursors().length < 2)
106 @reset()
107 return
108
109 if command is 'j'
110 cursorTop.destroy()
111 else
112 cursorBottom.destroy()
113 when 'I', 'A'
114 cursorsAdjusted = []
115
116 adjustCursor = (selection) ->
117 {start, end} = selection.getBufferRange()
118 pointEndOfLine = editor.bufferRangeForBufferRow(start.row).end
119 pointTarget = {'I': start, 'A': end}[command]
120 {cursor} = selection
121
122 if pointTarget.isGreaterThanOrEqual(pointEndOfLine)
123 pointTarget = pointEndOfLine
124 cursorsAdjusted.push cursor
125 cursor.setBufferPosition(pointTarget)
126
127 adjustCursor(selection) for selection in editor.getSelections()
128 vimState.activateCommandMode()
129 vimState.activateInsertMode()
130
131 if command is 'A' and cursorsAdjusted.length
132 cursor.moveRight() for cursor in cursorsAdjusted
133
134 else
135 event.abortKeyBinding()
136 content = """
137 *#{@prefix}*
138 * From version 0.2.5, `#{@prefix}` provide default keymap.
139 * And `h`, `l` command become obsolete.
140 * Remove all explicit keymap from `keymap.cson`.
141 """
142 atom.notifications.addWarning content, dismissable: true
143
144 unless @isVisualBlockMode vimState
145 @reset()
146
147 toggleDebug: ->
148 oldState = atom.config.get("#{@prefix}.debug")
149 atom.config.set("#{@prefix}.debug", not oldState)
150 state = atom.config.get("#{@prefix}.debug") and "enabled" or "disabled"
151 console.log "#{@prefix}: debug #{state}"
152
153 debug: (msg) ->
154 return unless atom.config.get("#{@prefix}.debug")
155 console.log msg
156
157 # dump: ->
158 # @debug "@startRow = #{@startRow}"