Move EditorCommand helpers elsewhere

RootView and Editor now have helpers that support
binding events to callbacks, binding a callback to
all current and future editors, and replacing the
selected text via a transforming callback.
This commit is contained in:
Kevin Sawicki
2012-10-10 18:41:12 -07:00
parent 1fa32c48e7
commit d4aeb1bb95
10 changed files with 162 additions and 176 deletions

View File

@@ -1828,3 +1828,55 @@ describe "Editor", ->
editor.pageUp()
expect(editor.getCursor().getScreenPosition().row).toBe(0)
expect(editor.getFirstVisibleScreenRow()).toBe(0)
describe ".replaceSelectedText()", ->
it "doesn't call the replace function when the selection is empty", ->
replaced = false
edited = false
replacer = (text) ->
replaced = true
'new'
editor.moveCursorToTop()
edited = editor.replaceSelectedText(replacer)
expect(replaced).toBe false
expect(edited).toBe false
it "returns true when transformed text is non-empty", ->
replaced = false
edited = false
replacer = (text) ->
replaced = true
'new'
editor.moveCursorToTop()
editor.selectToEndOfLine()
edited = editor.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe true
it "returns false when transformed text is null", ->
replaced = false
edited = false
replacer = (text) ->
replaced = true
null
editor.moveCursorToTop()
editor.selectToEndOfLine()
edited = editor.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe false
it "returns false when transformed text is undefined", ->
replaced = false
edited = false
replacer = (text) ->
replaced = true
undefined
editor.moveCursorToTop()
editor.selectToEndOfLine()
edited = editor.replaceSelectedText(replacer)
expect(replaced).toBe true
expect(edited).toBe false

View File

@@ -690,3 +690,31 @@ describe "RootView", ->
expect(fs.read(buffer1.getPath())).toBe("edited1")
expect(buffer2.isModified()).toBe(false)
expect(fs.read(buffer2.getPath())).toBe("edited2")
fdescribe ".eachEditor(callback)", ->
beforeEach ->
rootView.attachToDom()
it "invokes the callback for existing editor", ->
count = 0
callbackEditor = null
callback = (editor) ->
callbackEditor = editor
count++
rootView.eachEditor(callback)
expect(count).toBe 1
expect(callbackEditor).toBe rootView.getActiveEditor()
it "invokes the callback for new editor", ->
count = 0
callbackEditor = null
callback = (editor) ->
callbackEditor = editor
count++
rootView.eachEditor(callback)
count = 0
callbackEditor = null
rootView.getActiveEditor().splitRight()
expect(count).toBe 1
expect(callbackEditor).toBe rootView.getActiveEditor()

View File

@@ -1,140 +0,0 @@
EditorCommand = require 'editor-command'
LowerCaseCommand = require 'lowercase-command'
UpperCaseCommand = require 'uppercase-command'
RootView = require 'root-view'
fs = require 'fs'
describe "EditorCommand", ->
[rootView, editor, path] = []
beforeEach ->
rootView = new RootView
rootView.open(require.resolve 'fixtures/sample.js')
rootView.focus()
editor = rootView.getActiveEditor()
afterEach ->
rootView.remove()
describe "@replaceSelectedText()", ->
it "returns true when transformed text is non-empty", ->
transformed = false
edited = false
class CustomCommand extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'custom', =>
edited = @replaceSelectedText editor, (text) ->
transformed = true
'new'
CustomCommand.activate(rootView)
editor.moveCursorToTop()
editor.selectToEndOfLine()
editor.trigger 'custom'
expect(transformed).toBe true
expect(edited).toBe true
it "returns false when transformed text is null", ->
transformed = false
edited = false
class CustomCommand extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'custom', =>
edited = @replaceSelectedText editor, (text) ->
transformed = true
null
CustomCommand.activate(rootView)
editor.moveCursorToTop()
editor.selectToEndOfLine()
editor.trigger 'custom'
expect(transformed).toBe true
expect(edited).toBe false
it "returns false when transformed text is undefined", ->
transformed = false
edited = false
class CustomCommand extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'custom', =>
edited = @replaceSelectedText editor, (text) ->
transformed = true
undefined
CustomCommand.activate(rootView)
editor.moveCursorToTop()
editor.selectToEndOfLine()
editor.trigger 'custom'
expect(transformed).toBe true
expect(edited).toBe false
describe "custom sub-class", ->
it "removes vowels from selected text", ->
class VowelRemover extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'devowel', =>
@replaceSelectedText editor, (text) ->
text.replace(/[aeiouy]/gi, '')
VowelRemover.activate(rootView)
editor.moveCursorToTop()
editor.selectToEndOfLine()
editor.trigger 'devowel'
expect(editor.lineForBufferRow(0)).toBe 'vr qcksrt = fnctn () {'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'vr qcksrt = fnctn () {'
expect(editor.getCursorBufferPosition()).toBe(editor.getSelection().getBufferRange().end)
it "maintains reversed selections", ->
class VowelRemover extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'devowel', =>
@replaceSelectedText editor, (text) ->
text.replace(/[aeiouy]/gi, '')
VowelRemover.activate(rootView)
editor.moveCursorToTop()
editor.moveCursorToEndOfLine()
editor.selectToBeginningOfLine()
editor.trigger 'devowel'
expect(editor.lineForBufferRow(0)).toBe 'vr qcksrt = fnctn () {'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'vr qcksrt = fnctn () {'
expect(editor.getCursorBufferPosition()).toBe(editor.getSelection().getBufferRange().start)
it "doesn't transform empty selections", ->
callbackCount = 0
class CustomCommand extends EditorCommand
@onEditor: (editor) ->
@register editor, 'meta-V', 'custom', =>
@replaceSelectedText editor, (text) ->
callbackCount++
text
CustomCommand.activate(rootView)
editor.moveCursorToTop()
editor.selectToEndOfLine()
editor.trigger 'custom'
expect(callbackCount).toBe 1
editor.clearSelections()
editor.trigger 'custom'
expect(callbackCount).toBe 1
describe "LowerCaseCommand", ->
it "replaces the selected text with all lower case characters", ->
LowerCaseCommand.activate(rootView)
editor.setSelectedBufferRange([[11,14], [11,19]])
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'Array'
editor.trigger 'lowercase'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'array'
describe "UpperCaseCommand", ->
it "replaces the selected text with all upper case characters", ->
UpperCaseCommand.activate(rootView)
editor.setSelectedBufferRange([[0,0], [0,3]])
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'var'
editor.trigger 'uppercase'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'VAR'

View File

@@ -0,0 +1,23 @@
LowerCaseCommand = require 'lowercase-command'
RootView = require 'root-view'
fs = require 'fs'
describe "LowerCaseCommand", ->
[rootView, editor, path] = []
beforeEach ->
rootView = new RootView
rootView.open(require.resolve 'fixtures/sample.js')
rootView.focus()
editor = rootView.getActiveEditor()
afterEach ->
rootView.remove()
it "replaces the selected text with all lower case characters", ->
LowerCaseCommand.activate(rootView)
editor.setSelectedBufferRange([[11,14], [11,19]])
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'Array'
editor.trigger 'lowercase'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'array'

View File

@@ -0,0 +1,23 @@
UpperCaseCommand = require 'uppercase-command'
RootView = require 'root-view'
fs = require 'fs'
describe "UpperCaseCommand", ->
[rootView, editor, path] = []
beforeEach ->
rootView = new RootView
rootView.open(require.resolve 'fixtures/sample.js')
rootView.focus()
editor = rootView.getActiveEditor()
afterEach ->
rootView.remove()
it "replaces the selected text with all upper case characters", ->
UpperCaseCommand.activate(rootView)
editor.setSelectedBufferRange([[0,0], [0,3]])
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'var'
editor.trigger 'uppercase'
expect(editor.getTextInRange(editor.getSelection().getBufferRange())).toBe 'VAR'

View File

@@ -965,3 +965,20 @@ class Editor extends View
@find('pre.line.cursor-line').removeClass('cursor-line')
if @getSelection().isSingleScreenLine()
@find("pre.line:eq(#{screenRow})").addClass('cursor-line')
bindToKeyedEvent: (key, event, callback) ->
binding = {}
binding[key] = event
window.keymap.bindKeys '.editor', binding
@on event, =>
callback(this, event)
replaceSelectedText: (replaceFn) ->
selection = @getSelection()
return false if selection.isEmpty()
text = replaceFn(@getTextInRange(selection.getBufferRange()))
return false if text is null or text is undefined
@insertText(text, select: true)
true

View File

@@ -232,3 +232,10 @@ class RootView extends View
saveAll: ->
editor.save() for editor in @getEditors()
eachEditor: (callback) ->
for editor in @getEditors()
callback(editor)
@on 'editor-open', (e, editor) ->
callback(editor)

View File

@@ -1,26 +0,0 @@
module.exports =
class EditorCommand
@activate: (rootView) ->
for editor in rootView.getEditors()
@onEditor(editor)
rootView.on 'editor-open', (e, editor) =>
@onEditor(editor)
@register: (editor, key, event, callback) ->
binding = {}
binding[key] = event
window.keymap.bindKeys '.editor', binding
editor.on event, =>
callback(editor, event)
@replaceSelectedText: (editor, replace) ->
selection = editor.getSelection()
return false if selection.isEmpty()
text = replace(editor.getTextInRange(selection.getBufferRange()))
return false if text is null or text is undefined
editor.insertText(text, select: true)
true

View File

@@ -1,9 +1,10 @@
EditorCommand = require 'editor-command'
module.exports =
class LowerCaseCommand extends EditorCommand
class LowerCaseCommand
@activate: (rootView) ->
rootView.eachEditor(@onEditor)
@onEditor: (editor) ->
@register editor, 'meta-Y', 'lowercase', =>
@replaceSelectedText editor, (text) ->
editor.bindToKeyedEvent 'meta-Y', 'lowercase', =>
editor.replaceSelectedText (text) ->
text.toLowerCase()

View File

@@ -1,9 +1,10 @@
EditorCommand = require 'editor-command'
module.exports =
class UpperCaseCommand extends EditorCommand
class UpperCaseCommand
@activate: (rootView) ->
rootView.eachEditor(@onEditor)
@onEditor: (editor) ->
@register editor, 'meta-X', 'uppercase', =>
@replaceSelectedText editor, (text) ->
editor.bindToKeyedEvent 'meta-X', 'uppercase', =>
editor.replaceSelectedText (text) ->
text.toUpperCase()