Move handling of nonWordCharacters setting into TextEditorRegistry

This commit is contained in:
Max Brunsfeld
2016-07-12 11:30:41 -07:00
parent 5167dbca6f
commit 58ec44f8ec
5 changed files with 78 additions and 26 deletions

View File

@@ -394,5 +394,28 @@ describe('TextEditorRegistry', function () {
atom.config.set('editor.undoGroupingInterval', 300)
expect(editor.getUndoGroupingInterval()).toBe(300)
})
it('sets the non-word characters based on the config', function () {
atom.config.set('editor.nonWordCharacters', '(){}')
registry.maintainConfig(editor)
expect(editor.getNonWordCharacters()).toBe('(){}')
atom.config.set('editor.nonWordCharacters', '(){}[]')
expect(editor.getNonWordCharacters()).toBe('(){}[]')
})
it('gives the editor a scoped-settings delegate based on the config', function () {
atom.config.set('editor.nonWordCharacters', '()')
atom.config.set('editor.nonWordCharacters', '(){}', {scopeSelector: '.a.b .c.d'})
atom.config.set('editor.nonWordCharacters', '(){}[]', {scopeSelector: '.e.f *'})
registry.maintainConfig(editor)
let delegate = editor.getScopedSettingsDelegate()
expect(delegate.getNonWordCharacters(['a.b', 'c.d'])).toBe('(){}')
expect(delegate.getNonWordCharacters(['e.f', 'g.h'])).toBe('(){}[]')
expect(delegate.getNonWordCharacters(['i.j'])).toBe('()')
})
})
})

View File

@@ -1645,28 +1645,29 @@ describe "TextEditor", ->
editor.selectWordsContainingCursors()
expect(editor.getSelectedBufferRange()).toEqual [[12, 2], [12, 6]]
describe 'when editor.nonWordCharacters is set scoped to a grammar', ->
coffeeEditor = null
beforeEach ->
waitsForPromise ->
atom.packages.activatePackage('language-coffee-script')
waitsForPromise ->
atom.workspace.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o
it "selects words based on the non-word characters configured at the cursor's current scope", ->
editor.setText("one-one; 'two-two'; three-three");
it 'selects the correct surrounding word for the given scoped setting', ->
coffeeEditor.setCursorBufferPosition [0, 9] # in the middle of quicksort
coffeeEditor.selectWordsContainingCursors()
expect(coffeeEditor.getSelectedBufferRange()).toEqual [[0, 6], [0, 15]]
editor.setCursorBufferPosition([0, 1])
editor.addCursorAtBufferPosition([0, 12])
atom.config.set 'editor.nonWordCharacters', 'qusort', scopeSelector: '.source.coffee'
scopeDescriptors = editor.getCursors().map (c) -> c.getScopeDescriptor()
expect(scopeDescriptors[0].getScopesArray()).toEqual(['source.js'])
expect(scopeDescriptors[1].getScopesArray()).toEqual(['source.js', 'string.quoted.single.js'])
coffeeEditor.setCursorBufferPosition [0, 9]
coffeeEditor.selectWordsContainingCursors()
expect(coffeeEditor.getSelectedBufferRange()).toEqual [[0, 8], [0, 11]]
editor.setScopedSettingsDelegate({
getNonWordCharacters: (scopes) ->
result = '/\()"\':,.;<>~!@#$%^&*|+=[]{}`?'
if (scopes.some (scope) -> scope.startsWith('string'))
result
else
result + '-'
})
editor.setCursorBufferPosition [0, 7]
editor.selectWordsContainingCursors()
expect(editor.getSelectedBufferRange()).toEqual [[0, 4], [0, 13]]
editor.selectWordsContainingCursors()
expect(editor.getSelections()[0].getText()).toBe('one')
expect(editor.getSelections()[1].getText()).toBe('two-two')
describe ".selectToFirstCharacterOfLine()", ->
it "moves to the first character of the current line or the beginning of the line if it's already on the first character", ->

View File

@@ -18,7 +18,7 @@ class Cursor extends Model
visible: true
# Instantiated by a {TextEditor}
constructor: ({@editor, @marker, @config, id}) ->
constructor: ({@editor, @marker, id}) ->
@emitter = new Emitter
@assignId(id)
@@ -160,8 +160,8 @@ class Cursor extends Model
[before, after] = @editor.getTextInBufferRange(range)
return false if /\s/.test(before) or /\s/.test(after)
nonWordCharacters = @config.get('editor.nonWordCharacters', scope: @getScopeDescriptor()).split('')
_.contains(nonWordCharacters, before) isnt _.contains(nonWordCharacters, after)
nonWordCharacters = @getNonWordCharacters()
nonWordCharacters.includes(before) isnt nonWordCharacters.includes(after)
# Public: Returns whether this cursor is between a word's start and end.
#
@@ -608,9 +608,7 @@ class Cursor extends Model
#
# Returns a {RegExp}.
wordRegExp: (options) ->
scope = @getScopeDescriptor()
nonWordCharacters = _.escapeRegExp(@config.get('editor.nonWordCharacters', {scope}))
nonWordCharacters = _.escapeRegExp(@getNonWordCharacters())
source = "^[\t ]*$|[^\\s#{nonWordCharacters}]+"
if options?.includeNonWordCharacters ? true
source += "|" + "[#{nonWordCharacters}]+"
@@ -624,7 +622,7 @@ class Cursor extends Model
#
# Returns a {RegExp}.
subwordRegExp: (options={}) ->
nonWordCharacters = @config.get('editor.nonWordCharacters', scope: @getScopeDescriptor())
nonWordCharacters = @getNonWordCharacters()
lowercaseLetters = 'a-z\\u00DF-\\u00F6\\u00F8-\\u00FF'
uppercaseLetters = 'A-Z\\u00C0-\\u00D6\\u00D8-\\u00DE'
snakeCamelSegment = "[#{uppercaseLetters}]?[#{lowercaseLetters}]+"
@@ -647,6 +645,14 @@ class Cursor extends Model
Section: Private
###
getNonWordCharacters: ->
(
@editor
.scopedSettingsDelegate
?.getNonWordCharacters?(@getScopeDescriptor().getScopesArray()) ?
@editor.getNonWordCharacters()
)
changePosition: (options, fn) ->
@clearSelection(autoscroll: false)
fn()

View File

@@ -18,6 +18,7 @@ const EDITOR_SETTER_NAMES_BY_SETTING_KEY = [
['editor.autoIndentOnPaste', 'setAutoIndentOnPaste'],
['editor.scrollPastEnd', 'setScrollPastEnd'],
['editor.undoGroupingInterval', 'setUndoGroupingInterval'],
['editor.nonWordCharacters', 'setNonWordCharacters'],
]
// Experimental: This global registry tracks registered `TextEditors`.
@@ -39,6 +40,7 @@ export default class TextEditorRegistry {
this.emitter = new Emitter()
this.scopesWithConfigSubscriptions = new Set()
this.editorsWithMaintainedConfig = new Set()
this.scopedSettingsDelegate = new ScopedSettingsDelegate(config)
}
destroy () {
@@ -90,6 +92,7 @@ export default class TextEditorRegistry {
maintainConfig (editor) {
this.editorsWithMaintainedConfig.add(editor)
this.subscribeToSettingsForEditorScope(editor)
editor.setScopedSettingsDelegate(this.scopedSettingsDelegate)
const configOptions = {scope: editor.getRootScopeDescriptor()}
for (const [settingKey, setterName] of EDITOR_SETTER_NAMES_BY_SETTING_KEY) {
@@ -165,3 +168,13 @@ function shouldEditorUseSoftTabs (editor, tabType, softTabs) {
}
}
}
class ScopedSettingsDelegate {
constructor (config) {
this.config = config
}
getNonWordCharacters(scope) {
return this.config.get('editor.nonWordCharacters', {scope: scope})
}
}

View File

@@ -154,6 +154,7 @@ class TextEditor extends Model
@autoIndent ?= true
@autoIndentOnPaste ?= true
@undoGroupingInterval ?= 300
@nonWordCharacters ?= "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-…"
@buffer ?= new TextBuffer
@tokenizedBuffer ?= new TokenizedBuffer({
@@ -2094,7 +2095,7 @@ class TextEditor extends Model
# Add a cursor based on the given {DisplayMarker}.
addCursor: (marker) ->
cursor = new Cursor(editor: this, marker: marker, config: @config)
cursor = new Cursor(editor: this, marker: marker)
@cursors.push(cursor)
@cursorsByMarkerId.set(marker.id, cursor)
@decorateMarker(marker, type: 'line-number', class: 'cursor-line')
@@ -3328,6 +3329,10 @@ class TextEditor extends Model
Section: Config
###
setScopedSettingsDelegate: (@scopedSettingsDelegate) ->
getScopedSettingsDelegate: -> @scopedSettingsDelegate
setAutoIndent: (@autoIndent) ->
setAutoIndentOnPaste: (@autoIndentOnPaste) ->
@@ -3344,6 +3349,10 @@ class TextEditor extends Model
getUndoGroupingInterval: -> @undoGroupingInterval
setNonWordCharacters: (@nonWordCharacters) ->
getNonWordCharacters: -> @nonWordCharacters
###
Section: Event Handlers
###