mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-21 07:58:04 +03:00
Merge pull request #15977 from atom/mb-use-language-modes
Move `toggleLineComments` method from TokenizedBuffer to TextEditor
This commit is contained in:
commit
9a95372613
@ -4376,108 +4376,6 @@ describe "TextEditor", ->
|
||||
expect(editor.lineTextForBufferRow(4)).toBe " }"
|
||||
expect(editor.lineTextForBufferRow(5)).toBe " i=1"
|
||||
|
||||
describe ".toggleLineCommentsInSelection()", ->
|
||||
it "toggles comments on the selected lines", ->
|
||||
editor.setSelectedBufferRange([[4, 5], [7, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {"
|
||||
expect(buffer.lineForRow(5)).toBe " // current = items.shift();"
|
||||
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
|
||||
expect(buffer.lineForRow(7)).toBe " // }"
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[4, 8], [7, 8]]
|
||||
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
|
||||
expect(buffer.lineForRow(5)).toBe " current = items.shift();"
|
||||
expect(buffer.lineForRow(6)).toBe " current < pivot ? left.push(current) : right.push(current);"
|
||||
expect(buffer.lineForRow(7)).toBe " }"
|
||||
|
||||
it "does not comment the last line of a non-empty selection if it ends at column 0", ->
|
||||
editor.setSelectedBufferRange([[4, 5], [7, 0]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(4)).toBe " // while(items.length > 0) {"
|
||||
expect(buffer.lineForRow(5)).toBe " // current = items.shift();"
|
||||
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
|
||||
expect(buffer.lineForRow(7)).toBe " }"
|
||||
|
||||
it "uncomments lines if all lines match the comment regex", ->
|
||||
editor.setSelectedBufferRange([[0, 0], [0, 1]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {"
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "// // var quicksort = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe "// var sort = function(items) {"
|
||||
expect(buffer.lineForRow(2)).toBe "// if (items.length <= 1) return items;"
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe " var sort = function(items) {"
|
||||
expect(buffer.lineForRow(2)).toBe " if (items.length <= 1) return items;"
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [0, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "var quicksort = function () {"
|
||||
|
||||
it "uncomments commented lines separated by an empty line", ->
|
||||
editor.setSelectedBufferRange([[0, 0], [1, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "// var quicksort = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe "// var sort = function(items) {"
|
||||
|
||||
buffer.insert([0, Infinity], '\n')
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(0)).toBe "var quicksort = function () {"
|
||||
expect(buffer.lineForRow(1)).toBe ""
|
||||
expect(buffer.lineForRow(2)).toBe " var sort = function(items) {"
|
||||
|
||||
it "preserves selection emptiness", ->
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.getLastSelection().isEmpty()).toBeTruthy()
|
||||
|
||||
it "does not explode if the current language mode has no comment regex", ->
|
||||
editor = new TextEditor(buffer: new TextBuffer(text: 'hello'))
|
||||
editor.setSelectedBufferRange([[0, 0], [0, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe "hello"
|
||||
|
||||
it "does nothing for empty lines and null grammar", ->
|
||||
runs ->
|
||||
editor.setGrammar(atom.grammars.grammarForScopeName('text.plain.null-grammar'))
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.buffer.lineForRow(10)).toBe ""
|
||||
|
||||
it "uncomments when the line lacks the trailing whitespace in the comment regex", ->
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(buffer.lineForRow(10)).toBe "// "
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[10, 3], [10, 3]]
|
||||
editor.backspace()
|
||||
expect(buffer.lineForRow(10)).toBe "//"
|
||||
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(10)).toBe ""
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[10, 0], [10, 0]]
|
||||
|
||||
it "uncomments when the line has leading whitespace", ->
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(buffer.lineForRow(10)).toBe "// "
|
||||
editor.moveToBeginningOfLine()
|
||||
editor.insertText(" ")
|
||||
editor.setSelectedBufferRange([[10, 0], [10, 0]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(10)).toBe " "
|
||||
|
||||
describe ".undo() and .redo()", ->
|
||||
it "undoes/redoes the last change", ->
|
||||
editor.insertText("foo")
|
||||
|
@ -2,6 +2,8 @@ const fs = require('fs')
|
||||
const temp = require('temp').track()
|
||||
const {Point, Range} = require('text-buffer')
|
||||
const {it, fit, ffit, fffit, beforeEach, afterEach} = require('./async-spec-helpers')
|
||||
const TextBuffer = require('text-buffer')
|
||||
const TextEditor = require('../src/text-editor')
|
||||
|
||||
describe('TextEditor', () => {
|
||||
let editor
|
||||
@ -58,6 +60,276 @@ describe('TextEditor', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('.toggleLineCommentsInSelection()', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-javascript')
|
||||
editor = await atom.workspace.open('sample.js')
|
||||
})
|
||||
|
||||
it('toggles comments on the selected lines', () => {
|
||||
editor.setSelectedBufferRange([[4, 5], [7, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' // while(items.length > 0) {')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' // current = items.shift();')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' // }')
|
||||
expect(editor.getSelectedBufferRange()).toEqual([[4, 8], [7, 8]])
|
||||
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' while(items.length > 0) {')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' current = items.shift();')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' }')
|
||||
})
|
||||
|
||||
it('does not comment the last line of a non-empty selection if it ends at column 0', () => {
|
||||
editor.setSelectedBufferRange([[4, 5], [7, 0]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' // while(items.length > 0) {')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' // current = items.shift();')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' }')
|
||||
})
|
||||
|
||||
it('uncomments lines if all lines match the comment regex', () => {
|
||||
editor.setSelectedBufferRange([[0, 0], [0, 1]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// var quicksort = function () {')
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// // var quicksort = function () {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe('// var sort = function(items) {')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe('// if (items.length <= 1) return items;')
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// var quicksort = function () {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' var sort = function(items) {')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' if (items.length <= 1) return items;')
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [0, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('var quicksort = function () {')
|
||||
})
|
||||
|
||||
it('uncomments commented lines separated by an empty line', () => {
|
||||
editor.setSelectedBufferRange([[0, 0], [1, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// var quicksort = function () {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe('// var sort = function(items) {')
|
||||
|
||||
editor.getBuffer().insert([0, Infinity], '\n')
|
||||
|
||||
editor.setSelectedBufferRange([[0, 0], [2, Infinity]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('var quicksort = function () {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe('')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' var sort = function(items) {')
|
||||
})
|
||||
|
||||
it('preserves selection emptiness', () => {
|
||||
editor.setCursorBufferPosition([4, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.getLastSelection().isEmpty()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('does not explode if the current language mode has no comment regex', () => {
|
||||
const editor = new TextEditor({buffer: new TextBuffer({text: 'hello'})})
|
||||
editor.setSelectedBufferRange([[0, 0], [0, 5]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('hello')
|
||||
})
|
||||
|
||||
it('does nothing for empty lines and null grammar', () => {
|
||||
editor.setGrammar(atom.grammars.grammarForScopeName('text.plain.null-grammar'))
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(10)).toBe('')
|
||||
})
|
||||
|
||||
it('uncomments when the line lacks the trailing whitespace in the comment regex', () => {
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(editor.lineTextForBufferRow(10)).toBe('// ')
|
||||
expect(editor.getSelectedBufferRange()).toEqual([[10, 3], [10, 3]])
|
||||
editor.backspace()
|
||||
expect(editor.lineTextForBufferRow(10)).toBe('//')
|
||||
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(10)).toBe('')
|
||||
expect(editor.getSelectedBufferRange()).toEqual([[10, 0], [10, 0]])
|
||||
})
|
||||
|
||||
it('uncomments when the line has leading whitespace', () => {
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
|
||||
expect(editor.lineTextForBufferRow(10)).toBe('// ')
|
||||
editor.moveToBeginningOfLine()
|
||||
editor.insertText(' ')
|
||||
editor.setSelectedBufferRange([[10, 0], [10, 0]])
|
||||
editor.toggleLineCommentsInSelection()
|
||||
expect(editor.lineTextForBufferRow(10)).toBe(' ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('.toggleLineCommentsForBufferRows', () => {
|
||||
describe('xml', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-xml')
|
||||
editor = await atom.workspace.open('test.xml')
|
||||
editor.setText('<!-- test -->')
|
||||
})
|
||||
|
||||
it('removes the leading whitespace from the comment end pattern match when uncommenting lines', () => {
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('test')
|
||||
})
|
||||
})
|
||||
|
||||
describe('less', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-less')
|
||||
await atom.packages.activatePackage('language-css')
|
||||
editor = await atom.workspace.open('sample.less')
|
||||
})
|
||||
|
||||
it('only uses the `commentEnd` pattern if it comes from the same grammar as the `commentStart` when commenting lines', () => {
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// @color: #4D926F;')
|
||||
})
|
||||
})
|
||||
|
||||
describe('css', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-css')
|
||||
editor = await atom.workspace.open('css.css')
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
editor.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('/* body {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' font-size: 1234px; */')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' width: 110%;')
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(' font-weight: bold !important;')
|
||||
|
||||
editor.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('/* body {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' font-size: 1234px; */')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' /* width: 110%; */')
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(' font-weight: bold !important;')
|
||||
|
||||
editor.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('body {')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' font-size: 1234px;')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' /* width: 110%; */')
|
||||
expect(editor.lineTextForBufferRow(3)).toBe(' font-weight: bold !important;')
|
||||
})
|
||||
|
||||
it('uncomments lines with leading whitespace', () => {
|
||||
editor.setTextInBufferRange([[2, 0], [2, Infinity]], ' /* width: 110%; */')
|
||||
editor.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' width: 110%;')
|
||||
})
|
||||
|
||||
it('uncomments lines with trailing whitespace', () => {
|
||||
editor.setTextInBufferRange([[2, 0], [2, Infinity]], '/* width: 110%; */ ')
|
||||
editor.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(editor.lineTextForBufferRow(2)).toBe('width: 110%; ')
|
||||
})
|
||||
|
||||
it('uncomments lines with leading and trailing whitespace', () => {
|
||||
editor.setTextInBufferRange([[2, 0], [2, Infinity]], ' /* width: 110%; */ ')
|
||||
editor.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' width: 110%; ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('coffeescript', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-coffee-script')
|
||||
editor = await atom.workspace.open('coffee.coffee')
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
editor.toggleLineCommentsForBufferRows(4, 6)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' # pivot = items.shift()')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' # left = []')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' # right = []')
|
||||
|
||||
editor.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' pivot = items.shift()')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' left = []')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' # right = []')
|
||||
})
|
||||
|
||||
it('comments/uncomments empty lines', () => {
|
||||
editor.toggleLineCommentsForBufferRows(4, 7)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' # pivot = items.shift()')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' # left = []')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' # right = []')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' # ')
|
||||
|
||||
editor.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' pivot = items.shift()')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' left = []')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' # right = []')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' # ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('javascript', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-javascript')
|
||||
editor = await atom.workspace.open('sample.js')
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
editor.toggleLineCommentsForBufferRows(4, 7)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' // while(items.length > 0) {')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' // current = items.shift();')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' // }')
|
||||
|
||||
editor.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(editor.lineTextForBufferRow(4)).toBe(' while(items.length > 0) {')
|
||||
expect(editor.lineTextForBufferRow(5)).toBe(' current = items.shift();')
|
||||
expect(editor.lineTextForBufferRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(editor.lineTextForBufferRow(7)).toBe(' // }')
|
||||
|
||||
editor.setText('\tvar i;')
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('\t// var i;')
|
||||
|
||||
editor.setText('var i;')
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe('// var i;')
|
||||
|
||||
editor.setText(' var i;')
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe(' // var i;')
|
||||
|
||||
editor.setText(' ')
|
||||
editor.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe(' // ')
|
||||
|
||||
editor.setText(' a\n \n b')
|
||||
editor.toggleLineCommentsForBufferRows(0, 2)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe(' // a')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' // ')
|
||||
expect(editor.lineTextForBufferRow(2)).toBe(' // b')
|
||||
|
||||
editor.setText(' \n // var i;')
|
||||
editor.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(editor.lineTextForBufferRow(0)).toBe(' ')
|
||||
expect(editor.lineTextForBufferRow(1)).toBe(' var i;')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('folding', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-javascript')
|
||||
|
@ -643,186 +643,6 @@ describe('TokenizedBuffer', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('.toggleLineCommentsForBufferRows', () => {
|
||||
describe('xml', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-xml')
|
||||
buffer = new TextBuffer('<!-- test -->')
|
||||
tokenizedBuffer = new TokenizedBuffer({
|
||||
buffer,
|
||||
grammar: atom.grammars.grammarForScopeName('text.xml'),
|
||||
scopedSettingsDelegate: new ScopedSettingsDelegate(atom.config)
|
||||
})
|
||||
})
|
||||
|
||||
it('removes the leading whitespace from the comment end pattern match when uncommenting lines', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe('test')
|
||||
})
|
||||
})
|
||||
|
||||
describe('less', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-less')
|
||||
await atom.packages.activatePackage('language-css')
|
||||
buffer = await TextBuffer.load(require.resolve('./fixtures/sample.less'))
|
||||
tokenizedBuffer = new TokenizedBuffer({
|
||||
buffer,
|
||||
grammar: atom.grammars.grammarForScopeName('source.css.less'),
|
||||
scopedSettingsDelegate: new ScopedSettingsDelegate(atom.config)
|
||||
})
|
||||
})
|
||||
|
||||
it('only uses the `commentEnd` pattern if it comes from the same grammar as the `commentStart` when commenting lines', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe('// @color: #4D926F;')
|
||||
})
|
||||
})
|
||||
|
||||
describe('css', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-css')
|
||||
buffer = await TextBuffer.load(require.resolve('./fixtures/css.css'))
|
||||
tokenizedBuffer = new TokenizedBuffer({
|
||||
buffer,
|
||||
grammar: atom.grammars.grammarForScopeName('source.css'),
|
||||
scopedSettingsDelegate: new ScopedSettingsDelegate(atom.config)
|
||||
})
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(buffer.lineForRow(0)).toBe('/*body {')
|
||||
expect(buffer.lineForRow(1)).toBe(' font-size: 1234px;*/')
|
||||
expect(buffer.lineForRow(2)).toBe(' width: 110%;')
|
||||
expect(buffer.lineForRow(3)).toBe(' font-weight: bold !important;')
|
||||
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(0)).toBe('/*body {')
|
||||
expect(buffer.lineForRow(1)).toBe(' font-size: 1234px;*/')
|
||||
expect(buffer.lineForRow(2)).toBe(' /*width: 110%;*/')
|
||||
expect(buffer.lineForRow(3)).toBe(' font-weight: bold !important;')
|
||||
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(buffer.lineForRow(0)).toBe('body {')
|
||||
expect(buffer.lineForRow(1)).toBe(' font-size: 1234px;')
|
||||
expect(buffer.lineForRow(2)).toBe(' /*width: 110%;*/')
|
||||
expect(buffer.lineForRow(3)).toBe(' font-weight: bold !important;')
|
||||
})
|
||||
|
||||
it('uncomments lines with leading whitespace', () => {
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], ' /*width: 110%;*/')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe(' width: 110%;')
|
||||
})
|
||||
|
||||
it('uncomments lines with trailing whitespace', () => {
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], '/*width: 110%;*/ ')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe('width: 110%; ')
|
||||
})
|
||||
|
||||
it('uncomments lines with leading and trailing whitespace', () => {
|
||||
buffer.setTextInRange([[2, 0], [2, Infinity]], ' /*width: 110%;*/ ')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(2, 2)
|
||||
expect(buffer.lineForRow(2)).toBe(' width: 110%; ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('coffeescript', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-coffee-script')
|
||||
buffer = await TextBuffer.load(require.resolve('./fixtures/coffee.coffee'))
|
||||
tokenizedBuffer = new TokenizedBuffer({
|
||||
buffer,
|
||||
tabLength: 2,
|
||||
grammar: atom.grammars.grammarForScopeName('source.coffee'),
|
||||
scopedSettingsDelegate: new ScopedSettingsDelegate(atom.config)
|
||||
})
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 6)
|
||||
expect(buffer.lineForRow(4)).toBe(' # pivot = items.shift()')
|
||||
expect(buffer.lineForRow(5)).toBe(' # left = []')
|
||||
expect(buffer.lineForRow(6)).toBe(' # right = []')
|
||||
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(buffer.lineForRow(4)).toBe(' pivot = items.shift()')
|
||||
expect(buffer.lineForRow(5)).toBe(' left = []')
|
||||
expect(buffer.lineForRow(6)).toBe(' # right = []')
|
||||
})
|
||||
|
||||
it('comments/uncomments empty lines', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 7)
|
||||
expect(buffer.lineForRow(4)).toBe(' # pivot = items.shift()')
|
||||
expect(buffer.lineForRow(5)).toBe(' # left = []')
|
||||
expect(buffer.lineForRow(6)).toBe(' # right = []')
|
||||
expect(buffer.lineForRow(7)).toBe(' # ')
|
||||
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(buffer.lineForRow(4)).toBe(' pivot = items.shift()')
|
||||
expect(buffer.lineForRow(5)).toBe(' left = []')
|
||||
expect(buffer.lineForRow(6)).toBe(' # right = []')
|
||||
expect(buffer.lineForRow(7)).toBe(' # ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('javascript', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('language-javascript')
|
||||
buffer = await TextBuffer.load(require.resolve('./fixtures/sample.js'))
|
||||
tokenizedBuffer = new TokenizedBuffer({
|
||||
buffer,
|
||||
tabLength: 2,
|
||||
grammar: atom.grammars.grammarForScopeName('source.js'),
|
||||
scopedSettingsDelegate: new ScopedSettingsDelegate(atom.config)
|
||||
})
|
||||
})
|
||||
|
||||
it('comments/uncomments lines in the given range', () => {
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 7)
|
||||
expect(buffer.lineForRow(4)).toBe(' // while(items.length > 0) {')
|
||||
expect(buffer.lineForRow(5)).toBe(' // current = items.shift();')
|
||||
expect(buffer.lineForRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(buffer.lineForRow(7)).toBe(' // }')
|
||||
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(4, 5)
|
||||
expect(buffer.lineForRow(4)).toBe(' while(items.length > 0) {')
|
||||
expect(buffer.lineForRow(5)).toBe(' current = items.shift();')
|
||||
expect(buffer.lineForRow(6)).toBe(' // current < pivot ? left.push(current) : right.push(current);')
|
||||
expect(buffer.lineForRow(7)).toBe(' // }')
|
||||
|
||||
buffer.setText('\tvar i;')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe('\t// var i;')
|
||||
|
||||
buffer.setText('var i;')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe('// var i;')
|
||||
|
||||
buffer.setText(' var i;')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe(' // var i;')
|
||||
|
||||
buffer.setText(' ')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe(' // ')
|
||||
|
||||
buffer.setText(' a\n \n b')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 2)
|
||||
expect(buffer.lineForRow(0)).toBe(' // a')
|
||||
expect(buffer.lineForRow(1)).toBe(' // ')
|
||||
expect(buffer.lineForRow(2)).toBe(' // b')
|
||||
|
||||
buffer.setText(' \n // var i;')
|
||||
tokenizedBuffer.toggleLineCommentsForBufferRows(0, 1)
|
||||
expect(buffer.lineForRow(0)).toBe(' ')
|
||||
expect(buffer.lineForRow(1)).toBe(' var i;')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.isFoldableAtRow(row)', () => {
|
||||
beforeEach(() => {
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
|
139
src/text-editor-utils.js
Normal file
139
src/text-editor-utils.js
Normal file
@ -0,0 +1,139 @@
|
||||
// This file is temporary. We should gradually convert methods in `text-editor.coffee`
|
||||
// from CoffeeScript to JavaScript and move them here, so that we can eventually convert
|
||||
// the entire class to JavaScript.
|
||||
|
||||
const {Point, Range} = require('text-buffer')
|
||||
|
||||
const NON_WHITESPACE_REGEX = /\S/
|
||||
|
||||
module.exports = {
|
||||
toggleLineCommentsForBufferRows (start, end) {
|
||||
let {
|
||||
commentStartString,
|
||||
commentEndString
|
||||
} = this.tokenizedBuffer.commentStringsForPosition(Point(start, 0))
|
||||
if (!commentStartString) return
|
||||
commentStartString = commentStartString.trim()
|
||||
|
||||
if (commentEndString) {
|
||||
commentEndString = commentEndString.trim()
|
||||
const startDelimiterColumnRange = columnRangeForStartDelimiter(
|
||||
this.buffer.lineForRow(start),
|
||||
commentStartString
|
||||
)
|
||||
if (startDelimiterColumnRange) {
|
||||
const endDelimiterColumnRange = columnRangeForEndDelimiter(
|
||||
this.buffer.lineForRow(end),
|
||||
commentEndString
|
||||
)
|
||||
if (endDelimiterColumnRange) {
|
||||
this.buffer.transact(() => {
|
||||
this.buffer.delete([[end, endDelimiterColumnRange[0]], [end, endDelimiterColumnRange[1]]])
|
||||
this.buffer.delete([[start, startDelimiterColumnRange[0]], [start, startDelimiterColumnRange[1]]])
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.buffer.transact(() => {
|
||||
const indentLength = this.buffer.lineForRow(start).match(/^\s*/)[0].length
|
||||
this.buffer.insert([start, indentLength], commentStartString + ' ')
|
||||
this.buffer.insert([end, this.buffer.lineLengthForRow(end)], ' ' + commentEndString)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
let hasCommentedLines = false
|
||||
let hasUncommentedLines = false
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
if (columnRangeForStartDelimiter(line, commentStartString)) {
|
||||
hasCommentedLines = true
|
||||
} else {
|
||||
hasUncommentedLines = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const shouldUncomment = hasCommentedLines && !hasUncommentedLines
|
||||
|
||||
if (shouldUncomment) {
|
||||
for (let row = start; row <= end; row++) {
|
||||
const columnRange = columnRangeForStartDelimiter(
|
||||
this.buffer.lineForRow(row),
|
||||
commentStartString
|
||||
)
|
||||
if (columnRange) this.buffer.delete([[row, columnRange[0]], [row, columnRange[1]]])
|
||||
}
|
||||
} else {
|
||||
let minIndentLevel = Infinity
|
||||
let minBlankIndentLevel = Infinity
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
const indentLevel = this.indentLevelForLine(line)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
if (indentLevel < minIndentLevel) minIndentLevel = indentLevel
|
||||
} else {
|
||||
if (indentLevel < minBlankIndentLevel) minBlankIndentLevel = indentLevel
|
||||
}
|
||||
}
|
||||
minIndentLevel = Number.isFinite(minIndentLevel)
|
||||
? minIndentLevel
|
||||
: Number.isFinite(minBlankIndentLevel)
|
||||
? minBlankIndentLevel
|
||||
: 0
|
||||
|
||||
const tabLength = this.getTabLength()
|
||||
const indentString = ' '.repeat(tabLength * minIndentLevel)
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
const indentColumn = columnForIndentLevel(line, minIndentLevel, this.getTabLength())
|
||||
this.buffer.insert(Point(row, indentColumn), commentStartString + ' ')
|
||||
} else {
|
||||
this.buffer.setTextInRange(
|
||||
new Range(new Point(row, 0), new Point(row, Infinity)),
|
||||
indentString + commentStartString + ' '
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function columnForIndentLevel (line, indentLevel, tabLength) {
|
||||
let column = 0
|
||||
let indentLength = 0
|
||||
const goalIndentLength = indentLevel * tabLength
|
||||
while (indentLength < goalIndentLength) {
|
||||
const char = line[column]
|
||||
if (char === '\t') {
|
||||
indentLength += tabLength - (indentLength % tabLength)
|
||||
} else if (char === ' ') {
|
||||
indentLength++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
column++
|
||||
}
|
||||
return column
|
||||
}
|
||||
|
||||
function columnRangeForStartDelimiter (line, delimiter) {
|
||||
const startColumn = line.search(NON_WHITESPACE_REGEX)
|
||||
if (startColumn === -1) return null
|
||||
if (!line.startsWith(delimiter, startColumn)) return null
|
||||
|
||||
let endColumn = startColumn + delimiter.length
|
||||
if (line[endColumn] === ' ') endColumn++
|
||||
return [startColumn, endColumn]
|
||||
}
|
||||
|
||||
function columnRangeForEndDelimiter (line, delimiter) {
|
||||
let startColumn = line.lastIndexOf(delimiter)
|
||||
if (startColumn === -1) return null
|
||||
|
||||
const endColumn = startColumn + delimiter.length
|
||||
if (NON_WHITESPACE_REGEX.test(line.slice(endColumn))) return null
|
||||
if (line[startColumn - 1] === ' ') startColumn--
|
||||
return [startColumn, endColumn]
|
||||
}
|
@ -9,6 +9,8 @@ TokenizedBuffer = require './tokenized-buffer'
|
||||
Cursor = require './cursor'
|
||||
Model = require './model'
|
||||
Selection = require './selection'
|
||||
TextEditorUtils = require './text-editor-utils'
|
||||
|
||||
TextMateScopeSelector = require('first-mate').ScopeSelector
|
||||
GutterContainer = require './gutter-container'
|
||||
TextEditorComponent = null
|
||||
@ -123,6 +125,8 @@ class TextEditor extends Model
|
||||
|
||||
Object.defineProperty(@prototype, 'languageMode', get: -> @tokenizedBuffer)
|
||||
|
||||
Object.assign(@prototype, TextEditorUtils)
|
||||
|
||||
@deserialize: (state, atomEnvironment) ->
|
||||
# TODO: Return null on version mismatch when 1.8.0 has been out for a while
|
||||
if state.version isnt @prototype.serializationVersion and state.displayBuffer?
|
||||
@ -3622,9 +3626,6 @@ class TextEditor extends Model
|
||||
getNonWordCharacters: (scopes) ->
|
||||
@scopedSettingsDelegate?.getNonWordCharacters?(scopes) ? @nonWordCharacters
|
||||
|
||||
getCommentStrings: (scopes) ->
|
||||
@scopedSettingsDelegate?.getCommentStrings?(scopes)
|
||||
|
||||
###
|
||||
Section: Event Handlers
|
||||
###
|
||||
@ -3887,8 +3888,6 @@ class TextEditor extends Model
|
||||
|
||||
toggleLineCommentForBufferRow: (row) -> @toggleLineCommentsForBufferRows(row, row)
|
||||
|
||||
toggleLineCommentsForBufferRows: (start, end) -> @tokenizedBuffer.toggleLineCommentsForBufferRows(start, end)
|
||||
|
||||
rowRangeForParagraphAtBufferRow: (bufferRow) ->
|
||||
return unless NON_WHITESPACE_REGEXP.test(@lineTextForBufferRow(bufferRow))
|
||||
|
||||
|
@ -163,99 +163,12 @@ class TokenizedBuffer {
|
||||
Section - Comments
|
||||
*/
|
||||
|
||||
toggleLineCommentsForBufferRows (start, end) {
|
||||
const scope = this.scopeDescriptorForPosition([start, 0])
|
||||
const commentStrings = this.commentStringsForScopeDescriptor(scope)
|
||||
if (!commentStrings) return
|
||||
const {commentStartString, commentEndString} = commentStrings
|
||||
if (!commentStartString) return
|
||||
|
||||
const commentStartRegexString = _.escapeRegExp(commentStartString).replace(/(\s+)$/, '(?:$1)?')
|
||||
const commentStartRegex = new OnigRegExp(`^(\\s*)(${commentStartRegexString})`)
|
||||
|
||||
if (commentEndString) {
|
||||
const shouldUncomment = commentStartRegex.testSync(this.buffer.lineForRow(start))
|
||||
if (shouldUncomment) {
|
||||
const commentEndRegexString = _.escapeRegExp(commentEndString).replace(/^(\s+)/, '(?:$1)?')
|
||||
const commentEndRegex = new OnigRegExp(`(${commentEndRegexString})(\\s*)$`)
|
||||
const startMatch = commentStartRegex.searchSync(this.buffer.lineForRow(start))
|
||||
const endMatch = commentEndRegex.searchSync(this.buffer.lineForRow(end))
|
||||
if (startMatch && endMatch) {
|
||||
this.buffer.transact(() => {
|
||||
const columnStart = startMatch[1].length
|
||||
const columnEnd = columnStart + startMatch[2].length
|
||||
this.buffer.setTextInRange([[start, columnStart], [start, columnEnd]], '')
|
||||
|
||||
const endLength = this.buffer.lineLengthForRow(end) - endMatch[2].length
|
||||
const endColumn = endLength - endMatch[1].length
|
||||
return this.buffer.setTextInRange([[end, endColumn], [end, endLength]], '')
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.buffer.transact(() => {
|
||||
const indentLength = this.buffer.lineForRow(start).match(/^\s*/)[0].length
|
||||
this.buffer.insert([start, indentLength], commentStartString)
|
||||
this.buffer.insert([end, this.buffer.lineLengthForRow(end)], commentEndString)
|
||||
})
|
||||
}
|
||||
commentStringsForPosition (position) {
|
||||
if (this.scopedSettingsDelegate) {
|
||||
const scope = this.scopeDescriptorForPosition(position)
|
||||
return this.scopedSettingsDelegate.getCommentStrings(scope)
|
||||
} else {
|
||||
let hasCommentedLines = false
|
||||
let hasUncommentedLines = false
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
if (commentStartRegex.testSync(line)) {
|
||||
hasCommentedLines = true
|
||||
} else {
|
||||
hasUncommentedLines = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const shouldUncomment = hasCommentedLines && !hasUncommentedLines
|
||||
|
||||
if (shouldUncomment) {
|
||||
for (let row = start; row <= end; row++) {
|
||||
const match = commentStartRegex.searchSync(this.buffer.lineForRow(row))
|
||||
if (match) {
|
||||
const columnStart = match[1].length
|
||||
const columnEnd = columnStart + match[2].length
|
||||
this.buffer.setTextInRange([[row, columnStart], [row, columnEnd]], '')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let minIndentLevel = Infinity
|
||||
let minBlankIndentLevel = Infinity
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
const indentLevel = this.indentLevelForLine(line)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
if (indentLevel < minIndentLevel) minIndentLevel = indentLevel
|
||||
} else {
|
||||
if (indentLevel < minBlankIndentLevel) minBlankIndentLevel = indentLevel
|
||||
}
|
||||
}
|
||||
minIndentLevel = Number.isFinite(minIndentLevel)
|
||||
? minIndentLevel
|
||||
: Number.isFinite(minBlankIndentLevel)
|
||||
? minBlankIndentLevel
|
||||
: 0
|
||||
|
||||
const tabLength = this.getTabLength()
|
||||
const indentString = ' '.repeat(tabLength * minIndentLevel)
|
||||
for (let row = start; row <= end; row++) {
|
||||
const line = this.buffer.lineForRow(row)
|
||||
if (NON_WHITESPACE_REGEX.test(line)) {
|
||||
const indentColumn = this.columnForIndentLevel(line, minIndentLevel)
|
||||
this.buffer.insert(Point(row, indentColumn), commentStartString)
|
||||
} else {
|
||||
this.buffer.setTextInRange(
|
||||
new Range(new Point(row, 0), new Point(row, Infinity)),
|
||||
indentString + commentStartString
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,24 +507,6 @@ class TokenizedBuffer {
|
||||
return scopes
|
||||
}
|
||||
|
||||
columnForIndentLevel (line, indentLevel, tabLength = this.tabLength) {
|
||||
let column = 0
|
||||
let indentLength = 0
|
||||
const goalIndentLength = indentLevel * tabLength
|
||||
while (indentLength < goalIndentLength) {
|
||||
const char = line[column]
|
||||
if (char === '\t') {
|
||||
indentLength += tabLength - (indentLength % tabLength)
|
||||
} else if (char === ' ') {
|
||||
indentLength++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
column++
|
||||
}
|
||||
return column
|
||||
}
|
||||
|
||||
indentLevelForLine (line, tabLength = this.tabLength) {
|
||||
let indentLength = 0
|
||||
for (let i = 0, {length} = line; i < length; i++) {
|
||||
@ -841,12 +736,6 @@ class TokenizedBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
commentStringsForScopeDescriptor (scopes) {
|
||||
if (this.scopedSettingsDelegate) {
|
||||
return this.scopedSettingsDelegate.getCommentStrings(scopes)
|
||||
}
|
||||
}
|
||||
|
||||
regexForPattern (pattern) {
|
||||
if (pattern) {
|
||||
if (!this.regexesByPattern[pattern]) {
|
||||
|
Loading…
Reference in New Issue
Block a user