2 CommandError = require './command-error'
5 deferred = Promise.defer()
11 if error.message.endsWith('is a directory')
12 atom.notifications.addWarning("Unable to save file: #{error.message}")
14 if error.code is 'EACCES'
16 .addWarning("Unable to save file: Permission denied '#{error.path}'")
17 else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST']
18 atom.notifications.addWarning("Unable to save file '#{error.path}'",
19 detail: error.message)
20 else if error.code is 'EROFS'
21 atom.notifications.addWarning(
22 "Unable to save file: Read-only file system '#{error.path}'")
24 /ENOTDIR, not a directory '([^']+)'/.exec(error.message))
25 fileName = errorMatch[1]
26 atom.notifications.addWarning("Unable to save file: A directory in the "+
27 "path '#{fileName}' could not be written to")
33 getFullPath = (filePath) ->
34 return filePath if path.isAbsolute(filePath)
35 return path.join(atom.project.getPath(), filePath)
37 replaceGroups = (groups, replString) ->
38 arr = replString.split('')
42 while (m = replString.match(/(?:[^\\]|^)\\(\d)/))?
43 group = groups[m[1]] or ''
44 i = replString.indexOf(m[0])
46 replString = replString.slice(i + l)
47 arr[i + offset...i + offset + l] = (if l is 2 then '' else m[0][0]) +
49 arr = arr.join('').split ''
50 offset += i + l - group.length
52 return arr.join('').replace(/\\\\(\d)/, '\\$1')
58 @registerCommand: (name, func) =>
59 @singleton()[name] = func
62 atom.workspace.getActivePane().destroyActiveItem()
66 tabedit: (range, args) ->
68 filePaths = args.split(' ')
69 pane = atom.workspace.getActivePane()
70 if filePaths? and filePaths.length > 0
72 do -> atom.workspace.openURIInPane file, pane
74 atom.workspace.openURIInPane('', pane)
76 tabe: (args...) => @tabedit(args...)
78 tabnew: (args...) => @tabedit(args...)
85 pane = atom.workspace.getActivePane()
86 pane.activateNextItem()
91 pane = atom.workspace.getActivePane()
92 pane.activatePreviousItem()
94 tabp: => @tabprevious()
96 edit: (range, filePath) ->
97 filePath = filePath.trim()
98 if filePath.indexOf(' ') isnt -1
99 throw new CommandError('Only one file name allowed')
100 buffer = atom.workspace.getActiveTextEditor().buffer
101 filePath = buffer.getPath() if filePath is ''
102 buffer.setPath(getFullPath(filePath))
105 e: (args...) => @edit(args...)
108 buffer = atom.workspace.getActiveTextEditor().buffer
109 buffer.setPath(undefined)
112 write: (range, filePath) ->
113 filePath = filePath.trim()
114 deferred = Promise.defer()
116 pane = atom.workspace.getActivePane()
117 editor = atom.workspace.getActiveTextEditor()
118 if atom.workspace.getActiveTextEditor().getPath() isnt undefined
119 if filePath.length > 0
120 editorPath = editor.getPath()
121 fullPath = getFullPath(filePath)
122 trySave(-> editor.saveAs(fullPath))
125 editor.buffer.setPath(editorPath)
127 trySave(-> editor.save())
128 .then deferred.resolve
130 if filePath.length > 0
131 fullPath = getFullPath(filePath)
132 trySave(-> editor.saveAs(fullPath))
133 .then deferred.resolve
135 fullPath = atom.showSaveDialogSync()
137 trySave(-> editor.saveAs(fullPath))
138 .then deferred.resolve
146 @write(args...).then => @quit()
148 x: (args...) => @wq(args...)
151 atom.workspace.saveAll()
153 split: (range, args) ->
155 filePaths = args.split(' ')
156 filePaths = undefined if filePaths.length is 1 and filePaths[0] is ''
157 pane = atom.workspace.getActivePane()
158 if filePaths? and filePaths.length > 0
159 newPane = pane.splitUp()
160 for file in filePaths
162 atom.workspace.openURIInPane file, newPane
164 pane.splitUp(copyActiveItem: true)
166 sp: (args...) => @split(args...)
168 substitute: (range, args) ->
169 args = args.trimLeft()
171 if /[a-z]/i.test(delim)
172 throw new CommandError(
173 "Regular expressions can't be delimited by letters")
174 delimRE = new RegExp("[^\\\\]#{delim}")
177 while (i = args_.search(delimRE)) isnt -1
179 args_ = args_[i + 2..]
180 if args_.length is 0 and spl.length is 3
181 throw new CommandError('Trailing characters')
182 else if args_.length isnt 0
185 throw new CommandError('Trailing characters')
190 pattern = new RegExp(spl[0], spl[2])
192 if e.message.indexOf('Invalid flags supplied to RegExp constructor') is 0
193 # vim only says 'Trailing characters', but let's be more descriptive
194 throw new CommandError("Invalid flags: #{e.message[45..]}")
195 else if e.message.indexOf('Invalid regular expression: ') is 0
196 throw new CommandError("Invalid RegEx: #{e.message[27..]}")
200 buffer = atom.workspace.getActiveTextEditor().buffer
201 cp = buffer.history.createCheckpoint()
202 for line in [range[0]..range[1]]
203 buffer.scanInRange(pattern,
204 [[line, 0], [line, buffer.lines[line].length]],
205 ({match, matchText, range, stop, replace}) ->
206 replace(replaceGroups(match[..], spl[1]))
208 buffer.history.groupChangesSinceCheckpoint(cp)
210 s: (args...) => @substitute(args...)
212 vsplit: (range, args) ->
214 filePaths = args.split(' ')
215 filePaths = undefined if filePaths.length is 1 and filePaths[0] is ''
216 pane = atom.workspace.getActivePane()
217 if filePaths? and filePaths.length > 0
218 newPane = pane.splitLeft()
219 for file in filePaths
221 atom.workspace.openURIInPane file, newPane
223 pane.splitLeft(copyActiveItem: true)
225 vsp: (args...) => @vsplit(args...)
228 range = [[range[0], 0], [range[1] + 1, 0]]
229 atom.workspace.getActiveTextEditor().buffer.setTextInRange(range, '')