From 7eb01272edf5151f31f289e9e1671289c1495545 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 8 Jun 2012 12:31:29 -0600 Subject: [PATCH] Move text insertion and auto indent/outdent code from the selection view to the model --- spec/app/selection-spec.coffee | 2 +- src/app/ace-outdent-adaptor.coffee | 9 ++++---- src/app/cursor.coffee | 3 +++ src/app/edit-session.coffee | 36 +++++++++++++++++++++++++---- src/app/editor.coffee | 6 ++--- src/app/renderer.coffee | 3 +++ src/app/selection-view.coffee | 30 ------------------------ src/app/selection.coffee | 37 ++++++++++++++++++++++++++++++ 8 files changed, 84 insertions(+), 42 deletions(-) diff --git a/spec/app/selection-spec.coffee b/spec/app/selection-spec.coffee index b10c1724b..a86958407 100644 --- a/spec/app/selection-spec.coffee +++ b/spec/app/selection-spec.coffee @@ -307,7 +307,7 @@ describe "Selection", -> describe "inserting text", -> it "destroys the fold", -> selection.setBufferRange([[1,0], [2,0]]) - selection.insertText('holy cow') + editor.insertText('holy cow') expect(editor.screenLineForRow(3).text).toBe buffer.lineForRow(3) describe "backspace", -> diff --git a/src/app/ace-outdent-adaptor.coffee b/src/app/ace-outdent-adaptor.coffee index c4674ac01..795d2a066 100644 --- a/src/app/ace-outdent-adaptor.coffee +++ b/src/app/ace-outdent-adaptor.coffee @@ -2,7 +2,8 @@ Range = require 'range' module.exports = class AceOutdentAdaptor - constructor: (@buffer, @editor) -> + constructor: (@editSession) -> + @buffer = @editSession.buffer getLine: (row) -> @buffer.lineForRow(row) @@ -13,9 +14,9 @@ class AceOutdentAdaptor # Does not actually replace text, just line at range.start outdents one level replace: (range, text) -> - {row, column} = @editor.getCursorBufferPosition() + {row, column} = @editSession.getCursorBufferPosition() start = range.start - end = {row: range.start.row, column: range.start.column + @editor.tabText.length} + end = {row: range.start.row, column: range.start.column + @editSession.tabText.length} @buffer.change(new Range(start, end), "") - @editor.setCursorBufferPosition({row, column: column - @editor.tabText.length}) + @editSession.setCursorBufferPosition({row, column: column - @editSession.tabText.length}) diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index 369d7bbe9..2ea2ec808 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -36,6 +36,9 @@ class Cursor getBufferPosition: -> @anchor.getBufferPosition() + getCurrentScreenRow: -> + @getScreenPosition().row + getCurrentBufferRow: -> @getBufferPosition().row diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index a9e9d1279..064304a67 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -26,6 +26,7 @@ class EditSession constructor: (@editor, @buffer) -> @id = @constructor.idCounter++ + @tabText = @editor.tabText @renderer = new Renderer(@buffer, { softWrapColumn: @editor.calcSoftWrapColumn(), tabText: @editor.tabText }) @cursors = [] @selections = [] @@ -65,6 +66,9 @@ class EditSession setScrollLeft: (@scrollLeft) -> getScrollLeft: -> @scrollLeft + autoIndentEnabled: -> + @editor.autoIndent + screenPositionForBufferPosition: (bufferPosition, options) -> @renderer.screenPositionForBufferPosition(bufferPosition, options) @@ -92,8 +96,26 @@ class EditSession backwardsScanInRange: (args...) -> @buffer.backwardsScanInRange(args...) - getCursors: -> @cursors - getSelections: -> @selections + getCurrentMode: -> + @buffer.getMode() + + insertText: (text) -> + @mutateSelectedText (selection) -> selection.insertText(text) + + destroyFoldsContainingBufferRow: (bufferRow) -> + @renderer.destroyFoldsContainingBufferRow(bufferRow) + + mutateSelectedText: (fn) -> + selections = @getSelections() + @buffer.startUndoBatch(@getSelectedBufferRanges()) + fn(selection) for selection in selections + @buffer.endUndoBatch(@getSelectedBufferRanges()) + + stateForScreenRow: (screenRow) -> + @renderer.stateForScreenRow(screenRow) + + getCursors: -> new Array(@cursors...) + getSelections: -> new Array(@selections...) addCursorAtScreenPosition: (screenPosition) -> @addCursor(new Cursor(editSession: this, screenPosition: screenPosition)) @@ -107,14 +129,17 @@ class EditSession @addSelectionForCursor(cursor) cursor + removeCursor: (cursor) -> + _.remove(@cursors, cursor) + addSelectionForCursor: (cursor) -> selection = new Selection(editSession: this, cursor: cursor) @selections.push(selection) @trigger 'add-selection', selection selection - removeCursor: (cursor) -> - _.remove(@cursors, cursor) + removeSelection: (selection) -> + _.remove(@selections, selection) getLastCursor: -> _.last(@cursors) @@ -131,6 +156,9 @@ class EditSession getCursorBufferPosition: -> @getLastCursor().getBufferPosition() + getSelectedBufferRanges: -> + selection.getBufferRange() for selection in @selections + moveCursorUp: -> @moveCursors (cursor) -> cursor.moveUp() diff --git a/src/app/editor.coffee b/src/app/editor.coffee index 399d61e6d..a3775c1f5 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -707,7 +707,7 @@ class Editor extends View backwardsScanInRange: (args...) -> @buffer.backwardsScanInRange(args...) insertText: (text) -> - @compositeSelection.insertText(text) + @activeEditSession.insertText(text) insertNewline: -> @insertText('\n') @@ -719,9 +719,9 @@ class Editor extends View insertTab: -> if @getSelection().isEmpty() if @softTabs - @compositeSelection.insertText(@tabText) + @insertText(@tabText) else - @compositeSelection.insertText('\t') + @insertText('\t') else @compositeSelection.indentSelectedRows() diff --git a/src/app/renderer.coffee b/src/app/renderer.coffee index 2802ad504..0d505f860 100644 --- a/src/app/renderer.coffee +++ b/src/app/renderer.coffee @@ -159,6 +159,9 @@ class Renderer bufferPositionForScreenPosition: (position, options) -> @lineMap.bufferPositionForScreenPosition(position, options) + stateForScreenRow: (screenRow) -> + @highlighter.stateForRow(screenRow) + clipScreenPosition: (position, options) -> @lineMap.clipScreenPosition(position, options) diff --git a/src/app/selection-view.coffee b/src/app/selection-view.coffee index 8068228af..c6efbcdcb 100644 --- a/src/app/selection-view.coffee +++ b/src/app/selection-view.coffee @@ -97,16 +97,6 @@ class SelectionView extends View intersectsBufferRange: (bufferRange) -> @getBufferRange().intersectsWith(bufferRange) - insertText: (text) -> - { text, shouldOutdent } = @autoIndentText(text) - oldBufferRange = @getBufferRange() - @editor.destroyFoldsContainingBufferRow(oldBufferRange.end.row) - wasReversed = @isReversed() - @clearSelection() - newBufferRange = @editor.buffer.change(oldBufferRange, text) - @cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed - @autoOutdentText() if shouldOutdent - indentSelectedRows: -> range = @getBufferRange() for row in [range.start.row..range.end.row] @@ -124,26 +114,6 @@ class SelectionView extends View @modifySelection => @editor.toggleLineCommentsInRange(@getBufferRange()) - autoIndentText: (text) -> - if @editor.autoIndent - mode = @editor.getCurrentMode() - row = @cursor.getScreenPosition().row - state = @editor.stateForScreenRow(row) - lineBeforeCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferPosition().column] - if text[0] == "\n" - indent = mode.getNextLineIndent(state, lineBeforeCursor, @editor.tabText) - text = text[0] + indent + text[1..] - else if mode.checkOutdent(state, lineBeforeCursor, text) - shouldOutdent = true - - {text, shouldOutdent} - - autoOutdentText: -> - screenRow = @cursor.getScreenPosition().row - bufferRow = @cursor.getBufferPosition().row - state = @editor.renderer.lineForRow(screenRow).state - @editor.getCurrentMode().autoOutdent(state, new AceOutdentAdaptor(@editor.buffer, @editor), bufferRow) - backspace: -> @editor.destroyFoldsContainingBufferRow(@getBufferRange().end.row) @selectLeft() if @isEmpty() diff --git a/src/app/selection.coffee b/src/app/selection.coffee index 1b6c52116..839c02aad 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -1,6 +1,7 @@ Range = require 'range' Anchor = require 'new-anchor' EventEmitter = require 'event-emitter' +AceOutdentAdaptor = require 'ace-outdent-adaptor' _ = require 'underscore' module.exports = @@ -11,6 +12,12 @@ class Selection @cursor.on 'change-screen-position', (e) => @trigger 'change-screen-range', @getScreenRange() unless e.bufferChanged + @cursor.on 'destroy', => @destroy() + + destroy: -> + @cursor.off() + @editSession.removeSelection(this) + getScreenRange: -> if @anchor new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition()) @@ -43,6 +50,36 @@ class Selection isReversed: -> not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition()) + insertText: (text) -> + { text, shouldOutdent } = @autoIndentText(text) + oldBufferRange = @getBufferRange() + @editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row) + wasReversed = @isReversed() + @clear() + newBufferRange = @editSession.buffer.change(oldBufferRange, text) + @cursor.setBufferPosition(newBufferRange.end, skipAtomicTokens: true) if wasReversed + @autoOutdentText() if shouldOutdent + + autoIndentText: (text) -> + if @editSession.autoIndentEnabled() + mode = @editSession.getCurrentMode() + row = @cursor.getCurrentScreenRow() + state = @editSession.stateForScreenRow(row) + lineBeforeCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferPosition().column] + if text[0] == "\n" + indent = mode.getNextLineIndent(state, lineBeforeCursor, @editSession.tabText) + text = text[0] + indent + text[1..] + else if mode.checkOutdent(state, lineBeforeCursor, text) + shouldOutdent = true + + {text, shouldOutdent} + + autoOutdentText: -> + screenRow = @cursor.getCurrentScreenRow() + bufferRow = @cursor.getCurrentBufferRow() + state = @editSession.stateForScreenRow(screenRow) + @editSession.getCurrentMode().autoOutdent(state, new AceOutdentAdaptor(@editSession), bufferRow) + handleBufferChange: (e) -> @modifyScreenRange => @anchor?.handleBufferChange(e)