├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── keymaps └── sequential-number.cson ├── lib ├── sequential-number-view.coffee ├── sequential-number.coffee └── template-helper.coffee ├── menus └── sequential-number.cson ├── package.json └── spec └── sequential-number-spec.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | notifications: 4 | email: 5 | on_success: never 6 | on_failure: change 7 | 8 | script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh' 9 | 10 | branches: 11 | only: 12 | - master -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.5.0 - Support alphabet radix 2 | 3 | * Support alphabet radix option. Idea from @flyinbutrs, thanks. 4 | 5 | 6 | ## 0.4.0 - Add `radix` option 7 | 8 | * Add radix option. Very nice idea from @flyinbutrs, thanks. 9 | 10 | 11 | ## 0.3.0 - Replacement of selected text 12 | 13 | * When inserting a sequence number, modified to replace the text that was selected. 14 | 15 | 16 | ## 0.2.0 - Add real time simulator 17 | 18 | * Added a real-time simulator in the input panel. 19 | * Fixed a bug of the calculated value. 20 | * Changed the UI of the input panel. 21 | * Modified to count the position of the cursor from the top. 22 | 23 | 24 | ## 0.1.0 - First Release 25 | 26 | * Every feature added 27 | 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 tsuyoshiwada 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sequential-number 2 | ================= 3 | 4 | [![Build Status](http://img.shields.io/travis/tsuyoshiwada/sequential-number.svg?style=flat-square)](https://travis-ci.org/tsuyoshiwada/sequential-number) 5 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/tsuyoshiwada/sequential-number/master/LICENSE) 6 | 7 | An Atom package, to inputs sequential numbers across multiple cursors. 8 | 9 | ![screenshot](https://raw.githubusercontent.com/tsuyoshiwada/sequential-number/images/screenshot.gif) 10 | 11 | 12 | 13 | ## INSTALLATION 14 | 15 | Search in the `sequential-number` from Install Packages. 16 | Please restart as necessary After the installation. 17 | 18 | 19 | ## USAGE 20 | 21 | 22 | ### Keymaps (Linux, Win, OS X) 23 | 24 | ctrl + alt + 0 => Open the input panel ! 25 | 26 | 27 | ### Syntax Rules 28 | 29 | ``` 30 | : : 31 | ``` 32 | 33 | | Key | Default | Definition | 34 | | :------------------------------------ | :------ | :---------------------------------------------------------------------------------------------------------------------------------------------- | 35 | | **start** | `""` | It specifies the number that you start typing an integer. | 36 | | **operator** (optinal) | `+` | It specifies the generation rules of consecutive numbers in the `+` or `-`. The sign of the increment(`++`) and decrement(`--`) also available. | 37 | | **step** (optinal) | `1` | It specifies the integer to be added or subtracted. | 38 | | **digit** (optinal) | `0` | It specifies of the number of digits in the integer. | 39 | | **radix** (optinal) | `10` | It specifies an integer between 2 and 36 that represents radix. Or increment alphabetically by `"a"` or `"A"`. | 40 | 41 | 42 | 43 | #### Examples 44 | 45 | The following sample the cursor length is `5`. 46 | 47 | ``` 48 | # Input 49 | => 1 50 | => 1++ 51 | => 1 + 1 52 | 53 | # Output 54 | 1 55 | 2 56 | 3 57 | 4 58 | 5 59 | ``` 60 | 61 | ``` 62 | # Input 63 | => 10 + 2 64 | 65 | # Output 66 | 10 67 | 12 68 | 14 69 | 16 70 | 18 71 | ``` 72 | 73 | ``` 74 | # Input 75 | => 0027 + 3 76 | 77 | # Output 78 | 0027 79 | 0030 80 | 0033 81 | 0036 82 | 0039 83 | ``` 84 | 85 | ``` 86 | # Input 87 | => 010 - 1 88 | => 010-- 89 | 90 | # Output 91 | 010 92 | 009 93 | 008 94 | 007 95 | 006 96 | ``` 97 | 98 | ``` 99 | # Input 100 | => -10 + 1 : 2 101 | 102 | # Output 103 | -10 104 | -09 105 | -08 106 | -07 107 | -06 108 | ``` 109 | 110 | ``` 111 | # Input 112 | => 0ff + 14 : 3 : 16 113 | 114 | # Output 115 | 0ff 116 | 10d 117 | 11b 118 | 129 119 | 137 120 | ``` 121 | 122 | ``` 123 | # Input 124 | => 0AB239 + 2 : 6 : 16 125 | 126 | # Output 127 | 0AB239 128 | 0AB23B 129 | 0AB23D 130 | 0AB23F 131 | 0AB241 132 | ``` 133 | 134 | ``` 135 | # Input 136 | => a + 2 : 1 : a 137 | 138 | # Output 139 | a 140 | c 141 | e 142 | g 143 | i 144 | ``` 145 | 146 | ``` 147 | # Input 148 | => c + 20 : 3 : a 149 | 150 | # Output 151 | aac 152 | aaw 153 | aaq 154 | abk 155 | ace 156 | ``` 157 | 158 | 159 | 160 | ## CUSTOMIZING KEYMAP 161 | 162 | May be overriden for your favorite keystroke in your `keymap.cson`. 163 | 164 | ```coffeescript 165 | # Open input panel 166 | 'atom-text-editor': 167 | 'ctrl-alt-0': 'sequential-number:open' 168 | 169 | # Close input panel 170 | '.sequential-number atom-text-editor': 171 | 'escape': 'sequential-number:close' 172 | 'ctrl-c': 'sequential-number:close' 173 | ``` 174 | 175 | 176 | 177 | ## AUTHOR 178 | [tsuyoshiwada](https://github.com/tsuyoshiwada) 179 | 180 | 181 | 182 | --- 183 | 184 | 185 | 186 | Bugs, feature requests and comments are more than welcome in the [issues](https://github.com/tsuyoshiwada/sequential-number/issues) 187 | -------------------------------------------------------------------------------- /keymaps/sequential-number.cson: -------------------------------------------------------------------------------- 1 | 'atom-text-editor': 2 | 'ctrl-alt-0': 'sequential-number:open' 3 | 4 | '.sequential-number atom-text-editor': 5 | 'escape': 'sequential-number:close' 6 | 'ctrl-c': 'sequential-number:close' -------------------------------------------------------------------------------- /lib/sequential-number-view.coffee: -------------------------------------------------------------------------------- 1 | {Emitter} = require "event-kit" 2 | TemplateHelper = require "./template-helper" 3 | 4 | ENABLE_ENTER_KEY_DELAY = 250 5 | 6 | modalTemplate = """ 7 |
8 | 9 |
10 |
11 | 12 | 13 |
14 |
15 |
16 | """ 17 | 18 | module.exports = 19 | class SequentialNumberView extends Emitter 20 | constructor: (serializedState) -> 21 | super() 22 | 23 | @modalTemplate = TemplateHelper.create modalTemplate 24 | 25 | @element = document.createElement "div" 26 | @element.classList.add "sequential-number" 27 | @element.appendChild TemplateHelper.render @modalTemplate 28 | 29 | @textEditor = @element.querySelector "atom-text-editor" 30 | @simulator = @element.querySelector "#sequential-number-simulator" 31 | @modalPanel = atom.workspace.addModalPanel item: @element, visible: false 32 | 33 | @handleBlur = @handleBlur.bind this 34 | @handleKeyup = @handleKeyup.bind this 35 | 36 | serialize: -> 37 | 38 | bindEvents: -> 39 | @isEnableEnterKey = false 40 | @isEnableEnterKeyTimer = setTimeout => 41 | @isEnableEnterKey = true 42 | , ENABLE_ENTER_KEY_DELAY 43 | 44 | @textEditor.addEventListener "blur", @handleBlur, false 45 | @textEditor.addEventListener "keyup", @handleKeyup, false 46 | 47 | unbindEvents: -> 48 | @isEnableEnterKey = false 49 | clearTimeout @isEnableEnterKeyTimer 50 | @isEnableEnterKeyTimer = null 51 | 52 | @textEditor.removeEventListener "blur", @handleBlur, false 53 | @textEditor.removeEventListener "keyup", @handleKeyup, false 54 | 55 | handleBlur: -> 56 | @emit "blur" 57 | 58 | handleKeyup: (e) -> 59 | text = @getText() 60 | if @isEnableEnterKey && e.keyCode == 13 61 | @emit "done", text 62 | else 63 | @emit "change", text 64 | 65 | isVisible: -> 66 | @modalPanel.isVisible() 67 | 68 | show: -> 69 | @modalPanel.show() 70 | @textEditor.focus() 71 | @bindEvents() 72 | 73 | hide: -> 74 | @unbindEvents() 75 | @modalPanel.hide() 76 | @setText "" 77 | @setSimulatorText "" 78 | 79 | destroy: -> 80 | @modalPanel.destroy() 81 | @modalPanel = null 82 | @element.remove() 83 | @element = null 84 | 85 | setText: (text) -> 86 | @textEditor.getModel().setText text 87 | 88 | getText: -> 89 | @textEditor.getModel().getText().trim() 90 | 91 | setSimulatorText: (text) -> 92 | @simulator.textContent = text 93 | 94 | getSimulatorText: -> 95 | @simulator.textContent 96 | -------------------------------------------------------------------------------- /lib/sequential-number.coffee: -------------------------------------------------------------------------------- 1 | {CompositeDisposable, Range} = require "atom" 2 | SequentialNumberView = require "./sequential-number-view" 3 | 4 | SIMULATE_CURSOR_LENGTH = 3 5 | 6 | module.exports = SequentialNumber = 7 | activate: () -> 8 | @view = new SequentialNumberView 9 | @view.on "blur", => @close() 10 | @view.on "change", (value) => @simulate value 11 | @view.on "done", (value) => @exec value 12 | 13 | @previousFocused 14 | 15 | @subscriptions = new CompositeDisposable 16 | @subscriptions.add atom.commands.add "atom-workspace", "sequential-number:open": => @open() 17 | @subscriptions.add atom.commands.add "atom-workspace", "sequential-number:close": => @close() 18 | 19 | deactivate: -> 20 | @subscriptions.dispose() 21 | @view.destroy() 22 | 23 | serialize: -> 24 | 25 | open: -> 26 | if !@view.isVisible() 27 | @view.show() 28 | 29 | close: -> 30 | @view.hide() 31 | atom.views.getView(atom.workspace).focus() 32 | 33 | simulate: (value) -> 34 | result = @parseValue value 35 | text = "" 36 | 37 | if result != null 38 | simulateList = [0..SIMULATE_CURSOR_LENGTH - 1].map (index) => 39 | @calculateValue index, result 40 | simulateList.push "..." 41 | text = simulateList.join ", " 42 | 43 | @view.setSimulatorText text 44 | 45 | exec: (value) -> 46 | editor = @getEditor() 47 | result = @parseValue value 48 | 49 | if result != null 50 | editor.transact( => 51 | length = editor.cursors.length 52 | for index in [0...length] 53 | cursors = editor.cursors.slice() 54 | cursors = cursors.map (cursor) -> cursor.selection.getBufferRange() 55 | cursors = cursors.sort (a, b) -> a.start.row - b.start.row || a.start.column - b.start.column 56 | range = cursors[index] 57 | editor.setTextInBufferRange new Range(range.start, range.end), @calculateValue index, result 58 | ) 59 | 60 | @close() 61 | 62 | getEditor: -> 63 | atom.workspace.getActivePane().activeItem 64 | 65 | parseValue: (input) -> 66 | matches = "#{input}".match /^([+\-]?[\da-zA-Z]+(?:\.\d+)?)\s*([+\-]|(?:\+\+|\-\-))?\s*(\d+)?\s*(?:\:\s*(\d+))?\s*(?:\:\s*([\daA]+))?$/ 67 | return null if matches == null 68 | 69 | radix = matches[5] 70 | radix = if radix != undefined then radix else 10 71 | radix = if /\d+/.test radix then parseInt radix, 10 else radix 72 | isAlphaRadix = /[aA]/.test radix 73 | 74 | start = matches[1] 75 | return null if isAlphaRadix and /\d+/.test(start) 76 | 77 | start = if isAlphaRadix then start else parseInt(start, radix) 78 | 79 | operator = matches[2] || "+" 80 | step = parseInt matches[3], 10 81 | step = if isNaN matches[3] then 1 else step 82 | 83 | _digit = parseInt matches[4], 10 84 | digit = if "#{start}" == matches[1] then 0 else matches[1].length 85 | digit = if /^[+\-]/.test matches[1] then Math.max(digit - 1, 0) else digit 86 | digit = if isNaN _digit then digit else _digit 87 | 88 | return {start, digit, operator, step, radix, input} 89 | 90 | calculateValue: (index, args) -> 91 | if /[aA]/.test args.radix 92 | return @calculateAlphaValue index, args 93 | else 94 | return @calculateNumberValue index, args 95 | 96 | calculateNumberValue: (index, {start, digit, operator, step, radix, input}) -> 97 | _start = parseInt start, 10 98 | 99 | switch operator 100 | when "++" then value = _start + index 101 | when "--" then value = _start - index 102 | when "+" then value = _start + (index * step) 103 | when "-" then value = _start - (index * step) 104 | else return "" 105 | 106 | if isNaN value 107 | return "" 108 | 109 | value = @zeroPadding value, digit, radix 110 | firstAlpha = input.match /([a-fA-F])/ 111 | 112 | if firstAlpha 113 | value = value[if firstAlpha[1] == firstAlpha[1].toLowerCase() then "toLowerCase" else "toUpperCase"]() 114 | 115 | return value 116 | 117 | calculateAlphaValue: (index, {start, digit, operator, step, radix, input}) -> 118 | switch operator 119 | when "++" then count = (index - 1) + step 120 | when "--" then count = (index - 1) - step 121 | when "+" then count = index * step 122 | when "-" then count = index * step * -1 123 | 124 | value = @alphaSequence(start.toLowerCase(), count) 125 | value = @leftPadding(value, digit, "a") 126 | 127 | if /[A-Z]/.test(start) or /[A-Z]/.test(radix) 128 | value = value.toUpperCase() 129 | 130 | return value 131 | 132 | alphaSequence: (str, count) -> 133 | return str if count == 0 134 | 135 | alphabet = "abcdefghijklmnopqrstuvwxyz".split "" 136 | last = str.slice -1 137 | index = alphabet.indexOf last 138 | n = Math.floor((index + count) / alphabet.length) 139 | next = alphabet[(index + count) % alphabet.length] 140 | 141 | return "" if !next 142 | 143 | s = "#{str.slice(0, str.length - 1)}#{next}" 144 | 145 | if n > 0 146 | if s.length == 1 and index == alphabet.length - 1 147 | s = "a#{s}" 148 | else 149 | s = "#{@alphaSequence(s.slice(0, s.length - 1), n)}#{next}" 150 | 151 | return s 152 | 153 | leftPadding: (str, digit, padString) -> 154 | _digit = Math.max str.length, digit 155 | return (Array(_digit).join(padString) + str).slice(_digit * -1) 156 | 157 | zeroPadding: (number, digit = 0, radix = 10) -> 158 | num = number.toString radix 159 | numAbs = num.replace "-", "" 160 | positive = num.indexOf("-") < 0 161 | return (if positive then "" else "-") + @leftPadding(numAbs, digit, "0") 162 | -------------------------------------------------------------------------------- /lib/template-helper.coffee: -------------------------------------------------------------------------------- 1 | # Reference: 2 | # https://github.com/atom/notifications/blob/master/lib/template-helper.coffee 3 | 4 | module.exports = 5 | create: (htmlString) -> 6 | template = document.createElement("template") 7 | template.innerHTML = htmlString 8 | document.body.appendChild(template) 9 | template 10 | 11 | render: (template) -> 12 | document.importNode(template.content, true) -------------------------------------------------------------------------------- /menus/sequential-number.cson: -------------------------------------------------------------------------------- 1 | 'context-menu': 2 | 'atom-text-editor': [ 3 | { 4 | 'label': 'Open Sequential Number' 5 | 'command': 'sequential-number:open' 6 | } 7 | ] 8 | 'menu': [ 9 | { 10 | 'label': 'Packages' 11 | 'submenu': [ 12 | 'label': 'Sequential Number' 13 | 'submenu': [ 14 | { 15 | 'label': 'Open Sequential Number' 16 | 'command': 'sequential-number:open' 17 | } 18 | ] 19 | ] 20 | } 21 | ] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sequential-number", 3 | "main": "./lib/sequential-number", 4 | "version": "0.5.0", 5 | "description": "Input sequential number in the across multiple cursors.", 6 | "keywords": [ 7 | "serial number", 8 | "sequence number", 9 | "numbering", 10 | "text helper" 11 | ], 12 | "activationCommands": { 13 | "atom-workspace": "sequential-number:open" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/tsuyoshiwada/sequential-number" 18 | }, 19 | "license": "MIT", 20 | "engines": { 21 | "atom": ">=1.0.0 <2.0.0" 22 | }, 23 | "dependencies": { 24 | "event-kit": "^1.4.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /spec/sequential-number-spec.coffee: -------------------------------------------------------------------------------- 1 | {Range, Point} = require "atom" 2 | SequentialNumber = require "../lib/sequential-number" 3 | 4 | 5 | # Event trigger utility 6 | trigger = (el, event, type, data = {}) -> 7 | e = document.createEvent event 8 | e.initEvent type, true, true 9 | e = Object.assign e, data 10 | el.dispatchEvent e 11 | 12 | 13 | # setTimeout utility 14 | sleep = (msec) -> 15 | new Promise((resolve) -> 16 | setTimeout resolve, msec 17 | ) 18 | 19 | 20 | # Package 21 | describe "SequentialNumber", -> 22 | [workspaceElement, pane, element, panel] = [] 23 | 24 | beforeEach -> 25 | workspaceElement = atom.views.getView(atom.workspace) 26 | activationPromise = null 27 | 28 | jasmine.useRealClock() 29 | jasmine.attachToDOM(workspaceElement) 30 | 31 | waitsForPromise -> 32 | atom.workspace.open "test.txt" 33 | 34 | runs -> 35 | activationPromise = atom.packages.activatePackage "sequential-number" 36 | pane = atom.workspace.getActivePaneItem() 37 | pane.setText Array(5).join "\n" 38 | pane.setCursorBufferPosition [0, 0] 39 | atom.commands.dispatch workspaceElement, "sequential-number:open" 40 | 41 | waitsForPromise -> 42 | activationPromise 43 | 44 | runs -> 45 | element = workspaceElement.querySelector ".sequential-number" 46 | panel = atom.workspace.panelForItem(element) 47 | 48 | waitsForPromise -> 49 | sleep 250 50 | 51 | describe "when the sequential-number:open event is triggered", -> 52 | it "show the modal panel", -> 53 | expect(panel.isVisible()).toBe true 54 | 55 | it "hide the modal panel", -> 56 | atom.commands.dispatch element, "sequential-number:close" 57 | expect(panel.isVisible()).toBe false 58 | 59 | it "clears the previous editor text", -> 60 | model = panel.getItem().querySelector("atom-text-editor").getModel() 61 | model.setText "Sequential Number!!" 62 | expect(model.getText()).toBe "Sequential Number!!" 63 | 64 | atom.commands.dispatch element, "sequential-number:close" 65 | atom.commands.dispatch element, "sequential-number:open" 66 | expect(model.getText()).toBe "" 67 | 68 | describe "when the text is entered", -> 69 | [editor, simulator, model, previousText] = [] 70 | 71 | beforeEach -> 72 | pane.addCursorAtScreenPosition [1, 0] 73 | pane.addCursorAtScreenPosition [2, 0] 74 | pane.addCursorAtScreenPosition [3, 0] 75 | pane.addCursorAtScreenPosition [4, 0] 76 | pane.addCursorAtScreenPosition [5, 0] 77 | _panelItem = panel.getItem() 78 | editor = _panelItem.querySelector "atom-text-editor" 79 | simulator = _panelItem.querySelector "#sequential-number-simulator" 80 | model = editor.getModel() 81 | previousText = pane.getText() 82 | 83 | expectModelUndoToOriginal = -> 84 | pane.undo() 85 | expect(pane.getText()).toBe previousText 86 | 87 | expectModalTextToEnter = (input, simulateExpected, expected, undo = false) -> 88 | model.setText(input) 89 | 90 | # Simulate the Right key 91 | trigger editor, "HTMLEvents", "keyup", keyCode: 39 92 | expect(simulator.textContent).toBe simulateExpected 93 | 94 | # Simulate the Enter key 95 | trigger editor, "HTMLEvents", "keyup", keyCode: 13 96 | expect(pane.getText()).toBe expected 97 | 98 | if undo 99 | expectModelUndoToOriginal() 100 | 101 | it "does not change if the invalid value", -> 102 | expectModalTextToEnter "", "", previousText 103 | expectModalTextToEnter "--0011", "", previousText 104 | expectModalTextToEnter "++1", "", previousText 105 | expectModalTextToEnter "+1/", "", previousText 106 | expectModalTextToEnter "1%1", "", previousText 107 | expectModalTextToEnter "1*2", "", previousText 108 | expectModalTextToEnter "-2+++", "", previousText 109 | expectModalTextToEnter "+34hoge", "", previousText 110 | expectModalTextToEnter "alphabet", "", previousText 111 | 112 | describe "addition", -> 113 | it "syntax of the '0'", -> 114 | expectModalTextToEnter "0", 115 | "0, 1, 2, ...", 116 | """ 117 | 0 118 | 1 119 | 2 120 | 3 121 | 4 122 | """, 123 | true 124 | 125 | it "syntax of the '1'", -> 126 | expectModalTextToEnter "1", 127 | "1, 2, 3, ...", 128 | """ 129 | 1 130 | 2 131 | 3 132 | 4 133 | 5 134 | """, 135 | true 136 | 137 | it "syntax of the '1 + 2'", -> 138 | expectModalTextToEnter "1 + 2", 139 | "1, 3, 5, ...", 140 | """ 141 | 1 142 | 3 143 | 5 144 | 7 145 | 9 146 | """, 147 | true 148 | 149 | it "syntax of the '5++'", -> 150 | expectModalTextToEnter "5++", 151 | "5, 6, 7, ...", 152 | """ 153 | 5 154 | 6 155 | 7 156 | 8 157 | 9 158 | """, 159 | true 160 | 161 | it "syntax of the '015 + 1'", -> 162 | expectModalTextToEnter "015 + 1", 163 | "015, 016, 017, ...", 164 | """ 165 | 015 166 | 016 167 | 017 168 | 018 169 | 019 170 | """, 171 | true 172 | 173 | it "syntax of the '09 + 65'", -> 174 | expectModalTextToEnter "09 + 65", 175 | "09, 74, 139, ...", 176 | """ 177 | 09 178 | 74 179 | 139 180 | 204 181 | 269 182 | """, 183 | true 184 | 185 | it "syntax of the '-20+12'", -> 186 | expectModalTextToEnter "-20+12", 187 | "-20, -8, 4, ...", 188 | """ 189 | -20 190 | -8 191 | 4 192 | 16 193 | 28 194 | """, 195 | true 196 | 197 | it "syntax of the '-10 + 1 : 2'", -> 198 | expectModalTextToEnter "-10 + 1 : 2", 199 | "-10, -09, -08, ...", 200 | """ 201 | -10 202 | -09 203 | -08 204 | -07 205 | -06 206 | """, 207 | true 208 | 209 | it "syntax of the '-9 + 1000'", -> 210 | expectModalTextToEnter "-9 + 1000 : 3", 211 | "-009, 991, 1991, ...", 212 | """ 213 | -009 214 | 991 215 | 1991 216 | 2991 217 | 3991 218 | """, 219 | true 220 | 221 | describe "subtraction", -> 222 | it "syntax of the '10 - 3'", -> 223 | expectModalTextToEnter "10 - 3", 224 | "10, 7, 4, ...", 225 | """ 226 | 10 227 | 7 228 | 4 229 | 1 230 | -2 231 | """, 232 | true 233 | 234 | it "syntax of the '15--'", -> 235 | expectModalTextToEnter "15--", 236 | "15, 14, 13, ...", 237 | """ 238 | 15 239 | 14 240 | 13 241 | 12 242 | 11 243 | """, 244 | true 245 | 246 | it "syntax of the '0020 - 2'", -> 247 | expectModalTextToEnter "0020 - 2", 248 | "0020, 0018, 0016, ...", 249 | """ 250 | 0020 251 | 0018 252 | 0016 253 | 0014 254 | 0012 255 | """, 256 | true 257 | 258 | it "syntax of the '-003120 - 21'", -> 259 | expectModalTextToEnter "-003120 - 21", 260 | "-003120, -003141, -003162, ...", 261 | """ 262 | -003120 263 | -003141 264 | -003162 265 | -003183 266 | -003204 267 | """, 268 | true 269 | 270 | it "syntax of the '-8 - 90 : 3'", -> 271 | expectModalTextToEnter "-8 - 90 : 2", 272 | "-08, -98, -188, ...", 273 | """ 274 | -08 275 | -98 276 | -188 277 | -278 278 | -368 279 | """, 280 | true 281 | 282 | describe "radix = 2", -> 283 | it "syntax of the '0 + 1 : 1 : 2'", -> 284 | expectModalTextToEnter "0 + 1 : 1 : 2", 285 | "0, 1, 10, ...", 286 | """ 287 | 0 288 | 1 289 | 10 290 | 11 291 | 100 292 | """, 293 | true 294 | 295 | it "syntax of the '-11 - 2 : 2 : 2'", -> 296 | expectModalTextToEnter "-11 - 2 : 2 : 2", 297 | "-11, -101, -111, ...", 298 | """ 299 | -11 300 | -101 301 | -111 302 | -1001 303 | -1011 304 | """, 305 | true 306 | 307 | describe "radix = 8", -> 308 | it "syntax of the '6 + 1 : 2 : 8'", -> 309 | expectModalTextToEnter "6 + 1 : 2 : 8", 310 | "06, 07, 10, ...", 311 | """ 312 | 06 313 | 07 314 | 10 315 | 11 316 | 12 317 | """, 318 | true 319 | 320 | it "syntax of the '-5 - 5 : 2 : 8'", -> 321 | expectModalTextToEnter "-5 - 5 : 2 : 8", 322 | "-05, -12, -17, ...", 323 | """ 324 | -05 325 | -12 326 | -17 327 | -24 328 | -31 329 | """, 330 | true 331 | 332 | describe "radix = 16", -> 333 | it "syntax of the 'a + 6 : 1 : 16'", -> 334 | expectModalTextToEnter "a + 6 : 1 : 16", 335 | "a, 10, 16, ...", 336 | """ 337 | a 338 | 10 339 | 16 340 | 1c 341 | 22 342 | """, 343 | true 344 | 345 | it "syntax of the 'C4b + 9 : 6 : 16'", -> 346 | expectModalTextToEnter "C4b + 9 : 6 : 16", 347 | "000C4B, 000C54, 000C5D, ...", 348 | """ 349 | 000C4B 350 | 000C54 351 | 000C5D 352 | 000C66 353 | 000C6F 354 | """, 355 | true 356 | 357 | it "syntax of the 'b - 12 : 2 : 16'", -> 358 | expectModalTextToEnter "b - 12 : 2 : 16", 359 | "0b, -01, -0d, ...", 360 | """ 361 | 0b 362 | -01 363 | -0d 364 | -19 365 | -25 366 | """, 367 | true 368 | 369 | describe "radix = a", -> 370 | it "syntax of the 'a++ : 1 : a'", -> 371 | expectModalTextToEnter "a++ : 1 : a", 372 | "a, b, c, ...", 373 | """ 374 | a 375 | b 376 | c 377 | d 378 | e 379 | """, 380 | true 381 | 382 | it "syntax of the 'a + 2 : 1 : a'", -> 383 | expectModalTextToEnter "a + 2 : 1 : a", 384 | "a, c, e, ...", 385 | """ 386 | a 387 | c 388 | e 389 | g 390 | i 391 | """, 392 | true 393 | 394 | it "syntax of the 'z + 3 : 1 : a'", -> 395 | expectModalTextToEnter "z + 3 : 1 : a", 396 | "z, ac, af, ...", 397 | """ 398 | z 399 | ac 400 | af 401 | ai 402 | al 403 | """, 404 | true 405 | 406 | it "syntax of the 'W + 2 : 1 : a'", -> 407 | expectModalTextToEnter "W + 2 : 1 : a", 408 | "W, Y, AA, ...", 409 | """ 410 | W 411 | Y 412 | AA 413 | AC 414 | AE 415 | """, 416 | true 417 | 418 | it "syntax of the 'w + 2 : 1 : A'", -> 419 | expectModalTextToEnter "W + 2 : 1 : A", 420 | "W, Y, AA, ...", 421 | """ 422 | W 423 | Y 424 | AA 425 | AC 426 | AE 427 | """, 428 | true 429 | 430 | it "syntax of the 'y + 2 : 3 : a'", -> 431 | expectModalTextToEnter "y + 2 : 3 : a", 432 | "aay, aaa, aac, ...", 433 | """ 434 | aay 435 | aaa 436 | aac 437 | aae 438 | aag 439 | """, 440 | true 441 | 442 | it "syntax of the 'e - 1 : 1 : a'", -> 443 | expectModalTextToEnter "e - 1 : 1 : a", 444 | "e, d, c, ...", 445 | """ 446 | e 447 | d 448 | c 449 | b 450 | a 451 | """, 452 | true 453 | 454 | it "syntax of the 'a - 2 : 1 : a'", -> 455 | expectModalTextToEnter "a - 2 : 1 : a", 456 | "a, , , ...", 457 | """ 458 | a 459 | 460 | 461 | 462 | 463 | """, 464 | true 465 | 466 | describe "single line", -> 467 | it "syntax of the '1 + 1 : 2'", -> 468 | text = "test[] test[] test[]" 469 | pane.setText text 470 | pane.setCursorScreenPosition [0, 5] 471 | pane.addCursorAtScreenPosition [0, 12] 472 | pane.addCursorAtScreenPosition [0, 19] 473 | expectModalTextToEnter "1 + 1 : 2", 474 | "01, 02, 03, ...", 475 | """ 476 | test[01] test[02] test[03] 477 | """, 478 | false 479 | 480 | pane.undo() 481 | expect(pane.getText()).toBe text 482 | 483 | describe "when the currently selected text", -> 484 | it "replace selected text", -> 485 | pane.insertText "Hello World!!" 486 | 487 | # Select all of the "Hello World!!" 488 | for cursor in pane.getCursors() 489 | position = cursor.getBufferPosition() 490 | startPoint = new Point position.row, 0 491 | endPoint = new Point position.row, 13 492 | cursor.selection.setBufferRange new Range startPoint, endPoint 493 | 494 | model.setText "01+1:3" 495 | 496 | # Simulate the Enter key 497 | trigger editor, "HTMLEvents", "keyup", keyCode: 13 498 | 499 | expect(pane.getText()).toBe """ 500 | 001 501 | 002 502 | 003 503 | 004 504 | 005 505 | """ 506 | --------------------------------------------------------------------------------