diff --git a/README.md b/README.md index c3e9cd1..ce60fa8 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,10 @@ lets = see = what := happens a = a = b = c : d := e ``` +## See it in action + +![atom-alignment](http://papermoon1978.github.io/atom-alignment.gif) + ## License MIT © [Andre Lerche](https://github.com/papermoon1978) diff --git a/lib/aligner.coffee b/lib/aligner.coffee index ab30a64..818c28d 100644 --- a/lib/aligner.coffee +++ b/lib/aligner.coffee @@ -2,12 +2,42 @@ _ = require 'lodash' +class Ignorelist + #public + constructor: (string, regexp) -> + @__ignoreList = [] + if regexp? + while match = regexp.exec(string) + @__ignoreList.push {start:match.index, end:match.index + match[0].length} + + contains: (matcher, idx) => + found = false + _.forEach @__ignoreList, (ignore) -> + if ignore.start <= idx && ignore.end >= idx + matcher.length + found = true + return false + + return found + +class SafeRegExp + #public + constructor: (parts) -> + _.each parts, (part, idx) -> + if part == "|" + parts[idx] = "\\"+part + + @__regex = new RegExp(parts.join("|"), "g") + + exec: (s) => + @__regex.exec(s) + module.exports = class Aligner # Public - constructor: (@editor, @spaceChars, @matcher, @addSpacePostfix) -> + constructor: (@editor, @leftAlignChars, @leftSpaceChars, @rightSpaceChars, @matcher, @ignoreChars) -> @rows = [] @alignments = [] + @ignoreRegexp = new SafeRegExp(@ignoreChars) if @ignoreChars.length > 0 # Private __getRows: => @@ -25,16 +55,17 @@ module.exports = for cursor in cursors row = cursor.getBufferRow() t = @editor.lineTextForBufferRow(row) - l = @__computeLength(t.substring(0,cursor.getBufferColumn())) + v = cursor.getBufferColumn() + l = @__computeLength(t.substring(0, v)) o = text : t length : t.length row : row column : l - virtualColumn: cursor.getBufferColumn() + virtualColumn: v @rows.push (o) - else + rowNums = [] ranges = @editor.getSelectedBufferRanges() for range in ranges rowNums = rowNums.concat(range.getRows()) @@ -56,41 +87,75 @@ module.exports = firstCharIdx = o.text.indexOf(t.charAt(0)) o.text = o.text.substr(0,firstCharIdx) + o.text.substring(firstCharIdx).replace(/\ {2,}/g, ' ') - __getAllIndexes: (string, val, indexes) -> - found = [] - i = 0 - loop - i = string.indexOf(val, i) - if i != -1 && !_.some(indexes, {index:i}) - found.push({found:val,index:i}) + return + return + + __getAllIndexes: (string) => + ignoreList = new Ignorelist string, @ignoreRegexp + allMatcherRegEx = new SafeRegExp(@matcher) if @matcher.length > 0 + allMatcher = [] + if allMatcherRegEx? + while match = allMatcherRegEx.exec(string) + if !ignoreList.contains(match, match.index) + allMatcher.push {matcher: match[0], start:match.index, end:match.index + match[0].length} + + return allMatcher + + __getNextMatcher: (start, matcher, text) => + allMatcher = @__getAllIndexes(text) + + canUseMatcher = (i) -> + found = false + _.forEach allMatcher, (m) -> + if m.start == i && m.end == i + matcher.length && m.matcher == matcher + found = true + return false + + return found + + ret = -1 + idx = text.indexOf matcher, start + while idx >= 0 + if canUseMatcher idx + ret = idx + break + else + start = idx + 1 + + idx = text.indexOf matcher, start - break if i == -1 - i++ - return found + return ret #generate the sequence of alignment characters computed from the first matching line __generateAlignmentList: () => if @mode == "cursor" _.forEach @rows, (o) => part = o.text.substring(o.virtualColumn) - _.forEach @spaceChars, (char) -> + _.forEach @leftSpaceChars, (char) -> idx = part.indexOf(char) if idx == 0 && o.text.charAt(o.virtualColumn) != " " - o.addSpacePrefix = true - o.spaceCharLength = char.length + o.leftSpace = true + o.leftSpaceCharLength = char.length return false + + _.forEach @rightSpaceChars, (char) -> + idx = part.indexOf(char) + if idx == 0 && o.text.charAt(o.virtualColumn)+char.length != " " + o.rightSpace = true + o.rightSpaceCharLength = char.length + return false + return else _.forEach @rows, (o) => - _.forEach @matcher, (possibleMatcher) => - @alignments = @alignments.concat (@__getAllIndexes o.text, possibleMatcher, @alignments) - - if @alignments.length > 0 - return false # exit if we got all alignments characters in the row - else - return true # continue - @alignments = @alignments.sort (a, b) -> a.index - b.index - @alignments = _.pluck @alignments, "found" + newAlignments = @__getAllIndexes(o.text) + + if newAlignments.length > @alignments.length + @alignments = newAlignments.slice() + + @alignments = @alignments.sort (a, b) -> a.start - b.start + @alignments = _.pluck @alignments, "matcher" + console.log("atom-alignment: normal mode -> matcher: #{@alignments}") return __computeLength: (s) => @@ -112,14 +177,15 @@ module.exports = matched = null idx = -1 possibleMatcher = @alignments.shift() - addSpacePrefix = @spaceChars.indexOf(possibleMatcher) > -1 + leftSpace = @leftSpaceChars.indexOf(possibleMatcher) > -1 + rightSpace = @rightSpaceChars.indexOf(possibleMatcher) > -1 @rows.forEach (o) => o.splited = null if !o.done line = o.text - if (line.indexOf(possibleMatcher, o.nextPos) != -1) + idx = @__getNextMatcher(o.nextPos, possibleMatcher, line) + if (idx != -1) matched = possibleMatcher - idx = line.indexOf(matched, o.nextPos) len = matched.length if @mode == "break" idx += len-1 @@ -144,11 +210,13 @@ module.exports = if idx isnt -1 splitString = [line.substring(0,idx), line.substring(idx+next)] + splitString[0] = splitString[0].trimRight() if not leftSpace + splitString[1] = splitString[1].trimLeft() if not rightSpace o.splited = splitString l = @__computeLength(splitString[0]) if max <= l max = l - max++ if l > 0 && addSpacePrefix && splitString[0].charAt(splitString[0].length-1) != " " + max++ if l > 0 && leftSpace && splitString[0].charAt(splitString[0].length-1) != " " found = false _.forEach @alignments, (nextPossibleMatcher) -> @@ -168,13 +236,22 @@ module.exports = splitString = o.splited diff = max - @__computeLength(splitString[0]) if diff > 0 - splitString[0] = splitString[0] + Array(diff).join(' ') - - splitString[1] = " "+splitString[1].trim() if @addSpacePostfix && addSpacePrefix + if matched in @leftAlignChars + splitString[1] = Array(diff).join(' ') + splitString[1].trim() + splitString[0] = splitString[0].trim() + else + splitString[0] = splitString[0].trim() + Array(diff).join(' ') + splitString[1] = splitString[1].trim() + + if leftSpace + splitString[0] = splitString[0] + ' ' + if rightSpace + splitString[1] = ' ' + splitString[1] if @mode == "break" _.forEach splitString, (s, i) -> splitString[i] = s.trim() + return o.text = splitString.join("\n") else @@ -188,7 +265,7 @@ module.exports = if max <= o.column max = o.column part = o.text.substring(0,o.virtualColumn) - max++ if part.length > 0 && o.addSpacePrefix && part.charAt(part.length-1) != " " + max++ if part.length > 0 && o.leftSpace && part.charAt(part.length-1) != " " return max++ @@ -200,10 +277,11 @@ module.exports = if diff > 0 splitString[0] = splitString[0] + Array(diff).join(' ') - o.spaceCharLength ?= 0 - splitString[1] = splitString[1].substring(0, o.spaceCharLength) + splitString[1].substr(o.spaceCharLength).trim() - if @addSpacePostfix && o.addSpacePrefix - splitString[1] = splitString[1].substring(0, o.spaceCharLength) + " " +splitString[1].substr(o.spaceCharLength) + o.leftSpaceCharLength ?= 0 + o.rightSpaceCharLength ?= 0 + splitString[1] = splitString[1].substring(0, o.leftSpaceCharLength) + splitString[1].substr(o.leftSpaceCharLength).trim() + if o.rightSpace + splitString[1] = splitString[1].substring(0, o.rightSpaceCharLength) + " " +splitString[1].substr(o.rightSpaceCharLength) o.text = splitString.join("") return @@ -225,3 +303,4 @@ module.exports = @rows.forEach (o) => @editor.setTextInBufferRange([[o.row, 0],[o.row, o.length]], o.text) + return diff --git a/lib/atom-alignment.coffee b/lib/atom-alignment.coffee index 2bbd06d..04f2ceb 100644 --- a/lib/atom-alignment.coffee +++ b/lib/atom-alignment.coffee @@ -2,48 +2,57 @@ Aligner = require './aligner' module.exports = config: - alignmentSpaceChars: + alignBy: type: 'array' - default: ['=>', ':=', '='] + default: ['=>', ':=', ':', '='] + items: + type: "string" + description: "consider the order, the left most matching separator is taken to compute the alignment" + order: 1 + leftAlignChars: + type: 'array' + default: [':'] items: type: "string" - description: "insert space in front of the character (a=1 > a =1)" + description: "when aligning, keep these characters aligned to the left" order: 2 - alignBy: + leftSpaceChars: type: 'array' - default: ['=>', ':=', ':', '='] + default: ['=>', ':=', '='] items: type: "string" - description: "consider the order, the left most matching value is taken to compute the alignment" - order: 1 - addSpacePostfix: - type: 'boolean' - default: false - description: "insert space after the matching character (a=1 > a= 1) if character is part of the 'alignment space chars'" + description: "insert space left of the separator (a=1 > a =1)" order: 3 + rightSpaceChars: + type: 'array' + default: ['=>', ':=', '=', ":"] + items: + type: "string" + description: "insert space right of the separator (a=1 > a= 1)" + order: 4 + ignoreChars: + type: 'array' + default: ['===', '!==', '==', '!=', '>=', '<=', '::'] + items: + type: "string" + description: "ignore as separator" + order: 5 activate: (state) -> atom.commands.add 'atom-workspace', 'atom-alignment:align': -> - editor = atom.workspace.getActivePaneItem() - alignLines editor + alignLines false 'atom-alignment:alignMultiple': -> - editor = atom.workspace.getActivePaneItem() - alignLinesMultiple editor - -alignLines = (editor) -> - spaceChars = atom.config.get 'atom-alignment.alignmentSpaceChars' - matcher = atom.config.get 'atom-alignment.alignBy' - addSpacePostfix = atom.config.get 'atom-alignment.addSpacePostfix' - a = new Aligner(editor, spaceChars, matcher, addSpacePostfix) - a.align(false) - return + alignLines true -alignLinesMultiple = (editor) -> - spaceChars = atom.config.get 'atom-alignment.alignmentSpaceChars' - matcher = atom.config.get 'atom-alignment.alignBy' - addSpacePostfix = atom.config.get 'atom-alignment.addSpacePostfix' - a = new Aligner(editor, spaceChars, matcher, addSpacePostfix) - a.align(true) +alignLines = (multiple) -> + editor = atom.workspace.getActiveTextEditor() + leftAlignChars = atom.config.get('atom-alignment.leftAlignChars', scope: editor.getRootScopeDescriptor()) + leftSpaceChars = atom.config.get('atom-alignment.leftSpaceChars', scope: editor.getRootScopeDescriptor()) + rightSpaceChars = atom.config.get('atom-alignment.rightSpaceChars', scope: editor.getRootScopeDescriptor()) + matcher = atom.config.get('atom-alignment.alignBy', scope: editor.getRootScopeDescriptor()) + ignoreChars = atom.config.get('atom-alignment.ignoreChars', scope: editor.getRootScopeDescriptor()) + aligner = new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars) + aligner.align(multiple) return diff --git a/menus/atom-alignment.cson b/menus/atom-alignment.cson index d1bd1fd..49fe324 100644 --- a/menus/atom-alignment.cson +++ b/menus/atom-alignment.cson @@ -1,12 +1,9 @@ # See https://atom.io/docs/latest/creating-a-package#menus for more details -'context-menu': - '.overlayer':[{'Enable atom-alignment': 'atom-alignment:align'}] - 'menu': [ { 'label': 'Packages' 'submenu': [ - 'label': 'atom-alignment' + 'label': 'Atom Alignment' 'submenu': [ { 'label': 'Align', 'command': 'atom-alignment:align' }, { 'label': 'Align Multiple', 'command': 'atom-alignment:alignMultiple' } diff --git a/package.json b/package.json index 218fe3a..603487f 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "atom-alignment", "main": "./lib/atom-alignment", - "version": "0.12.1", + "version": "0.13.0", "private": true, "description": "A simple key-binding for aligning multi-line and multiple selections in Atom (Based on the sublime text plugin)", - "repository": "https://github.com/Freyskeyd/atom-alignment", + "repository": "https://github.com/crshd/atom-alignment", "license": "MIT", "engines": { "atom": ">0.50.0" diff --git a/spec/atom-alignment-spec.coffee b/spec/atom-alignment-spec.coffee index 5fe33e6..356c76e 100644 --- a/spec/atom-alignment-spec.coffee +++ b/spec/atom-alignment-spec.coffee @@ -1,29 +1,246 @@ -AtomAlignment = require '../lib/atom-alignment' +Aligner = require '../lib/aligner.coffee' # Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. # # To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` # or `fdescribe`). Remove the `f` to unfocus the block. -describe "AtomAlignment", -> - activationPromise = null - - beforeEach -> - atom.workspaceView = new WorkspaceView - activationPromise = atom.packages.activatePackage('atomAlignment') - - # describe "when the atom-alignment:align event is triggered", -> - # it "attaches and then detaches the view", -> - # expect(atom.workspaceView.find('.atom-alignment')).not.toExist() - # - # # This is an activation event, triggering it will cause the package to be - # # activated. - # atom.workspaceView.trigger 'atom-alignment:toggle' - # - # waitsForPromise -> - # activationPromise - # - # runs -> - # expect(atom.workspaceView.find('.atom-alignment')).toExist() - # atom.workspaceView.trigger 'atom-alignment:toggle' - # expect(atom.workspaceView.find('.atom-alignment')).not.toExist() +describe "atom-alignment", -> + leftAlignChars = [':'] + leftSpaceChars = ['=>', ':=', '='] + rightSpaceChars = ['=>', ':=', '=', ':'] + matcher = ['=>', ':=', ':', '='] + ignoreChars = ['===', '==', '!==', '!=', '::'] + editor = null + + align = (callback) -> + runs(callback) + + beforeEach -> + waitsForPromise -> + atom.workspace.open() + + runs -> + editor = atom.workspace.getActiveTextEditor() + editorView = atom.views.getView(editor) + return + + describe "when aligner is called on one line only", -> + it "has to break the line", -> + editor.setText "var a = 1; var b = 2;" + editor.setCursorScreenPosition([1, 1]) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var b = 2;" + + describe "when aligner is called on multiple lines with only one matcher", -> + it "should align correctly", -> + editor.setText "var a = 1;\nvar bbb = 2;" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb = 2;" + + describe "when aligner is called on multiple lines with different matchers", -> + it "should align correctly", -> + editor.setText "var a = 1; b:2; c:3;d=4\nvar bbb : 2;" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb: 2;" + + describe "when aligner is called on lines with multiple char matchers", -> + it "should align correctly", -> + editor.setText "var a => 1; b = 2;\nvar bbb => 2;" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb => 2;" + + describe "when aligner is called on lines with ignore chars", -> + it "should align correctly", -> + editor.setText "a::a::a:1\nbbb::bbb=ccc:1" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a::a::a: 1" + + describe "when there is everything put together (1)", -> + it "should align correctly", -> + editor.setText "a::a=b=c=>d\naaaaa=b=>a\nfffffffffff=ffffffff=>h" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a::a = b = c => d" + expect(editor.lineTextForBufferRow 1).toEqual "aaaaa = b => a" + expect(editor.lineTextForBufferRow 2).toEqual "fffffffffff = ffffffff => h" + + describe "when there is everything put together (2)", -> + it "should align correctly", -> + editor.setText "a=b=>c\naa=bb=>cc\nb=>c=a\nbb=>cc=aa" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = b => c" + expect(editor.lineTextForBufferRow 1).toEqual "aa = bb => cc" + expect(editor.lineTextForBufferRow 2).toEqual "b=>c = a" + expect(editor.lineTextForBufferRow 3).toEqual "bb=>cc = aa" + + describe "when indentation is mixed with spaces and tabs", -> + it "should align correctly", -> + editor.setText "aa = 4\na = 1\nb = 2\nc::3=4" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "aa = 4" + expect(editor.lineTextForBufferRow(1).replace(/\t/g,"t")).toEqual "at = 1" #specs cannot handle tabs ... wtf? + expect(editor.lineTextForBufferRow 2).toEqual "b = 2" + expect(editor.lineTextForBufferRow 3).toEqual "c::3 = 4" + + describe "when matcher with left and right space prefix are mixed", -> + it "should align correctly", -> + editor.setText "a=1a : 1\nb = 2c::ab :2" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = 1a : 1" + expect(editor.lineTextForBufferRow 1).toEqual "b = 2c::ab: 2" + + describe "when there are some matcher to ignore", -> + it "should align correctly", -> + editor.setText "a = a = b => c\na => a = b => c" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = a = b => c" + expect(editor.lineTextForBufferRow 1).toEqual "a => a = b => c" + + describe "when matcher is the first character on the line", -> + it "should align correctly", -> + editor.setText "a=a\n=c" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = a" + expect(editor.lineTextForBufferRow 1).toEqual " = c" + + describe "when there is nothing to do", -> + it "should keep the intendation and remove duplicate blanks", -> + editor.setText " a::a::b a\nb::b::c" + editor.selectAll() + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual " a::a::b a" + expect(editor.lineTextForBufferRow 1).toEqual "b::b::c" + + describe "when there are multiple separators, but we only want to align the first one", -> + it "should align the first one, but in any case remove duplicate blanks", -> + editor.setText "a=1 b=2\na =2 b =1" + editor.selectAll() + new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(false) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = 1 b=2" + expect(editor.lineTextForBufferRow 1).toEqual "a = 2 b =1" + + leftSpaceChars2 = ['=', ':'] + rightSpaceChars2 = ['=', ':'] + matcher2 = [':', '=', '|'] + ignoreChars2 = ['===', '==', '!==', '!='] + + describe "run 2 when aligner is called on one line only", -> + it "has to break the line", -> + editor.setText "var a = 1; var b = 2;" + editor.setCursorScreenPosition([1, 1]) + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var b = 2;" + + describe "run 2 when aligner is called on multiple lines with only one matcher", -> + it "should align correctly", -> + editor.setText "var a = 1;\nvar bbb = 2;" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb = 2;" + + describe "run 2 when aligner is called on multiple lines with different matchers", -> + it "should align correctly", -> + editor.setText "var a = 1; b:2; c:3;d=4\nvar bbb : 2;" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb : 2;" + + describe "run 2 when aligner is called on lines with multiple char matchers", -> + it "should align correctly", -> + editor.setText "var a => 1; b = 2;\nvar bbb => 2;" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 1).toEqual "var bbb = > 2;" + + describe "run 2 when aligner is called on lines with ignore chars", -> + it "should align correctly", -> + editor.setText "a==a::a:1\nbbb::bbb=ccc:1" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a==a : : a : 1" + + describe "run 2 when there is everything put together (1)", -> + it "should align correctly", -> + editor.setText "a::a=b=c=>d\naaaaa=b=>a\nfffffffffff=ffffffff=>h" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a : : a = b = c = >d" + expect(editor.lineTextForBufferRow 1).toEqual "aaaaa = b = >a" + expect(editor.lineTextForBufferRow 2).toEqual "fffffffffff = ffffffff = >h" + + describe "run 2 when there is everything put together (2)", -> + it "should align correctly", -> + editor.setText "a=b=>c\naa=bb=>cc\nb=>c=a\nbb=>cc=aa" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = b = >c" + expect(editor.lineTextForBufferRow 1).toEqual "aa = bb = >cc" + expect(editor.lineTextForBufferRow 2).toEqual "b = >c = a" + expect(editor.lineTextForBufferRow 3).toEqual "bb = >cc = aa" + + describe "run 2 when indentation is mixed with spaces and tabs", -> + it "should align correctly", -> + editor.setText "aa = 4\na = 1\nb = 2\nc::3=4" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "aa = 4" + expect(editor.lineTextForBufferRow(1).replace(/\t/g,"t")).toEqual "at = 1" #specs cannot handle tabs ... wtf? + expect(editor.lineTextForBufferRow 2).toEqual "b = 2" + expect(editor.lineTextForBufferRow 3).toEqual "c : : 3 = 4" + + describe "run 2 when matcher with left and right space prefix are mixed", -> + it "should align correctly", -> + editor.setText "a=1a : 1\nb = 2c::ab :2" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a = 1a : 1" + expect(editor.lineTextForBufferRow 1).toEqual "b = 2c : : ab : 2" + + describe "run 2 when there are some matcher to ignore", -> + it "should align correctly", -> + editor.setText "a== = a = b => c\na => ==a = b => c" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a== = a = b = > c" + expect(editor.lineTextForBufferRow 1).toEqual "a = > ==a = b = > c" + + describe "when character | (pipe) should be aligned", -> + it "should align correctly", -> + editor.setText "a|1|a\naa|1|aa" + editor.selectAll() + new Aligner(editor, leftSpaceChars2, rightSpaceChars2, matcher2, ignoreChars2).align(true) + align -> + expect(editor.lineTextForBufferRow 0).toEqual "a |1|a"