From 604c3f553b663584c30335e181e1ebcb9be8b410 Mon Sep 17 00:00:00 2001 From: papermoon1978 Date: Mon, 6 Jul 2015 13:24:58 +0200 Subject: [PATCH 01/11] improved specs --- spec/atom-alignment-spec.coffee | 262 +++++++++++++++++++++++++++++--- 1 file changed, 239 insertions(+), 23 deletions(-) diff --git a/spec/atom-alignment-spec.coffee b/spec/atom-alignment-spec.coffee index 5fe33e6..091da62 100644 --- a/spec/atom-alignment-spec.coffee +++ b/spec/atom-alignment-spec.coffee @@ -1,29 +1,245 @@ -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", -> + 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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" From 5909c6a705a592cce9c3f03dfe86903599ca2b9b Mon Sep 17 00:00:00 2001 From: papermoon1978 Date: Mon, 6 Jul 2015 13:26:03 +0200 Subject: [PATCH 02/11] added new separator options --- README.md | 4 ++ lib/aligner.coffee | 143 ++++++++++++++++++++++++++++---------- lib/atom-alignment.coffee | 57 +++++++-------- 3 files changed, 140 insertions(+), 64 deletions(-) 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..f0a6aa8 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, @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 - break if i == -1 - i++ - return found + idx = text.indexOf matcher, start + + 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) -> @@ -170,11 +238,12 @@ module.exports = if diff > 0 splitString[0] = splitString[0] + Array(diff).join(' ') - splitString[1] = " "+splitString[1].trim() if @addSpacePostfix && addSpacePrefix + splitString[1] = " "+splitString[1].trim() if rightSpace if @mode == "break" _.forEach splitString, (s, i) -> splitString[i] = s.trim() + return o.text = splitString.join("\n") else @@ -188,7 +257,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 +269,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 +295,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..b40df82 100644 --- a/lib/atom-alignment.coffee +++ b/lib/atom-alignment.coffee @@ -2,48 +2,49 @@ Aligner = require './aligner' module.exports = config: - alignmentSpaceChars: + alignBy: + type: 'array' + default: ['=>', ':=', ':', '='] + items: + type: "string" + description: "consider the order, the left most matching separator is taken to compute the alignment" + order: 1 + leftSpaceChars: type: 'array' default: ['=>', ':=', '='] items: type: "string" - description: "insert space in front of the character (a=1 > a =1)" + description: "insert space left of the separator (a=1 > a =1)" order: 2 - alignBy: + rightSpaceChars: 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 right of the separator (a=1 > a= 1)" order: 3 + ignoreChars: + type: 'array' + default: ['===', '!==', '==', '!=', '>=', '<=', '::'] + items: + type: "string" + description: "ignore as separator" + order: 4 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() + leftSpaceChars = atom.config.get 'atom-alignment.leftSpaceChars' + rightSpaceChars = atom.config.get 'atom-alignment.rightSpaceChars' + matcher = atom.config.get 'atom-alignment.alignBy' + ignoreChars = atom.config.get 'atom-alignment.ignoreChars' + aligner = new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars) + aligner.align(multiple) return From 297c7570b6853eda98052115602cdb7b106f7af4 Mon Sep 17 00:00:00 2001 From: papermoon1978 Date: Mon, 6 Jul 2015 13:26:43 +0200 Subject: [PATCH 03/11] removed context menu | fixes #34 --- menus/atom-alignment.cson | 4 ---- 1 file changed, 4 deletions(-) diff --git a/menus/atom-alignment.cson b/menus/atom-alignment.cson index 76ac06d..2466303 100644 --- a/menus/atom-alignment.cson +++ b/menus/atom-alignment.cson @@ -1,8 +1,4 @@ # 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' From d37b1ba76e8546bf99e13b22baecdb8a4ab10847 Mon Sep 17 00:00:00 2001 From: papermoon1978 Date: Mon, 6 Jul 2015 13:28:15 +0200 Subject: [PATCH 04/11] renamed menu title | fixes #37 --- menus/atom-alignment.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menus/atom-alignment.cson b/menus/atom-alignment.cson index 2466303..49fe324 100644 --- a/menus/atom-alignment.cson +++ b/menus/atom-alignment.cson @@ -3,7 +3,7 @@ { 'label': 'Packages' 'submenu': [ - 'label': 'atom-alignment' + 'label': 'Atom Alignment' 'submenu': [ { 'label': 'Align', 'command': 'atom-alignment:align' }, { 'label': 'Align Multiple', 'command': 'atom-alignment:alignMultiple' } From 65d7c29857aeda0649e678f86ea74c6338c0642e Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Fri, 2 Oct 2015 16:46:17 +0200 Subject: [PATCH 05/11] Add scope-specific settings. .getRootScopeDescriptor() --- lib/atom-alignment.coffee | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/atom-alignment.coffee b/lib/atom-alignment.coffee index 2bbd06d..a512b4f 100644 --- a/lib/atom-alignment.coffee +++ b/lib/atom-alignment.coffee @@ -33,17 +33,17 @@ module.exports = 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' + spaceChars = atom.config.get('atom-alignment.alignmentSpaceChars', scope: editor.getRootScopeDescriptor()) + matcher = atom.config.get('atom-alignment.alignBy', scope: editor.getRootScopeDescriptor()) + addSpacePostfix = atom.config.get('atom-alignment.addSpacePostfix', scope: editor.getRootScopeDescriptor()) a = new Aligner(editor, spaceChars, matcher, addSpacePostfix) a.align(false) return alignLinesMultiple = (editor) -> - spaceChars = atom.config.get 'atom-alignment.alignmentSpaceChars' - matcher = atom.config.get 'atom-alignment.alignBy' - addSpacePostfix = atom.config.get 'atom-alignment.addSpacePostfix' + spaceChars = atom.config.get('atom-alignment.alignmentSpaceChars', scope: editor.getRootScopeDescriptor()) + matcher = atom.config.get('atom-alignment.alignBy', scope: editor.getRootScopeDescriptor()) + addSpacePostfix = atom.config.get('atom-alignment.addSpacePostfix', scope: editor.getRootScopeDescriptor()) a = new Aligner(editor, spaceChars, matcher, addSpacePostfix) a.align(true) return From 8eabd13ca943d962b25254c166cb2e009f6e5639 Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 15:37:52 +0100 Subject: [PATCH 06/11] change repository URL --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 218fe3a..69570f8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.12.1", "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" From c0e9e48b8c5d236a62041c842c30f9340ca9aa57 Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 15:38:58 +0100 Subject: [PATCH 07/11] Add setting to add padding to the right of the matched characters --- lib/aligner.coffee | 12 +++++++++--- lib/atom-alignment.coffee | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/aligner.coffee b/lib/aligner.coffee index f0a6aa8..4ffe70f 100644 --- a/lib/aligner.coffee +++ b/lib/aligner.coffee @@ -34,7 +34,7 @@ class SafeRegExp module.exports = class Aligner # Public - constructor: (@editor, @leftSpaceChars, @rightSpaceChars, @matcher, @ignoreChars) -> + constructor: (@editor, @leftAlignChars, @leftSpaceChars, @rightSpaceChars, @matcher, @ignoreChars) -> @rows = [] @alignments = [] @ignoreRegexp = new SafeRegExp(@ignoreChars) if @ignoreChars.length > 0 @@ -236,9 +236,15 @@ module.exports = splitString = o.splited diff = max - @__computeLength(splitString[0]) if diff > 0 - splitString[0] = splitString[0] + Array(diff).join(' ') + if matched in @leftAlignChars + splitString[1] = Array(diff).join(' ') + splitString[1] + else + splitString[0] = splitString[0] + Array(diff).join(' ') - splitString[1] = " "+splitString[1].trim() if rightSpace + if matched in @leftAlignChars + splitString[0] = splitString[0].trim()+" " if leftSpace + else + splitString[1] = " "+splitString[1].trim() if rightSpace if @mode == "break" _.forEach splitString, (s, i) -> diff --git a/lib/atom-alignment.coffee b/lib/atom-alignment.coffee index 4a38d53..04f2ceb 100644 --- a/lib/atom-alignment.coffee +++ b/lib/atom-alignment.coffee @@ -9,27 +9,34 @@ module.exports = 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: "when aligning, keep these characters aligned to the left" + order: 2 leftSpaceChars: type: 'array' default: ['=>', ':=', '='] items: type: "string" description: "insert space left of the separator (a=1 > a =1)" - order: 2 + order: 3 rightSpaceChars: type: 'array' default: ['=>', ':=', '=', ":"] items: type: "string" description: "insert space right of the separator (a=1 > a= 1)" - order: 3 + order: 4 ignoreChars: type: 'array' default: ['===', '!==', '==', '!=', '>=', '<=', '::'] items: type: "string" description: "ignore as separator" - order: 4 + order: 5 activate: (state) -> atom.commands.add 'atom-workspace', @@ -41,10 +48,11 @@ module.exports = 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, leftSpaceChars, rightSpaceChars, matcher, ignoreChars) + aligner = new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars) aligner.align(multiple) return From e36d6c2223dcc3818d759b19011660d986faa5ad Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 15:53:43 +0100 Subject: [PATCH 08/11] fix trimming --- lib/aligner.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/aligner.coffee b/lib/aligner.coffee index 4ffe70f..09524a9 100644 --- a/lib/aligner.coffee +++ b/lib/aligner.coffee @@ -241,10 +241,8 @@ module.exports = else splitString[0] = splitString[0] + Array(diff).join(' ') - if matched in @leftAlignChars - splitString[0] = splitString[0].trim()+" " if leftSpace - else - splitString[1] = " "+splitString[1].trim() if rightSpace + splitString[0] = splitString[0].trimRight()+" " if leftSpace + splitString[1] = " "+splitString[1].trim() if rightSpace if @mode == "break" _.forEach splitString, (s, i) -> From 83852ec7a87783bd2fa98ecc1bd08fad7bd0193c Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 15:55:01 +0100 Subject: [PATCH 09/11] 0.13.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69570f8..603487f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "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/crshd/atom-alignment", From f789deb32d2ab2b4f2e9abd170d7701b86778890 Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 17:04:51 +0100 Subject: [PATCH 10/11] fix trimming. again. --- lib/aligner.coffee | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/aligner.coffee b/lib/aligner.coffee index 09524a9..4edcca7 100644 --- a/lib/aligner.coffee +++ b/lib/aligner.coffee @@ -237,12 +237,16 @@ module.exports = diff = max - @__computeLength(splitString[0]) if diff > 0 if matched in @leftAlignChars - splitString[1] = Array(diff).join(' ') + splitString[1] + splitString[1] = Array(diff).join(' ') + splitString[1].trim() + splitString[0] = splitString[0].trimRight() else - splitString[0] = splitString[0] + Array(diff).join(' ') + splitString[0] = splitString[0].trim() + Array(diff).join(' ') + splitString[1] = splitString[1].trimLeft() - splitString[0] = splitString[0].trimRight()+" " if leftSpace - splitString[1] = " "+splitString[1].trim() if rightSpace + if leftSpace + splitString[0] = splitString[0] + ' ' + if rightSpace + splitString[1] = ' ' + splitString[1] if @mode == "break" _.forEach splitString, (s, i) -> From c2a0edb9d6e48fe8a19d3341906eaec040e13646 Mon Sep 17 00:00:00 2001 From: Christian Brassat Date: Mon, 4 Jan 2016 17:16:50 +0100 Subject: [PATCH 11/11] testing --- lib/aligner.coffee | 4 ++-- spec/atom-alignment-spec.coffee | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/aligner.coffee b/lib/aligner.coffee index 4edcca7..818c28d 100644 --- a/lib/aligner.coffee +++ b/lib/aligner.coffee @@ -238,10 +238,10 @@ module.exports = if diff > 0 if matched in @leftAlignChars splitString[1] = Array(diff).join(' ') + splitString[1].trim() - splitString[0] = splitString[0].trimRight() + splitString[0] = splitString[0].trim() else splitString[0] = splitString[0].trim() + Array(diff).join(' ') - splitString[1] = splitString[1].trimLeft() + splitString[1] = splitString[1].trim() if leftSpace splitString[0] = splitString[0] + ' ' diff --git a/spec/atom-alignment-spec.coffee b/spec/atom-alignment-spec.coffee index 091da62..356c76e 100644 --- a/spec/atom-alignment-spec.coffee +++ b/spec/atom-alignment-spec.coffee @@ -6,6 +6,7 @@ Aligner = require '../lib/aligner.coffee' # or `fdescribe`). Remove the `f` to unfocus the block. describe "atom-alignment", -> + leftAlignChars = [':'] leftSpaceChars = ['=>', ':=', '='] rightSpaceChars = ['=>', ':=', '=', ':'] matcher = ['=>', ':=', ':', '='] @@ -28,7 +29,7 @@ describe "atom-alignment", -> it "has to break the line", -> editor.setText "var a = 1; var b = 2;" editor.setCursorScreenPosition([1, 1]) - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> expect(editor.lineTextForBufferRow 1).toEqual "var b = 2;" @@ -36,7 +37,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "var a = 1;\nvar bbb = 2;" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> expect(editor.lineTextForBufferRow 1).toEqual "var bbb = 2;" @@ -44,15 +45,15 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "var a = 1; b:2; c:3;d=4\nvar bbb : 2;" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> - expect(editor.lineTextForBufferRow 1).toEqual "var bbb : 2;" + 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, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> expect(editor.lineTextForBufferRow 1).toEqual "var bbb => 2;" @@ -60,15 +61,15 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "a::a::a:1\nbbb::bbb=ccc:1" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> - expect(editor.lineTextForBufferRow 0).toEqual "a::a::a : 1" + 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, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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" @@ -78,7 +79,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "a=b=>c\naa=bb=>cc\nb=>c=a\nbb=>cc=aa" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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" @@ -89,7 +90,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "aa = 4\na = 1\nb = 2\nc::3=4" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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? @@ -100,7 +101,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "a=1a : 1\nb = 2c::ab :2" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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" @@ -109,7 +110,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "a = a = b => c\na => a = b => c" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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" @@ -118,7 +119,7 @@ describe "atom-alignment", -> it "should align correctly", -> editor.setText "a=a\n=c" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + new Aligner(editor, leftAlignChars, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) align -> expect(editor.lineTextForBufferRow 0).toEqual "a = a" expect(editor.lineTextForBufferRow 1).toEqual " = c" @@ -127,7 +128,7 @@ describe "atom-alignment", -> it "should keep the intendation and remove duplicate blanks", -> editor.setText " a::a::b a\nb::b::c" editor.selectAll() - new Aligner(editor, leftSpaceChars, rightSpaceChars, matcher, ignoreChars).align(true) + 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"