From 455f099b504ec07dd492ab31987ae05a6f6774c7 Mon Sep 17 00:00:00 2001 From: Ben Beltran Date: Mon, 28 Sep 2015 12:39:59 -0500 Subject: Adds atom packages --- .../lib/ex-command-mode-input-element.coffee | 64 ------- .../lib/ex-normal-mode-input-element.coffee | 64 +++++++ atom/packages/ex-mode/lib/ex-state.coffee | 4 + atom/packages/ex-mode/lib/ex.coffee | 184 ++++++++++++++------- atom/packages/ex-mode/lib/view-model.coffee | 6 +- atom/packages/ex-mode/lib/vim-option.coffee | 23 +++ 6 files changed, 214 insertions(+), 131 deletions(-) delete mode 100644 atom/packages/ex-mode/lib/ex-command-mode-input-element.coffee create mode 100644 atom/packages/ex-mode/lib/ex-normal-mode-input-element.coffee create mode 100644 atom/packages/ex-mode/lib/vim-option.coffee (limited to 'atom/packages/ex-mode/lib') diff --git a/atom/packages/ex-mode/lib/ex-command-mode-input-element.coffee b/atom/packages/ex-mode/lib/ex-command-mode-input-element.coffee deleted file mode 100644 index 91e0eb2..0000000 --- a/atom/packages/ex-mode/lib/ex-command-mode-input-element.coffee +++ /dev/null @@ -1,64 +0,0 @@ -class ExCommandModeInputElement extends HTMLDivElement - createdCallback: -> - @className = "command-mode-input" - - @editorContainer = document.createElement("div") - @editorContainer.className = "editor-container" - - @appendChild(@editorContainer) - - initialize: (@viewModel, opts = {}) -> - if opts.class? - @editorContainer.classList.add(opts.class) - - if opts.hidden - @editorContainer.style.height = "0px" - - @editorElement = document.createElement "atom-text-editor" - @editorElement.classList.add('editor') - @editorElement.getModel().setMini(true) - @editorElement.setAttribute('mini', '') - @editorContainer.appendChild(@editorElement) - - @singleChar = opts.singleChar - @defaultText = opts.defaultText ? '' - - @panel = atom.workspace.addBottomPanel(item: this, priority: 100) - - @focus() - @handleEvents() - - this - - handleEvents: -> - if @singleChar? - @editorElement.getModel().getBuffer().onDidChange (e) => - @confirm() if e.newText - else - atom.commands.add(@editorElement, 'editor:newline', @confirm.bind(this)) - - atom.commands.add(@editorElement, 'core:confirm', @confirm.bind(this)) - atom.commands.add(@editorElement, 'core:cancel', @cancel.bind(this)) - atom.commands.add(@editorElement, 'blur', @cancel.bind(this)) - - confirm: -> - @value = @editorElement.getModel().getText() or @defaultText - @viewModel.confirm(this) - @removePanel() - - focus: -> - @editorElement.focus() - - cancel: (e) -> - @viewModel.cancel(this) - @removePanel() - - removePanel: -> - atom.workspace.getActivePane().activate() - @panel.destroy() - -module.exports = -document.registerElement("ex-command-mode-input" - extends: "div", - prototype: ExCommandModeInputElement.prototype -) diff --git a/atom/packages/ex-mode/lib/ex-normal-mode-input-element.coffee b/atom/packages/ex-mode/lib/ex-normal-mode-input-element.coffee new file mode 100644 index 0000000..91e0eb2 --- /dev/null +++ b/atom/packages/ex-mode/lib/ex-normal-mode-input-element.coffee @@ -0,0 +1,64 @@ +class ExCommandModeInputElement extends HTMLDivElement + createdCallback: -> + @className = "command-mode-input" + + @editorContainer = document.createElement("div") + @editorContainer.className = "editor-container" + + @appendChild(@editorContainer) + + initialize: (@viewModel, opts = {}) -> + if opts.class? + @editorContainer.classList.add(opts.class) + + if opts.hidden + @editorContainer.style.height = "0px" + + @editorElement = document.createElement "atom-text-editor" + @editorElement.classList.add('editor') + @editorElement.getModel().setMini(true) + @editorElement.setAttribute('mini', '') + @editorContainer.appendChild(@editorElement) + + @singleChar = opts.singleChar + @defaultText = opts.defaultText ? '' + + @panel = atom.workspace.addBottomPanel(item: this, priority: 100) + + @focus() + @handleEvents() + + this + + handleEvents: -> + if @singleChar? + @editorElement.getModel().getBuffer().onDidChange (e) => + @confirm() if e.newText + else + atom.commands.add(@editorElement, 'editor:newline', @confirm.bind(this)) + + atom.commands.add(@editorElement, 'core:confirm', @confirm.bind(this)) + atom.commands.add(@editorElement, 'core:cancel', @cancel.bind(this)) + atom.commands.add(@editorElement, 'blur', @cancel.bind(this)) + + confirm: -> + @value = @editorElement.getModel().getText() or @defaultText + @viewModel.confirm(this) + @removePanel() + + focus: -> + @editorElement.focus() + + cancel: (e) -> + @viewModel.cancel(this) + @removePanel() + + removePanel: -> + atom.workspace.getActivePane().activate() + @panel.destroy() + +module.exports = +document.registerElement("ex-command-mode-input" + extends: "div", + prototype: ExCommandModeInputElement.prototype +) diff --git a/atom/packages/ex-mode/lib/ex-state.coffee b/atom/packages/ex-mode/lib/ex-state.coffee index b676535..7c0f37c 100644 --- a/atom/packages/ex-mode/lib/ex-state.coffee +++ b/atom/packages/ex-mode/lib/ex-state.coffee @@ -34,6 +34,9 @@ class ExState onDidFailToExecute: (fn) -> @emitter.on('failed-to-execute', fn) + onDidProcessOpStack: (fn) -> + @emitter.on('processed-op-stack', fn) + pushOperations: (operations) -> @opStack.push operations @@ -55,5 +58,6 @@ class ExState else throw e @clearOpStack() + @emitter.emit('processed-op-stack') module.exports = ExState diff --git a/atom/packages/ex-mode/lib/ex.coffee b/atom/packages/ex-mode/lib/ex.coffee index c159534..e259c90 100644 --- a/atom/packages/ex-mode/lib/ex.coffee +++ b/atom/packages/ex-mode/lib/ex.coffee @@ -1,5 +1,7 @@ path = require 'path' CommandError = require './command-error' +fs = require 'fs-plus' +VimOption = require './vim-option' trySave = (func) -> deferred = Promise.defer() @@ -30,26 +32,37 @@ trySave = (func) -> deferred.promise +saveAs = (filePath) -> + editor = atom.workspace.getActiveTextEditor() + fs.writeFileSync(filePath, editor.getText()) + getFullPath = (filePath) -> - return filePath if path.isAbsolute(filePath) - return path.join(atom.project.getPath(), filePath) - -replaceGroups = (groups, replString) -> - arr = replString.split('') - offset = 0 - cdiff = 0 - - while (m = replString.match(/(?:[^\\]|^)\\(\d)/))? - group = groups[m[1]] or '' - i = replString.indexOf(m[0]) - l = m[0].length - replString = replString.slice(i + l) - arr[i + offset...i + offset + l] = (if l is 2 then '' else m[0][0]) + - group - arr = arr.join('').split '' - offset += i + l - group.length - - return arr.join('').replace(/\\\\(\d)/, '\\$1') + filePath = fs.normalize(filePath) + + if path.isAbsolute(filePath) + filePath + else if atom.project.getPaths().length == 0 + path.join(fs.normalize('~'), filePath) + else + path.join(atom.project.getPaths()[0], filePath) + +replaceGroups = (groups, string) -> + replaced = '' + escaped = false + while (char = string[0])? + string = string[1..] + if char is '\\' and not escaped + escaped = true + else if /\d/.test(char) and escaped + escaped = false + group = groups[parseInt(char)] + group ?= '' + replaced += group + else + escaped = false + replaced += char + + replaced class Ex @singleton: => @@ -63,21 +76,21 @@ class Ex q: => @quit() - tabedit: (range, args) -> - args = args.trim() - filePaths = args.split(' ') - pane = atom.workspace.getActivePane() - if filePaths? and filePaths.length > 0 - for file in filePaths - do -> atom.workspace.openURIInPane file, pane + tabedit: (range, args) => + if args.trim() isnt '' + @edit(range, args) else - atom.workspace.openURIInPane('', pane) + @tabnew(range, args) tabe: (args...) => @tabedit(args...) - tabnew: (args...) => @tabedit(args...) + tabnew: (range, args) => + if args.trim() is '' + atom.workspace.open() + else + @tabedit(range, args) - tabclose: => @quit() + tabclose: (args...) => @quit(args...) tabc: => @tabclose() @@ -95,12 +108,29 @@ class Ex edit: (range, filePath) -> filePath = filePath.trim() + if filePath[0] is '!' + force = true + filePath = filePath[1..].trim() + else + force = false + + editor = atom.workspace.getActiveTextEditor() + if editor.isModified() and not force + throw new CommandError('No write since last change (add ! to override)') if filePath.indexOf(' ') isnt -1 throw new CommandError('Only one file name allowed') - buffer = atom.workspace.getActiveTextEditor().buffer - filePath = buffer.getPath() if filePath is '' - buffer.setPath(getFullPath(filePath)) - buffer.load() + + if filePath.length isnt 0 + fullPath = getFullPath(filePath) + if fullPath is editor.getPath() + editor.getBuffer().reload() + else + atom.workspace.open(fullPath) + else + if editor.getPath()? + editor.getBuffer().reload() + else + throw new CommandError('No file name') e: (args...) => @edit(args...) @@ -110,32 +140,33 @@ class Ex buffer.load() write: (range, filePath) -> + if filePath[0] is '!' + force = true + filePath = filePath[1..] + else + force = false + filePath = filePath.trim() + if filePath.indexOf(' ') isnt -1 + throw new CommandError('Only one file name allowed') + deferred = Promise.defer() - pane = atom.workspace.getActivePane() editor = atom.workspace.getActiveTextEditor() - if atom.workspace.getActiveTextEditor().getPath() isnt undefined - if filePath.length > 0 - editorPath = editor.getPath() - fullPath = getFullPath(filePath) - trySave(-> editor.saveAs(fullPath)) - .then -> - deferred.resolve() - editor.buffer.setPath(editorPath) - else - trySave(-> editor.save()) - .then deferred.resolve - else - if filePath.length > 0 - fullPath = getFullPath(filePath) - trySave(-> editor.saveAs(fullPath)) - .then deferred.resolve - else - fullPath = atom.showSaveDialogSync() - if fullPath? - trySave(-> editor.saveAs(fullPath)) - .then deferred.resolve + saved = false + if filePath.length isnt 0 + fullPath = getFullPath(filePath) + if editor.getPath()? and (not fullPath? or editor.getPath() == fullPath) + # Use editor.save when no path is given or the path to the file is given + trySave(-> editor.save()).then(deferred.resolve) + saved = true + else if not fullPath? + fullPath = atom.showSaveDialogSync() + + if not saved and fullPath? + if not force and fs.existsSync(fullPath) + throw new CommandError("File exists (add ! to override)") + trySave(-> saveAs(fullPath)).then(deferred.resolve) deferred.promise @@ -145,7 +176,7 @@ class Ex wq: (args...) => @write(args...).then => @quit() - x: (args...) => @wq(args...) + xit: (args...) => @wq(args...) wa: -> atom.workspace.saveAll() @@ -185,6 +216,9 @@ class Ex throw new CommandError('Trailing characters') spl[1] ?= '' spl[2] ?= '' + notDelimRE = new RegExp("\\\\#{delim}", 'g') + spl[0] = spl[0].replace(notDelimRE, delim) + spl[1] = spl[1].replace(notDelimRE, delim) try pattern = new RegExp(spl[0], spl[2]) @@ -198,14 +232,13 @@ class Ex throw e buffer = atom.workspace.getActiveTextEditor().buffer - cp = buffer.history.createCheckpoint() - for line in [range[0]..range[1]] - buffer.scanInRange(pattern, - [[line, 0], [line, buffer.lines[line].length]], - ({match, matchText, range, stop, replace}) -> - replace(replaceGroups(match[..], spl[1])) - ) - buffer.history.groupChangesSinceCheckpoint(cp) + atom.workspace.getActiveTextEditor().transact -> + for line in [range[0]..range[1]] + buffer.scanInRange(pattern, + [[line, 0], [line, buffer.lines[line].length]], + ({match, matchText, range, stop, replace}) -> + replace(replaceGroups(match[..], spl[1])) + ) s: (args...) => @substitute(args...) @@ -228,4 +261,27 @@ class Ex range = [[range[0], 0], [range[1] + 1, 0]] atom.workspace.getActiveTextEditor().buffer.setTextInRange(range, '') + set: (range, args) -> + args = args.trim() + if args == "" + throw new CommandError("No option specified") + options = args.split(' ') + for option in options + do -> + if option.includes("=") + nameValPair = option.split("=") + if (nameValPair.length != 2) + throw new CommandError("Wrong option format. [name]=[value] format is expected") + optionName = nameValPair[0] + optionValue = nameValPair[1] + optionProcessor = VimOption.singleton()[optionName] + if not optionProcessor? + throw new CommandError("No such option: #{optionName}") + optionProcessor(optionValue) + else + optionProcessor = VimOption.singleton()[option] + if not optionProcessor? + throw new CommandError("No such option: #{option}") + optionProcessor() + module.exports = Ex diff --git a/atom/packages/ex-mode/lib/view-model.coffee b/atom/packages/ex-mode/lib/view-model.coffee index af96e77..742d751 100644 --- a/atom/packages/ex-mode/lib/view-model.coffee +++ b/atom/packages/ex-mode/lib/view-model.coffee @@ -1,11 +1,11 @@ -ExCommandModeInputElement = require './ex-command-mode-input-element' +ExNormalModeInputElement = require './ex-normal-mode-input-element' class ViewModel constructor: (@command, opts={}) -> {@editor, @exState} = @command - @view = new ExCommandModeInputElement().initialize(@, opts) - @editor.commandModeInputView = @view + @view = new ExNormalModeInputElement().initialize(@, opts) + @editor.normalModeInputView = @view @exState.onDidFailToExecute => @view.remove() @done = false diff --git a/atom/packages/ex-mode/lib/vim-option.coffee b/atom/packages/ex-mode/lib/vim-option.coffee new file mode 100644 index 0000000..2ee056c --- /dev/null +++ b/atom/packages/ex-mode/lib/vim-option.coffee @@ -0,0 +1,23 @@ +class VimOption + @singleton: => + @option ||= new VimOption + + list: => + atom.config.set("editor.showInvisibles", true) + + nolist: => + atom.config.set("editor.showInvisibles", false) + + number: => + atom.config.set("editor.showLineNumbers", true) + + nu: => + @number() + + nonumber: => + atom.config.set("editor.showLineNumbers", false) + + nonu: => + @nonumber() + +module.exports = VimOption -- cgit