diff --git a/spec/app/edit-session-spec.coffee b/spec/app/edit-session-spec.coffee index 7ee574e24..2adf7feb4 100644 --- a/spec/app/edit-session-spec.coffee +++ b/spec/app/edit-session-spec.coffee @@ -307,6 +307,36 @@ describe "EditSession", -> editSession.moveCursorToEndOfWord() expect(editSession.getCursorBufferPosition()).toEqual endPosition + describe ".getCurrentParagraphBufferRange()", -> + it "returns the buffer range of the current paragraph, delimited by blank lines or the beginning / end of the file", -> + buffer.setText """ + I am the first paragraph, + bordered by the beginning of + the file + #{' '} + + I am the second paragraph + with blank lines above and below + me. + + I am the last paragraph, + bordered by the end of the file. + """ + + # in a paragraph + editSession.setCursorBufferPosition([1, 7]) + expect(editSession.getCurrentParagraphBufferRange()).toEqual [[0, 0], [2, 8]] + + editSession.setCursorBufferPosition([7, 1]) + expect(editSession.getCurrentParagraphBufferRange()).toEqual [[5, 0], [7, 3]] + + editSession.setCursorBufferPosition([9, 10]) + expect(editSession.getCurrentParagraphBufferRange()).toEqual [[9, 0], [10, 32]] + + # between paragraphs + editSession.setCursorBufferPosition([3, 1]) + expect(editSession.getCurrentParagraphBufferRange()).toBeUndefined() + describe "selection", -> selection = null diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index da44e890e..498b2ef83 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -175,6 +175,23 @@ class Cursor getCurrentLineBufferRange: (options) -> @editSession.bufferRangeForBufferRow(@getBufferRow(), options) + getCurrentParagraphBufferRange: -> + row = @getBufferRow() + return unless /\w/.test(@editSession.lineForBufferRow(row)) + + startRow = row + while startRow > 0 + break unless /\w/.test(@editSession.lineForBufferRow(startRow - 1)) + startRow-- + + endRow = row + lastRow = @editSession.getLastBufferRow() + while endRow < lastRow + break unless /\w/.test(@editSession.lineForBufferRow(endRow + 1)) + endRow++ + + new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)]) + getCurrentWordPrefix: -> @editSession.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()]) diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 8d7d3f03c..24bcb6bf1 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -139,6 +139,7 @@ class EditSession getLastBufferRow: -> @buffer.getLastRow() bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options) lineForBufferRow: (row) -> @buffer.lineForRow(row) + lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row) scanInRange: (args...) -> @buffer.scanInRange(args...) backwardsScanInRange: (args...) -> @buffer.backwardsScanInRange(args...) @@ -489,6 +490,9 @@ class EditSession getTextInBufferRange: (range) -> @buffer.getTextInRange(range) + getCurrentParagraphBufferRange: -> + @getCursor().getCurrentParagraphBufferRange() + moveCursorUp: (lineCount) -> @moveCursors (cursor) -> cursor.moveUp(lineCount) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index e8bb77dfd..4f2b2befb 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -206,6 +206,7 @@ class Editor extends View getCursorScreenRow: -> @activeEditSession.getCursorScreenRow() setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options) getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition() + getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange() getSelection: (index) -> @activeEditSession.getSelection(index) getSelections: -> @activeEditSession.getSelections() diff --git a/src/packages/autoflow/index.coffee b/src/packages/autoflow/index.coffee new file mode 100644 index 000000000..950ab2727 --- /dev/null +++ b/src/packages/autoflow/index.coffee @@ -0,0 +1 @@ +module.exports = require './lib/autoflow' diff --git a/src/packages/autoflow/lib/autoflow.coffee b/src/packages/autoflow/lib/autoflow.coffee new file mode 100644 index 000000000..41a583e68 --- /dev/null +++ b/src/packages/autoflow/lib/autoflow.coffee @@ -0,0 +1,31 @@ +module.exports = + activate: (rootView) -> + rootView.command 'autoflow:reflow-paragraph', '.editor', (e) => + @reflowParagraph(e.currentTargetView()) + + reflowParagraph: (editor) -> + if range = editor.getCurrentParagraphBufferRange() + editor.getBuffer().change(range, @reflow(editor.getTextInRange(range))) + + reflow: (text) -> + wrapColumn = config.get('editor.preferredLineLength') ? 80 + lines = [] + + currentLine = [] + currentLineLength = 0 + for segment in @segmentText(text.replace(/\n/g, ' ')) + if /\w/.test(segment) and currentLineLength + segment.length > wrapColumn + lines.push(currentLine.join('')) + currentLine = [] + currentLineLength = 0 + currentLine.push(segment) + currentLineLength += segment.length + lines.push(currentLine.join('')) + + lines.join('\n').replace(/\s+\n/g, '\n') + + segmentText: (text) -> + segments = [] + re = /[\s]+|[^\s]+/g + segments.push(match[0]) while match = re.exec(text) + segments diff --git a/src/packages/autoflow/spec/autoflow-spec.coffee b/src/packages/autoflow/spec/autoflow-spec.coffee new file mode 100644 index 000000000..d41e25bb1 --- /dev/null +++ b/src/packages/autoflow/spec/autoflow-spec.coffee @@ -0,0 +1,41 @@ +RootView = require 'root-view' + +describe "Autoflow package", -> + editor = null + + beforeEach -> + rootView = new RootView + atom.loadPackage 'autoflow' + editor = rootView.getActiveEditor() + + describe "autoflow:reflow-paragraph", -> + it "rearranges line breaks in the current paragraph to ensure lines are shorter than config.editor.preferredLineLength", -> + config.set('editor.preferredLineLength', 30) + editor.setText """ + This is a preceding paragraph, which shouldn't be modified by a reflow of the following paragraph. + + The quick brown fox jumps over the lazy + dog. The preceding sentence contains every letter + in the entire English alphabet, which has absolutely no relevance + to this test. + + This is a following paragraph, which shouldn't be modified by a reflow of the preciding paragraph. + + """ + + editor.setCursorBufferPosition([3, 5]) + editor.trigger 'autoflow:reflow-paragraph' + + expect(editor.getText()).toBe """ + This is a preceding paragraph, which shouldn't be modified by a reflow of the following paragraph. + + The quick brown fox jumps over + the lazy dog. The preceding + sentence contains every letter + in the entire English + alphabet, which has absolutely + no relevance to this test. + + This is a following paragraph, which shouldn't be modified by a reflow of the preciding paragraph. + + """