more method clean-up; bug fixes for shell junk
--HG-- branch : pmacs2
This commit is contained in:
parent
dcf393d135
commit
d5c005a692
|
@ -118,7 +118,10 @@ class Application(object):
|
||||||
|
|
||||||
# initialize our methods
|
# initialize our methods
|
||||||
self.methods = {}
|
self.methods = {}
|
||||||
for name in ('method', 'method.svn', 'method.cvs'):
|
names = ('method', 'method.svn', 'method.cvs', 'method.search',
|
||||||
|
'method.buffers', 'method.move', 'method.shell',
|
||||||
|
'method.introspect', 'method.help')
|
||||||
|
for name in names:
|
||||||
exec("import %s" % name)
|
exec("import %s" % name)
|
||||||
mod = eval(name)
|
mod = eval(name)
|
||||||
for mname in dir(mod):
|
for mname in dir(mod):
|
||||||
|
|
|
@ -105,213 +105,6 @@ class Method(object):
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
raise Exception, "Unimplemented Method: %s %r" % (self.name, vargs)
|
raise Exception, "Unimplemented Method: %s %r" % (self.name, vargs)
|
||||||
|
|
||||||
class AboutPmacs(Method):
|
|
||||||
'''print some information about pmacs'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
a = w.application
|
|
||||||
if not a.has_buffer_name('*About*'):
|
|
||||||
b = buffer.AboutBuffer()
|
|
||||||
a.add_buffer(b)
|
|
||||||
window.Window(b, a)
|
|
||||||
b = a.bufferlist.get_buffer_by_name('*About*')
|
|
||||||
if a.window().buffer is not b:
|
|
||||||
a.switch_buffer(b)
|
|
||||||
|
|
||||||
class GotoChar(Method):
|
|
||||||
'''Jump to the specified character'''
|
|
||||||
args = [Argument("charno", type=type(0), prompt="Goto char: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.goto_char(vargs["charno"])
|
|
||||||
class ForwardChars(Method):
|
|
||||||
'''Move forward the specified number of characters'''
|
|
||||||
args = [Argument("charno", type=type(0), prompt="Forward chars: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.forward_chars(vargs["charno"])
|
|
||||||
|
|
||||||
class GotoLine(Method):
|
|
||||||
'''Jump to the specified line number'''
|
|
||||||
args = [Argument("lineno", type=type(0), prompt="Goto line: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
n = vargs["lineno"]
|
|
||||||
if n < 0:
|
|
||||||
n = len(w.buffer.lines) + n + 1
|
|
||||||
if n > len(w.buffer.lines):
|
|
||||||
n = len(w.buffer.lines)
|
|
||||||
elif n < 1:
|
|
||||||
n = 1
|
|
||||||
w.goto_line(n)
|
|
||||||
class ForwardLines(Method):
|
|
||||||
'''Move forward the specified number of characters'''
|
|
||||||
args = [Argument("lineno", type=type(0), prompt="Forward lines: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.forward_lines(vargs["lineno"])
|
|
||||||
|
|
||||||
# search and replace
|
|
||||||
class Search(Method):
|
|
||||||
'''Interactive search; finds next occurance of text in buffer'''
|
|
||||||
is_literal = True
|
|
||||||
direction = 'next'
|
|
||||||
prompt = 'I-Search: '
|
|
||||||
def execute(self, w, **vargs):
|
|
||||||
self.old_cursor = w.logical_cursor()
|
|
||||||
self.old_window = w
|
|
||||||
w.application.open_mini_buffer(self.prompt, lambda x: None, self, None, 'search')
|
|
||||||
class ReverseSearch(Search):
|
|
||||||
'''Interactive search; finds previous occurance of text in buffer'''
|
|
||||||
direction = 'previous'
|
|
||||||
class RegexSearch(Search):
|
|
||||||
'''Interactive search; finds next occurance of regex in buffer'''
|
|
||||||
is_literal = False
|
|
||||||
prompt = 'I-RegexSearch: '
|
|
||||||
class RegexReverseSearch(RegexSearch):
|
|
||||||
'''Interactive search; finds prevoius occurance of regex in buffer'''
|
|
||||||
direction = 'previous'
|
|
||||||
|
|
||||||
class Replace(Method):
|
|
||||||
'''Replace occurances of string X with string Y'''
|
|
||||||
is_literal = True
|
|
||||||
args = [Argument('before', prompt="Replace String: ",
|
|
||||||
default=default.last_replace_before, load_default=True),
|
|
||||||
Argument('after', prompt="Replace With: ",
|
|
||||||
default=default.last_replace_after, load_default=True)]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
a = w.application
|
|
||||||
a.last_replace_before = self.before = vargs['before']
|
|
||||||
a.last_replace_after = self.after = vargs['after']
|
|
||||||
self.old_window = w
|
|
||||||
a.open_mini_buffer('I-Replace: ', lambda x: None, self, None, 'replace')
|
|
||||||
class RegexReplace(Method):
|
|
||||||
'''Replace occurances of string X with string Y'''
|
|
||||||
is_literal = False
|
|
||||||
args = [Argument('before', prompt="Replace Regex: ",
|
|
||||||
default=default.last_replace_before, load_default=True),
|
|
||||||
Argument('after', prompt="Replace With: ",
|
|
||||||
default=default.last_replace_after, load_default=True)]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.application.last_replace_before = self.before = vargs['before']
|
|
||||||
w.application.last_replace_after = self.after = vargs['after']
|
|
||||||
self.old_window = w
|
|
||||||
f = lambda x: None
|
|
||||||
w.application.open_mini_buffer('I-RegexReplace: ', f, self, None, 'replace')
|
|
||||||
|
|
||||||
# navigating between buffers
|
|
||||||
class OpenFile(Method):
|
|
||||||
'''Open file in a new buffer, or go to file's open buffer'''
|
|
||||||
args = [Argument('filename', datatype="path", prompt="Open File: ",
|
|
||||||
default=default.path_dirname, load_default=True)]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
b = w.application.open_path(vargs['filename'])
|
|
||||||
SwitchBuffer().execute(w, buffername=b.name())
|
|
||||||
class OpenAesFile(Method):
|
|
||||||
'''Open AES encrypted file in a new buffer, or go to file's open buffer'''
|
|
||||||
args = [Argument('filename', datatype="path", prompt="Open AES File: "),
|
|
||||||
Argument('password', prompt="Use AES Password: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
b = w.application.open_path(vargs['filename'], 'aes', vargs['password'])
|
|
||||||
SwitchBuffer().execute(w, buffername=b.name())
|
|
||||||
return
|
|
||||||
|
|
||||||
class ViewBufferParent(Method):
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
b = w.buffer
|
|
||||||
if not hasattr(b, 'path'):
|
|
||||||
w.set_error('Buffer has no path')
|
|
||||||
elif b.path == '/':
|
|
||||||
w.set_error("Root directory has no parent")
|
|
||||||
else:
|
|
||||||
path = os.path.dirname(b.path)
|
|
||||||
w.application.methods['open-file'].execute(w, filename=path)
|
|
||||||
|
|
||||||
class SwitchBuffer(Method):
|
|
||||||
'''Switch to a different'''
|
|
||||||
args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ",
|
|
||||||
default=default.last_buffer)]
|
|
||||||
def _pre_execute(self, w, **vargs):
|
|
||||||
a = w.application
|
|
||||||
if len(a.bufferlist.buffers) < 1:
|
|
||||||
raise Exception, "No other buffers"
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
name = vargs['buffername']
|
|
||||||
buf = None
|
|
||||||
if w.application.has_buffer_name(name):
|
|
||||||
b = w.application.bufferlist.get_buffer_by_name(name)
|
|
||||||
w.application.switch_buffer(b)
|
|
||||||
else:
|
|
||||||
w.set_error("buffer %r was not found" % name)
|
|
||||||
class KillBuffer(Method):
|
|
||||||
'''Close the current buffer'''
|
|
||||||
force=False
|
|
||||||
args = [Argument('buffername', datatype="buffer", prompt="Kill Buffer: ",
|
|
||||||
default=default.current_buffer)]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
name = vargs['buffername']
|
|
||||||
a = w.application
|
|
||||||
assert name in a.bufferlist.buffer_names, "Buffer %r does not exist" % name
|
|
||||||
assert name != '*Scratch*', "Can't kill scratch buffer"
|
|
||||||
self._to_kill = a.bufferlist.buffer_names[name]
|
|
||||||
self._old_window = w
|
|
||||||
if self.force or not self._to_kill.changed():
|
|
||||||
self._doit()
|
|
||||||
else:
|
|
||||||
self._prompt = "Buffer has unsaved changes; kill anyway? "
|
|
||||||
a.open_mini_buffer(self._prompt, self._callback)
|
|
||||||
def _doit(self):
|
|
||||||
a = self._old_window.application
|
|
||||||
b = self._to_kill
|
|
||||||
if a.bufferlist.is_buffer_visible(b):
|
|
||||||
a.bufferlist.set_slot(a.active_slot, a.bufferlist.hidden_buffers[0])
|
|
||||||
a.bufferlist.remove_buffer(b)
|
|
||||||
b.close()
|
|
||||||
def _callback(self, v):
|
|
||||||
a = self._old_window.application
|
|
||||||
if v == 'yes':
|
|
||||||
self._doit()
|
|
||||||
a.close_mini_buffer()
|
|
||||||
elif v == 'no':
|
|
||||||
a.close_mini_buffer()
|
|
||||||
else:
|
|
||||||
a.close_mini_buffer()
|
|
||||||
a.set_error('Please type "yes" or "no"')
|
|
||||||
|
|
||||||
class ForceKillBuffer(KillBuffer):
|
|
||||||
force=True
|
|
||||||
args = [Argument('buffername', datatype="buffer", prompt="Force Kill Buffer: ",
|
|
||||||
default=default.current_buffer)]
|
|
||||||
class ListBuffers(Method):
|
|
||||||
'''List all open buffers in a new buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
bl = w.application.bufferlist
|
|
||||||
bnames = [b.name() for b in bl.buffers]
|
|
||||||
bnames.sort()
|
|
||||||
data = '\n'.join(bnames)
|
|
||||||
w.application.data_buffer("*Buffers*", data, switch_to=True)
|
|
||||||
class SaveBufferAs(Method):
|
|
||||||
'''Save the contents of a buffer to the specified path'''
|
|
||||||
args = [Argument('path', datatype="path", prompt="Write file: ",
|
|
||||||
default=default.current_working_dir, load_default=True)]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
curr_buffer = w.buffer
|
|
||||||
curr_buffer_name = curr_buffer.name()
|
|
||||||
data = curr_buffer.make_string()
|
|
||||||
path = os.path.realpath(os.path.expanduser(vargs['path']))
|
|
||||||
w.set_error("got %r (%d)" % (path, len(data)))
|
|
||||||
if w.application.has_buffer_name(path):
|
|
||||||
w.set_error("buffer for %r is already open" % path)
|
|
||||||
return
|
|
||||||
w.application.file_buffer(path, data, switch_to=True)
|
|
||||||
if curr_buffer_name != '*Scratch*':
|
|
||||||
w.application.methods['kill-buffer'].execute(w, buffername=curr_buffer_name)
|
|
||||||
else:
|
|
||||||
curr_buffer.set_data('')
|
|
||||||
w.set_error('Wrote %r' % path)
|
|
||||||
class SaveBuffer(Method):
|
|
||||||
'''Save the contents of a buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
if w.buffer.changed():
|
|
||||||
w.buffer.save()
|
|
||||||
w.set_error("Wrote %s" % (w.buffer.path))
|
|
||||||
else:
|
|
||||||
w.set_error("(No changes need to be saved)")
|
|
||||||
class RelexBuffer(Method):
|
class RelexBuffer(Method):
|
||||||
'''Relex the buffer; this resets syntax highlighting'''
|
'''Relex the buffer; this resets syntax highlighting'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -321,6 +114,7 @@ class RelexBuffer(Method):
|
||||||
else:
|
else:
|
||||||
h.highlight(w.buffer.lines)
|
h.highlight(w.buffer.lines)
|
||||||
w.set_error("Buffer relexed.")
|
w.set_error("Buffer relexed.")
|
||||||
|
|
||||||
class ToggleWindow(Method):
|
class ToggleWindow(Method):
|
||||||
'''Move between visible windows'''
|
'''Move between visible windows'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -511,57 +305,6 @@ class DeleteRightSpace(Method):
|
||||||
if p > c:
|
if p > c:
|
||||||
w.kill(c, p)
|
w.kill(c, p)
|
||||||
|
|
||||||
# random stuff
|
|
||||||
class DumpRegions(Method):
|
|
||||||
'''debug region highlighting'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
lines = []
|
|
||||||
for (w, p1, p2) in w.application.highlighted_ranges:
|
|
||||||
lines.append("%r %s %s" % (w, p1, p2))
|
|
||||||
output = "\n".join(lines)
|
|
||||||
w.application.data_buffer("region-dump", output, switch_to=True)
|
|
||||||
class DumpMarkers(Method):
|
|
||||||
'''Dump all tab markers (tab debugging)'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
lines = []
|
|
||||||
if w.mode.tabber:
|
|
||||||
keys = w.mode.tabber.lines.keys()
|
|
||||||
keys.sort()
|
|
||||||
for i in keys:
|
|
||||||
line = w.mode.tabber.lines[i]
|
|
||||||
lines.append("LINE %d: %r" % (i, line))
|
|
||||||
lines.append(" %s" % repr(w.mode.tabber.record[i]))
|
|
||||||
else:
|
|
||||||
lines.append("no tokens")
|
|
||||||
output = "\n".join(lines)
|
|
||||||
w.application.data_buffer("marker-dump", output, switch_to=True)
|
|
||||||
class DumpTokens(Method):
|
|
||||||
'''Dump all lexical tokens (syntax highlighting debugging)'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
modename = w.mode.name()
|
|
||||||
lines = []
|
|
||||||
if modename in w.buffer.highlights:
|
|
||||||
tokens = w.buffer.highlights[modename].tokens
|
|
||||||
for i in range(0, len(tokens)):
|
|
||||||
lines.append("LINE %d" % i)
|
|
||||||
group = tokens[i]
|
|
||||||
for token in group:
|
|
||||||
fqname = token.fqname()
|
|
||||||
p1 = Point(token.x, token.y)
|
|
||||||
if token.parent is None:
|
|
||||||
pcoord = ''
|
|
||||||
else:
|
|
||||||
pcoord = '[%d, %d]' % (token.parent.x, token.parent.y)
|
|
||||||
if fqname in w.mode.ghist and p1 in w.mode.ghist[fqname]:
|
|
||||||
g = '[' + w.mode.ghist[fqname][p1].name() + ']'
|
|
||||||
else:
|
|
||||||
g = ''
|
|
||||||
fields = (str(p1), pcoord, token.fqname(), g, token.string)
|
|
||||||
lines.append(' %-10s %-10s %-20s %-10s %r' % fields)
|
|
||||||
else:
|
|
||||||
lines.append("no tokens")
|
|
||||||
output = "\n".join(lines)
|
|
||||||
w.application.data_buffer("token-dump", output, switch_to=True)
|
|
||||||
class MetaX(Method):
|
class MetaX(Method):
|
||||||
'''Invoke commands by name'''
|
'''Invoke commands by name'''
|
||||||
args = [Argument('method', datatype="method", prompt="M-x ")]
|
args = [Argument('method', datatype="method", prompt="M-x ")]
|
||||||
|
@ -598,16 +341,25 @@ class InsertSpace(Method):
|
||||||
'''Insert space into buffer at the cursor'''
|
'''Insert space into buffer at the cursor'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
w.insert_string_at_cursor(' ')
|
w.insert_string_at_cursor(' ')
|
||||||
class GetIndentionLevel(Method):
|
|
||||||
'''Calculate the indention level for this line'''
|
class InsertSquotes(Method):
|
||||||
|
'''Insert a pair of single-quotes into the buffer'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
cursor = w.logical_cursor()
|
w.insert_string_at_cursor("''")
|
||||||
if not w.mode.tabber:
|
w.backward()
|
||||||
w.set_error('No tabber available')
|
class InsertDquotes(Method):
|
||||||
return
|
'''Insert a pair of double-quotes into the buffer'''
|
||||||
else:
|
def _execute(self, w, **vargs):
|
||||||
i = w.mode.tabber.get_level(cursor.y)
|
w.insert_string_at_cursor('""')
|
||||||
w.set_error('Indention level: %r' % i)
|
w.backward()
|
||||||
|
class InsertEscapedSquote(Method):
|
||||||
|
'''Insert an escaped single-quote'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.insert_string_at_cursor("\\'")
|
||||||
|
class InsertEscapedDquote(Method):
|
||||||
|
'''Insert an escaped double-quote'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.insert_string_at_cursor('\\"')
|
||||||
|
|
||||||
class InsertTab(Method):
|
class InsertTab(Method):
|
||||||
'''Insert tab into buffer, or tabbify line, depending on mode'''
|
'''Insert tab into buffer, or tabbify line, depending on mode'''
|
||||||
|
@ -627,6 +379,7 @@ class InsertTab(Method):
|
||||||
w.insert_string(Point(0, cursor.y), ' ' * i)
|
w.insert_string(Point(0, cursor.y), ' ' * i)
|
||||||
else:
|
else:
|
||||||
w.goto(Point(j, cursor.y))
|
w.goto(Point(j, cursor.y))
|
||||||
|
|
||||||
class KillWhitespace(Method):
|
class KillWhitespace(Method):
|
||||||
'''Delete leading whitespace on current line'''
|
'''Delete leading whitespace on current line'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -645,6 +398,16 @@ class TabBuffer(Method):
|
||||||
w.goto_line(i)
|
w.goto_line(i)
|
||||||
it.execute(w)
|
it.execute(w)
|
||||||
w.goto_line(y)
|
w.goto_line(y)
|
||||||
|
class GetIndentionLevel(Method):
|
||||||
|
'''Calculate the indention level for this line'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
cursor = w.logical_cursor()
|
||||||
|
if not w.mode.tabber:
|
||||||
|
w.set_error('No tabber available')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
i = w.mode.tabber.get_level(cursor.y)
|
||||||
|
w.set_error('Indention level: %r' % i)
|
||||||
|
|
||||||
# commenting
|
# commenting
|
||||||
class CommentRegion(Method):
|
class CommentRegion(Method):
|
||||||
|
@ -899,79 +662,6 @@ class Redo(Method):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
w.set_error("%s" % (e))
|
w.set_error("%s" % (e))
|
||||||
|
|
||||||
# w navigation methods
|
|
||||||
class StartOfLine(Method):
|
|
||||||
'''Move the cursor to the start of the current line'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.start_of_line()
|
|
||||||
class EndOfLine(Method):
|
|
||||||
'''Move the cursor to the end of the current line'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.end_of_line()
|
|
||||||
class Forward(Method):
|
|
||||||
'''Move the cursor right one character'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.forward()
|
|
||||||
class Backward(Method):
|
|
||||||
'''Move the cursor left one character'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.backward()
|
|
||||||
class NextLine(Method):
|
|
||||||
'''Move the cursor down one line'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.next_line()
|
|
||||||
class PreviousLine(Method):
|
|
||||||
'''Move the cursor up one line'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.previous_line()
|
|
||||||
class PageUp(Method):
|
|
||||||
'''Move the cursor up one page'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.page_up()
|
|
||||||
class PageDown(Method):
|
|
||||||
'''Move the cursor down one page'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.page_down()
|
|
||||||
class GotoBeginning(Method):
|
|
||||||
'''Move the cursor to the beginning of the buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.goto_beginning()
|
|
||||||
class GotoEnd(Method):
|
|
||||||
'''Move the cursor to the end of the buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.goto_end()
|
|
||||||
class RightWord(Method):
|
|
||||||
'''Move the cursor to the start of the word to the right'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.right_word()
|
|
||||||
class LeftWord(Method):
|
|
||||||
'''Move the cursor to the start of the word to the left'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.left_word()
|
|
||||||
class NextSection(Method):
|
|
||||||
'''Move the cursor to the next section'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
cursor = w.logical_cursor()
|
|
||||||
i = cursor.y + 1
|
|
||||||
seen_null_line = False
|
|
||||||
while i < len(w.buffer.lines):
|
|
||||||
if seen_null_line:
|
|
||||||
w.goto_line(i)
|
|
||||||
break
|
|
||||||
seen_null_line = regex.whitespace.match(w.buffer.lines[i])
|
|
||||||
i += 1
|
|
||||||
class PreviousSection(Method):
|
|
||||||
'''Move the cursor to the previous section'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
cursor = w.logical_cursor()
|
|
||||||
i = cursor.y - 1
|
|
||||||
seen_null_line = False
|
|
||||||
while i >= 0:
|
|
||||||
if seen_null_line:
|
|
||||||
w.goto_line(i)
|
|
||||||
break
|
|
||||||
seen_null_line = regex.whitespace.match(w.buffer.lines[i])
|
|
||||||
i -= 1
|
|
||||||
class UnindentBlock(Method):
|
class UnindentBlock(Method):
|
||||||
'''Prepend 4 spaces to each line in region'''
|
'''Prepend 4 spaces to each line in region'''
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -1011,32 +701,6 @@ class IndentBlock(Method):
|
||||||
w.buffer.delete(Point(0, p1.y), Point(0, p2.y))
|
w.buffer.delete(Point(0, p1.y), Point(0, p2.y))
|
||||||
w.buffer.insert_string(Point(0, p1.y), '\n'.join(lines) + '\n')
|
w.buffer.insert_string(Point(0, p1.y), '\n'.join(lines) + '\n')
|
||||||
|
|
||||||
class OpenConsole(Method):
|
|
||||||
'''Evaluate python expressions (for advanced use and debugging only)'''
|
|
||||||
def execute(self, w, **vargs):
|
|
||||||
a = w.application
|
|
||||||
if not a.has_buffer_name('*Console*'):
|
|
||||||
b = buffer.ConsoleBuffer()
|
|
||||||
a.add_buffer(b)
|
|
||||||
window.Window(b, a)
|
|
||||||
b = a.bufferlist.get_buffer_by_name('*Console*')
|
|
||||||
if a.window().buffer is not b:
|
|
||||||
a.switch_buffer(b)
|
|
||||||
f = lambda x: None
|
|
||||||
w.application.open_mini_buffer('>>> ', f, self, None, 'consolemini')
|
|
||||||
|
|
||||||
class ShellCmd(Method):
|
|
||||||
'''Run a command in a shell and put the output in a new buffer'''
|
|
||||||
args = [Argument("cmd", type=type(""), prompt="$ ", datatype='shell')]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
cmd = "PBUF='%s'; %s" % (w.buffer.name(), vargs['cmd'])
|
|
||||||
(status, data) = commands.getstatusoutput(cmd)
|
|
||||||
if status == 0:
|
|
||||||
mesg = 'ok'
|
|
||||||
else:
|
|
||||||
mesg = 'error'
|
|
||||||
data += "\nprocess exited with status %d (%s)" % (status, mesg)
|
|
||||||
w.application.data_buffer("*Shell*", data, switch_to=True)
|
|
||||||
class FileDiff(Method):
|
class FileDiff(Method):
|
||||||
'''diff the buffer's contents with the given file'''
|
'''diff the buffer's contents with the given file'''
|
||||||
args = [Argument("path", type=type(""), prompt="Filename: ", datatype='path')]
|
args = [Argument("path", type=type(""), prompt="Filename: ", datatype='path')]
|
||||||
|
@ -1062,109 +726,6 @@ class FileDiff(Method):
|
||||||
w.application.data_buffer("*Diff*", errdata, switch_to=True)
|
w.application.data_buffer("*Diff*", errdata, switch_to=True)
|
||||||
w.set_error("There was an error: %d exited with status %s" % (pid, status))
|
w.set_error("There was an error: %d exited with status %s" % (pid, status))
|
||||||
|
|
||||||
class ShowBindingsBuffer(Method):
|
|
||||||
'''Dump all keybindings for current mode into a new buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
lines = []
|
|
||||||
mode_name = w.mode.name()
|
|
||||||
|
|
||||||
lines.append('Key bindings for mode %r:' % (mode_name))
|
|
||||||
lines.append('')
|
|
||||||
|
|
||||||
names_to_sequences = {}
|
|
||||||
|
|
||||||
seq_len = len('BINDINGS')
|
|
||||||
name_len = len('ACTION')
|
|
||||||
for seq in w.mode.bindings:
|
|
||||||
name = w.mode.bindings[seq]
|
|
||||||
if name.startswith('insert-string-'):
|
|
||||||
# we aren't going to show all the generic keypress actions
|
|
||||||
continue
|
|
||||||
# determine this for formatting
|
|
||||||
seq_len = max(seq_len, len(seq))
|
|
||||||
name_len = max(name_len, len(name))
|
|
||||||
|
|
||||||
# set up our new data structure
|
|
||||||
names_to_sequences.setdefault(name, [])
|
|
||||||
names_to_sequences[name].append(seq)
|
|
||||||
|
|
||||||
# generate the format string (note the 'meta formatting')
|
|
||||||
format_str = '%%-%ds %%-%ds %%s' % (seq_len, name_len)
|
|
||||||
|
|
||||||
lines.append(format_str % ('BINDINGS', 'ACTIONS', 'HELP'))
|
|
||||||
|
|
||||||
names = names_to_sequences.keys()
|
|
||||||
names.sort()
|
|
||||||
for name in names:
|
|
||||||
sequences = names_to_sequences[name]
|
|
||||||
sequences.sort()
|
|
||||||
seq = sequences[0]
|
|
||||||
help = w.application.methods[name].help
|
|
||||||
if help is None:
|
|
||||||
help = ''
|
|
||||||
|
|
||||||
lines.append(format_str % (seq, name, help))
|
|
||||||
for seq2 in sequences[1:]:
|
|
||||||
lines.append(format_str % (seq2, '', ''))
|
|
||||||
|
|
||||||
data = '\n'.join(lines)
|
|
||||||
w.application.data_buffer("*Bindings-Help*", data, switch_to=True)
|
|
||||||
|
|
||||||
class CmdHelpBuffer(Method):
|
|
||||||
'''Get help with the specified command'''
|
|
||||||
args = [Argument('method', datatype="method", prompt="Help for command: ")]
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
lines = []
|
|
||||||
name = vargs['method']
|
|
||||||
if name not in w.application.methods:
|
|
||||||
err = "No command called %r in mode %r" % (name, w.mode.name)
|
|
||||||
raise Exception, err
|
|
||||||
|
|
||||||
m = w.application.methods[name]
|
|
||||||
lines.append('HELP FOR %r' % name)
|
|
||||||
lines.append('')
|
|
||||||
|
|
||||||
# sequences
|
|
||||||
sequences = []
|
|
||||||
for seq in w.mode.bindings:
|
|
||||||
if w.mode.bindings[seq] == name:
|
|
||||||
sequences.append(seq)
|
|
||||||
sequences.sort()
|
|
||||||
lines.append('Keys bound to this command:')
|
|
||||||
for seq in sequences:
|
|
||||||
lines.append(' %s' % (seq))
|
|
||||||
lines.append('')
|
|
||||||
|
|
||||||
# arguments
|
|
||||||
if m.args:
|
|
||||||
lines.append('Arguments for this command:')
|
|
||||||
for arg in m.args:
|
|
||||||
if arg.datatype is None:
|
|
||||||
if arg.type == type(""):
|
|
||||||
t = 'str'
|
|
||||||
elif arg.type == type(0):
|
|
||||||
t = 'int'
|
|
||||||
elif arg.type == type(0.0):
|
|
||||||
t = 'float'
|
|
||||||
else:
|
|
||||||
t = 'str'
|
|
||||||
else:
|
|
||||||
t = arg.datatype
|
|
||||||
if arg.help:
|
|
||||||
lines.append(' %s %r: %s' % (t, arg.name, arg.help))
|
|
||||||
else:
|
|
||||||
lines.append(' %s %r' % (t, arg.name))
|
|
||||||
lines.append('')
|
|
||||||
|
|
||||||
# help text
|
|
||||||
lines.append('Help text for this command:')
|
|
||||||
h = m.help
|
|
||||||
if not h:
|
|
||||||
h = 'No help available'
|
|
||||||
lines.append(' %s' % h)
|
|
||||||
data = '\n'.join(lines)
|
|
||||||
w.application.data_buffer("*Command-Help*", data, switch_to=True)
|
|
||||||
|
|
||||||
class SetMode(Method):
|
class SetMode(Method):
|
||||||
'''Set the mode of the current buffer'''
|
'''Set the mode of the current buffer'''
|
||||||
args = [Argument('mode', datatype='mode', prompt="Enter new mode: ")]
|
args = [Argument('mode', datatype='mode', prompt="Enter new mode: ")]
|
||||||
|
@ -1174,16 +735,6 @@ class SetMode(Method):
|
||||||
w.set_mode(m)
|
w.set_mode(m)
|
||||||
w.set_error('Set mode to %r' % (mode_name))
|
w.set_error('Set mode to %r' % (mode_name))
|
||||||
|
|
||||||
class WhichCommand(Method):
|
|
||||||
'''Display which command is run for a given key-sequence'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
self.old_window = w
|
|
||||||
w.application.open_mini_buffer('Enter a key sequence to be explained: ',
|
|
||||||
lambda x: None,
|
|
||||||
self,
|
|
||||||
None,
|
|
||||||
'which')
|
|
||||||
|
|
||||||
class Cancel(Method):
|
class Cancel(Method):
|
||||||
'''Cancel command in-progress, and return to the main buffer'''
|
'''Cancel command in-progress, and return to the main buffer'''
|
||||||
def execute(self, w, **vargs):
|
def execute(self, w, **vargs):
|
||||||
|
@ -1207,29 +758,6 @@ class UnsplitWindow(Method):
|
||||||
w.application.single_slot()
|
w.application.single_slot()
|
||||||
w.set_error('Window has been unsplit back to one window!')
|
w.set_error('Window has been unsplit back to one window!')
|
||||||
|
|
||||||
class SomethingCrazy(Method):
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class InsertSquotes(Method):
|
|
||||||
'''Insert a pair of single-quotes into the buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.insert_string_at_cursor("''")
|
|
||||||
w.backward()
|
|
||||||
class InsertDquotes(Method):
|
|
||||||
'''Insert a pair of double-quotes into the buffer'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.insert_string_at_cursor('""')
|
|
||||||
w.backward()
|
|
||||||
class InsertEscapedSquote(Method):
|
|
||||||
'''Insert an escaped single-quote'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.insert_string_at_cursor("\\'")
|
|
||||||
class InsertEscapedDquote(Method):
|
|
||||||
'''Insert an escaped double-quote'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
w.insert_string_at_cursor('\\"')
|
|
||||||
|
|
||||||
class CloseTag(Method):
|
class CloseTag(Method):
|
||||||
mytag = ')'
|
mytag = ')'
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
@ -1290,15 +818,6 @@ class CloseBrace(CloseTag):
|
||||||
class CloseBracket(CloseTag):
|
class CloseBracket(CloseTag):
|
||||||
mytag = ']'
|
mytag = ']'
|
||||||
|
|
||||||
class GetToken(Method):
|
|
||||||
'''View type and data of the "current" token'''
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
token = w.get_token()
|
|
||||||
if token is None:
|
|
||||||
w.set_error('No Token')
|
|
||||||
else:
|
|
||||||
w.set_error('Token: %r (%s)' % (token.string, token.fqname()))
|
|
||||||
|
|
||||||
class RegisterSave(Method):
|
class RegisterSave(Method):
|
||||||
MAX_TXT = 30
|
MAX_TXT = 30
|
||||||
MAX_REG = 20
|
MAX_REG = 20
|
||||||
|
@ -1334,129 +853,3 @@ class RegisterRestore(Method):
|
||||||
if len(name) > self.MAX_REG:
|
if len(name) > self.MAX_REG:
|
||||||
name = name[0:self.MAX_REG] + '...'
|
name = name[0:self.MAX_REG] + '...'
|
||||||
w.set_error('Restored %r from register %r' % (text2, name2))
|
w.set_error('Restored %r from register %r' % (text2, name2))
|
||||||
|
|
||||||
class Pipe(Method):
|
|
||||||
'''Pipe the buffer's contents through the command, and display the output in a new buffer'''
|
|
||||||
args = [Argument('cmd', datatype="str", prompt="Command: ")]
|
|
||||||
def _parse(self, w, **vargs):
|
|
||||||
m = regex.shell_command.match(vargs['cmd'])
|
|
||||||
if m:
|
|
||||||
prog = m.group(0)
|
|
||||||
return (prog, vargs['cmd'])
|
|
||||||
else:
|
|
||||||
return (None, None)
|
|
||||||
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
(prog, cmd) = self._parse(w, **vargs)
|
|
||||||
if prog is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
|
|
||||||
pid = pipe.pid
|
|
||||||
|
|
||||||
indata = w.buffer.make_string()
|
|
||||||
pipe.stdin.write(indata)
|
|
||||||
pipe.stdin.close()
|
|
||||||
|
|
||||||
outdata = pipe.stdout.read()
|
|
||||||
status = pipe.wait() >> 8
|
|
||||||
|
|
||||||
bufname = '*%s*' % self.name.title()
|
|
||||||
w.application.data_buffer(bufname, outdata, switch_to=True)
|
|
||||||
w.set_error("%s exited with status %d" % (prog, status))
|
|
||||||
|
|
||||||
class Grep(Pipe):
|
|
||||||
'''Grep the buffer's contents for instances of a pattern, and display them in a new buffer'''
|
|
||||||
args = [Argument('pattern', datatype="str", prompt="Pattern: ")]
|
|
||||||
def _parse(self, w, **vargs):
|
|
||||||
return ('grep', ('/usr/bin/grep', '-E', '-n', vargs['pattern']))
|
|
||||||
|
|
||||||
class Exec(Method):
|
|
||||||
args = [Argument('cmd', datatype="str", prompt="Exec: ")]
|
|
||||||
def _doit(self, w, path, cmd):
|
|
||||||
try:
|
|
||||||
cmd = cmd % path
|
|
||||||
except:
|
|
||||||
w.set_error("Malformed command: %r" % cmd)
|
|
||||||
return
|
|
||||||
(status, output) = commands.getstatusoutput(cmd)
|
|
||||||
bufname = '*%s*' % self.name.title()
|
|
||||||
w.application.data_buffer(bufname, output, switch_to=True)
|
|
||||||
w.set_error("Shell exited with %d" % status)
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
if w.buffer.btype == 'dir':
|
|
||||||
name = dirutil.resolve_name(w)
|
|
||||||
path = dirutil.resolve_path(w)
|
|
||||||
self._doit(w, path, vargs['cmd'])
|
|
||||||
dirutil.find_name(w, name)
|
|
||||||
elif hasattr(w.buffer, 'path'):
|
|
||||||
path = w.buffer.path
|
|
||||||
self._doit(w, path, vargs['cmd'])
|
|
||||||
else:
|
|
||||||
w.set_error("Don't know how to exec: %r" % w.buffer)
|
|
||||||
return
|
|
||||||
|
|
||||||
class TokenComplete(Method):
|
|
||||||
'''Complete token names based on other tokens in the buffer'''
|
|
||||||
name_overrides = {}
|
|
||||||
def _min_completion(self, w, t):
|
|
||||||
h = w.get_highlighter()
|
|
||||||
minlen = None
|
|
||||||
if t.name in self.name_overrides:
|
|
||||||
ok = name_overrides[t.name]
|
|
||||||
else:
|
|
||||||
ok = (t.name,)
|
|
||||||
|
|
||||||
strings = {}
|
|
||||||
for line in h.tokens:
|
|
||||||
for t2 in line:
|
|
||||||
if t2 is t:
|
|
||||||
continue
|
|
||||||
elif False and t2.name not in ok:
|
|
||||||
continue
|
|
||||||
elif t2.string.startswith(t.string):
|
|
||||||
strings[t2.string] = 1
|
|
||||||
if minlen is None:
|
|
||||||
minlen = len(t2.string)
|
|
||||||
else:
|
|
||||||
minlen = min(minlen, len(t2.string))
|
|
||||||
|
|
||||||
strings = strings.keys()
|
|
||||||
if not strings:
|
|
||||||
return ([], t.string)
|
|
||||||
|
|
||||||
i = len(t.string)
|
|
||||||
while i < minlen:
|
|
||||||
c = strings[0][i]
|
|
||||||
for s in strings:
|
|
||||||
if s[i] != c:
|
|
||||||
return (strings, strings[0][:i])
|
|
||||||
i += 1
|
|
||||||
return (strings, strings[0][:minlen])
|
|
||||||
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
t = w.get_token2()
|
|
||||||
|
|
||||||
if t is None:
|
|
||||||
w.set_error("No token to complete!")
|
|
||||||
return
|
|
||||||
elif regex.reserved_token_names.match(t.name):
|
|
||||||
w.set_error("Will not complete reserved token")
|
|
||||||
return
|
|
||||||
|
|
||||||
(candidates, result) = self._min_completion(w, t)
|
|
||||||
|
|
||||||
if candidates:
|
|
||||||
p1 = Point(t.x, t.y)
|
|
||||||
p2 = Point(t.end_x(), t.y)
|
|
||||||
w.buffer.delete(p1, p2)
|
|
||||||
w.insert_string(p1, result)
|
|
||||||
|
|
||||||
if not candidates:
|
|
||||||
w.set_error("No completion: %r" % result)
|
|
||||||
elif len(candidates) == 1:
|
|
||||||
w.set_error("Unique completion: %r" % result)
|
|
||||||
elif result in candidates:
|
|
||||||
w.set_error("Ambiguous completion: %r" % candidates)
|
|
||||||
else:
|
|
||||||
w.set_error("Partial completion: %r" % candidates)
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class OpenFile(Method):
|
||||||
|
'''Open file in a new buffer, or go to file's open buffer'''
|
||||||
|
args = [Argument('filename', datatype="path", prompt="Open File: ",
|
||||||
|
default=default.path_dirname, load_default=True)]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
b = w.application.open_path(vargs['filename'])
|
||||||
|
SwitchBuffer().execute(w, buffername=b.name())
|
||||||
|
class OpenAesFile(Method):
|
||||||
|
'''Open AES encrypted file in a new buffer, or go to file's open buffer'''
|
||||||
|
args = [Argument('filename', datatype="path", prompt="Open AES File: "),
|
||||||
|
Argument('password', prompt="Use AES Password: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
b = w.application.open_path(vargs['filename'], 'aes', vargs['password'])
|
||||||
|
SwitchBuffer().execute(w, buffername=b.name())
|
||||||
|
return
|
||||||
|
|
||||||
|
class ViewBufferParent(Method):
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
b = w.buffer
|
||||||
|
if not hasattr(b, 'path'):
|
||||||
|
w.set_error('Buffer has no path')
|
||||||
|
elif b.path == '/':
|
||||||
|
w.set_error("Root directory has no parent")
|
||||||
|
else:
|
||||||
|
path = os.path.dirname(b.path)
|
||||||
|
w.application.methods['open-file'].execute(w, filename=path)
|
||||||
|
|
||||||
|
class SwitchBuffer(Method):
|
||||||
|
'''Switch to a different'''
|
||||||
|
args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ",
|
||||||
|
default=default.last_buffer)]
|
||||||
|
def _pre_execute(self, w, **vargs):
|
||||||
|
a = w.application
|
||||||
|
if len(a.bufferlist.buffers) < 1:
|
||||||
|
raise Exception, "No other buffers"
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
name = vargs['buffername']
|
||||||
|
buf = None
|
||||||
|
if w.application.has_buffer_name(name):
|
||||||
|
b = w.application.bufferlist.get_buffer_by_name(name)
|
||||||
|
w.application.switch_buffer(b)
|
||||||
|
else:
|
||||||
|
w.set_error("buffer %r was not found" % name)
|
||||||
|
class KillBuffer(Method):
|
||||||
|
'''Close the current buffer'''
|
||||||
|
force=False
|
||||||
|
args = [Argument('buffername', datatype="buffer", prompt="Kill Buffer: ",
|
||||||
|
default=default.current_buffer)]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
name = vargs['buffername']
|
||||||
|
a = w.application
|
||||||
|
assert name in a.bufferlist.buffer_names, "Buffer %r does not exist" % name
|
||||||
|
assert name != '*Scratch*', "Can't kill scratch buffer"
|
||||||
|
self._to_kill = a.bufferlist.buffer_names[name]
|
||||||
|
self._old_window = w
|
||||||
|
if self.force or not self._to_kill.changed():
|
||||||
|
self._doit()
|
||||||
|
else:
|
||||||
|
self._prompt = "Buffer has unsaved changes; kill anyway? "
|
||||||
|
a.open_mini_buffer(self._prompt, self._callback)
|
||||||
|
def _doit(self):
|
||||||
|
a = self._old_window.application
|
||||||
|
b = self._to_kill
|
||||||
|
if a.bufferlist.is_buffer_visible(b):
|
||||||
|
a.bufferlist.set_slot(a.active_slot, a.bufferlist.hidden_buffers[0])
|
||||||
|
a.bufferlist.remove_buffer(b)
|
||||||
|
b.close()
|
||||||
|
def _callback(self, v):
|
||||||
|
a = self._old_window.application
|
||||||
|
if v == 'yes':
|
||||||
|
self._doit()
|
||||||
|
a.close_mini_buffer()
|
||||||
|
elif v == 'no':
|
||||||
|
a.close_mini_buffer()
|
||||||
|
else:
|
||||||
|
a.close_mini_buffer()
|
||||||
|
a.set_error('Please type "yes" or "no"')
|
||||||
|
|
||||||
|
class ForceKillBuffer(KillBuffer):
|
||||||
|
force=True
|
||||||
|
args = [Argument('buffername', datatype="buffer", prompt="Force Kill Buffer: ",
|
||||||
|
default=default.current_buffer)]
|
||||||
|
class ListBuffers(Method):
|
||||||
|
'''List all open buffers in a new buffer'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
bl = w.application.bufferlist
|
||||||
|
bnames = [b.name() for b in bl.buffers]
|
||||||
|
bnames.sort()
|
||||||
|
data = '\n'.join(bnames)
|
||||||
|
w.application.data_buffer("*Buffers*", data, switch_to=True)
|
||||||
|
class SaveBufferAs(Method):
|
||||||
|
'''Save the contents of a buffer to the specified path'''
|
||||||
|
args = [Argument('path', datatype="path", prompt="Write file: ",
|
||||||
|
default=default.current_working_dir, load_default=True)]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
curr_buffer = w.buffer
|
||||||
|
curr_buffer_name = curr_buffer.name()
|
||||||
|
data = curr_buffer.make_string()
|
||||||
|
path = os.path.realpath(os.path.expanduser(vargs['path']))
|
||||||
|
w.set_error("got %r (%d)" % (path, len(data)))
|
||||||
|
if w.application.has_buffer_name(path):
|
||||||
|
w.set_error("buffer for %r is already open" % path)
|
||||||
|
return
|
||||||
|
w.application.file_buffer(path, data, switch_to=True)
|
||||||
|
if curr_buffer_name != '*Scratch*':
|
||||||
|
w.application.methods['kill-buffer'].execute(w, buffername=curr_buffer_name)
|
||||||
|
else:
|
||||||
|
curr_buffer.set_data('')
|
||||||
|
w.set_error('Wrote %r' % path)
|
||||||
|
class SaveBuffer(Method):
|
||||||
|
'''Save the contents of a buffer'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
if w.buffer.changed():
|
||||||
|
w.buffer.save()
|
||||||
|
w.set_error("Wrote %s" % (w.buffer.path))
|
||||||
|
else:
|
||||||
|
w.set_error("(No changes need to be saved)")
|
|
@ -0,0 +1,132 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class ShowBindingsBuffer(Method):
|
||||||
|
'''Dump all keybindings for current mode into a new buffer'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
lines = []
|
||||||
|
mode_name = w.mode.name()
|
||||||
|
|
||||||
|
lines.append('Key bindings for mode %r:' % (mode_name))
|
||||||
|
lines.append('')
|
||||||
|
|
||||||
|
names_to_sequences = {}
|
||||||
|
|
||||||
|
seq_len = len('BINDINGS')
|
||||||
|
name_len = len('ACTION')
|
||||||
|
for seq in w.mode.bindings:
|
||||||
|
name = w.mode.bindings[seq]
|
||||||
|
if name.startswith('insert-string-'):
|
||||||
|
# we aren't going to show all the generic keypress actions
|
||||||
|
continue
|
||||||
|
# determine this for formatting
|
||||||
|
seq_len = max(seq_len, len(seq))
|
||||||
|
name_len = max(name_len, len(name))
|
||||||
|
|
||||||
|
# set up our new data structure
|
||||||
|
names_to_sequences.setdefault(name, [])
|
||||||
|
names_to_sequences[name].append(seq)
|
||||||
|
|
||||||
|
# generate the format string (note the 'meta formatting')
|
||||||
|
format_str = '%%-%ds %%-%ds %%s' % (seq_len, name_len)
|
||||||
|
|
||||||
|
lines.append(format_str % ('BINDINGS', 'ACTIONS', 'HELP'))
|
||||||
|
|
||||||
|
names = names_to_sequences.keys()
|
||||||
|
names.sort()
|
||||||
|
for name in names:
|
||||||
|
sequences = names_to_sequences[name]
|
||||||
|
sequences.sort()
|
||||||
|
seq = sequences[0]
|
||||||
|
help = w.application.methods[name].help
|
||||||
|
if help is None:
|
||||||
|
help = ''
|
||||||
|
|
||||||
|
lines.append(format_str % (seq, name, help))
|
||||||
|
for seq2 in sequences[1:]:
|
||||||
|
lines.append(format_str % (seq2, '', ''))
|
||||||
|
|
||||||
|
data = '\n'.join(lines)
|
||||||
|
w.application.data_buffer("*Bindings-Help*", data, switch_to=True)
|
||||||
|
|
||||||
|
class CmdHelpBuffer(Method):
|
||||||
|
'''Get help with the specified command'''
|
||||||
|
args = [Argument('method', datatype="method", prompt="Help for command: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
lines = []
|
||||||
|
name = vargs['method']
|
||||||
|
if name not in w.application.methods:
|
||||||
|
err = "No command called %r in mode %r" % (name, w.mode.name)
|
||||||
|
raise Exception, err
|
||||||
|
|
||||||
|
m = w.application.methods[name]
|
||||||
|
lines.append('HELP FOR %r' % name)
|
||||||
|
lines.append('')
|
||||||
|
|
||||||
|
# sequences
|
||||||
|
sequences = []
|
||||||
|
for seq in w.mode.bindings:
|
||||||
|
if w.mode.bindings[seq] == name:
|
||||||
|
sequences.append(seq)
|
||||||
|
sequences.sort()
|
||||||
|
lines.append('Keys bound to this command:')
|
||||||
|
for seq in sequences:
|
||||||
|
lines.append(' %s' % (seq))
|
||||||
|
lines.append('')
|
||||||
|
|
||||||
|
# arguments
|
||||||
|
if m.args:
|
||||||
|
lines.append('Arguments for this command:')
|
||||||
|
for arg in m.args:
|
||||||
|
if arg.datatype is None:
|
||||||
|
if arg.type == type(""):
|
||||||
|
t = 'str'
|
||||||
|
elif arg.type == type(0):
|
||||||
|
t = 'int'
|
||||||
|
elif arg.type == type(0.0):
|
||||||
|
t = 'float'
|
||||||
|
else:
|
||||||
|
t = 'str'
|
||||||
|
else:
|
||||||
|
t = arg.datatype
|
||||||
|
if arg.help:
|
||||||
|
lines.append(' %s %r: %s' % (t, arg.name, arg.help))
|
||||||
|
else:
|
||||||
|
lines.append(' %s %r' % (t, arg.name))
|
||||||
|
lines.append('')
|
||||||
|
|
||||||
|
# help text
|
||||||
|
lines.append('Help text for this command:')
|
||||||
|
h = m.help
|
||||||
|
if not h:
|
||||||
|
h = 'No help available'
|
||||||
|
lines.append(' %s' % h)
|
||||||
|
data = '\n'.join(lines)
|
||||||
|
w.application.data_buffer("*Command-Help*", data, switch_to=True)
|
||||||
|
|
||||||
|
class WhichCommand(Method):
|
||||||
|
'''Display which command is run for a given key-sequence'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
self.old_window = w
|
||||||
|
w.application.open_mini_buffer('Enter a key sequence to be explained: ',
|
||||||
|
lambda x: None,
|
||||||
|
self,
|
||||||
|
None,
|
||||||
|
'which')
|
||||||
|
|
||||||
|
class AboutPmacs(Method):
|
||||||
|
'''print some information about pmacs'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
a = w.application
|
||||||
|
if not a.has_buffer_name('*About*'):
|
||||||
|
b = buffer.AboutBuffer()
|
||||||
|
a.add_buffer(b)
|
||||||
|
window.Window(b, a)
|
||||||
|
b = a.bufferlist.get_buffer_by_name('*About*')
|
||||||
|
if a.window().buffer is not b:
|
||||||
|
a.switch_buffer(b)
|
|
@ -0,0 +1,148 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class DumpRegions(Method):
|
||||||
|
'''debug region highlighting'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
lines = []
|
||||||
|
for (w, p1, p2) in w.application.highlighted_ranges:
|
||||||
|
lines.append("%r %s %s" % (w, p1, p2))
|
||||||
|
output = "\n".join(lines)
|
||||||
|
w.application.data_buffer("region-dump", output, switch_to=True)
|
||||||
|
|
||||||
|
class DumpMarkers(Method):
|
||||||
|
'''Dump all tab markers (tab debugging)'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
lines = []
|
||||||
|
if w.mode.tabber:
|
||||||
|
keys = w.mode.tabber.lines.keys()
|
||||||
|
keys.sort()
|
||||||
|
for i in keys:
|
||||||
|
line = w.mode.tabber.lines[i]
|
||||||
|
lines.append("LINE %d: %r" % (i, line))
|
||||||
|
lines.append(" %s" % repr(w.mode.tabber.record[i]))
|
||||||
|
else:
|
||||||
|
lines.append("no tokens")
|
||||||
|
output = "\n".join(lines)
|
||||||
|
w.application.data_buffer("marker-dump", output, switch_to=True)
|
||||||
|
|
||||||
|
class DumpTokens(Method):
|
||||||
|
'''Dump all lexical tokens (syntax highlighting debugging)'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
modename = w.mode.name()
|
||||||
|
lines = []
|
||||||
|
if modename in w.buffer.highlights:
|
||||||
|
tokens = w.buffer.highlights[modename].tokens
|
||||||
|
for i in range(0, len(tokens)):
|
||||||
|
lines.append("LINE %d" % i)
|
||||||
|
group = tokens[i]
|
||||||
|
for token in group:
|
||||||
|
fqname = token.fqname()
|
||||||
|
p1 = Point(token.x, token.y)
|
||||||
|
if token.parent is None:
|
||||||
|
pcoord = ''
|
||||||
|
else:
|
||||||
|
pcoord = '[%d, %d]' % (token.parent.x, token.parent.y)
|
||||||
|
if fqname in w.mode.ghist and p1 in w.mode.ghist[fqname]:
|
||||||
|
g = '[' + w.mode.ghist[fqname][p1].name() + ']'
|
||||||
|
else:
|
||||||
|
g = ''
|
||||||
|
fields = (str(p1), pcoord, token.fqname(), g, token.string)
|
||||||
|
lines.append(' %-10s %-10s %-20s %-10s %r' % fields)
|
||||||
|
else:
|
||||||
|
lines.append("no tokens")
|
||||||
|
output = "\n".join(lines)
|
||||||
|
w.application.data_buffer("token-dump", output, switch_to=True)
|
||||||
|
|
||||||
|
class GetToken(Method):
|
||||||
|
'''View type and data of the "current" token'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
token = w.get_token()
|
||||||
|
if token is None:
|
||||||
|
w.set_error('No Token')
|
||||||
|
else:
|
||||||
|
w.set_error('Token: %r (%s)' % (token.string, token.fqname()))
|
||||||
|
|
||||||
|
class TokenComplete(Method):
|
||||||
|
'''Complete token names based on other tokens in the buffer'''
|
||||||
|
name_overrides = {}
|
||||||
|
def _min_completion(self, w, t):
|
||||||
|
h = w.get_highlighter()
|
||||||
|
minlen = None
|
||||||
|
if t.name in self.name_overrides:
|
||||||
|
ok = name_overrides[t.name]
|
||||||
|
else:
|
||||||
|
ok = (t.name,)
|
||||||
|
|
||||||
|
strings = {}
|
||||||
|
for line in h.tokens:
|
||||||
|
for t2 in line:
|
||||||
|
if t2 is t:
|
||||||
|
continue
|
||||||
|
elif False and t2.name not in ok:
|
||||||
|
continue
|
||||||
|
elif t2.string.startswith(t.string):
|
||||||
|
strings[t2.string] = 1
|
||||||
|
if minlen is None:
|
||||||
|
minlen = len(t2.string)
|
||||||
|
else:
|
||||||
|
minlen = min(minlen, len(t2.string))
|
||||||
|
|
||||||
|
strings = strings.keys()
|
||||||
|
if not strings:
|
||||||
|
return ([], t.string)
|
||||||
|
|
||||||
|
i = len(t.string)
|
||||||
|
while i < minlen:
|
||||||
|
c = strings[0][i]
|
||||||
|
for s in strings:
|
||||||
|
if s[i] != c:
|
||||||
|
return (strings, strings[0][:i])
|
||||||
|
i += 1
|
||||||
|
return (strings, strings[0][:minlen])
|
||||||
|
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
t = w.get_token2()
|
||||||
|
|
||||||
|
if t is None:
|
||||||
|
w.set_error("No token to complete!")
|
||||||
|
return
|
||||||
|
elif regex.reserved_token_names.match(t.name):
|
||||||
|
w.set_error("Will not complete reserved token")
|
||||||
|
return
|
||||||
|
|
||||||
|
(candidates, result) = self._min_completion(w, t)
|
||||||
|
|
||||||
|
if candidates:
|
||||||
|
p1 = Point(t.x, t.y)
|
||||||
|
p2 = Point(t.end_x(), t.y)
|
||||||
|
w.buffer.delete(p1, p2)
|
||||||
|
w.insert_string(p1, result)
|
||||||
|
|
||||||
|
if not candidates:
|
||||||
|
w.set_error("No completion: %r" % result)
|
||||||
|
elif len(candidates) == 1:
|
||||||
|
w.set_error("Unique completion: %r" % result)
|
||||||
|
elif result in candidates:
|
||||||
|
w.set_error("Ambiguous completion: %r" % candidates)
|
||||||
|
else:
|
||||||
|
w.set_error("Partial completion: %r" % candidates)
|
||||||
|
|
||||||
|
class OpenConsole(Method):
|
||||||
|
'''Evaluate python expressions (for advanced use and debugging only)'''
|
||||||
|
def execute(self, w, **vargs):
|
||||||
|
a = w.application
|
||||||
|
if not a.has_buffer_name('*Console*'):
|
||||||
|
b = buffer.ConsoleBuffer()
|
||||||
|
a.add_buffer(b)
|
||||||
|
window.Window(b, a)
|
||||||
|
b = a.bufferlist.get_buffer_by_name('*Console*')
|
||||||
|
if a.window().buffer is not b:
|
||||||
|
a.switch_buffer(b)
|
||||||
|
f = lambda x: None
|
||||||
|
w.application.open_mini_buffer('>>> ', f, self, None, 'consolemini')
|
|
@ -0,0 +1,118 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class StartOfLine(Method):
|
||||||
|
'''Move the cursor to the start of the current line'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.start_of_line()
|
||||||
|
class EndOfLine(Method):
|
||||||
|
'''Move the cursor to the end of the current line'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.end_of_line()
|
||||||
|
|
||||||
|
class Forward(Method):
|
||||||
|
'''Move the cursor right one character'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.forward()
|
||||||
|
class Backward(Method):
|
||||||
|
'''Move the cursor left one character'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.backward()
|
||||||
|
|
||||||
|
class NextLine(Method):
|
||||||
|
'''Move the cursor down one line'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.next_line()
|
||||||
|
class PreviousLine(Method):
|
||||||
|
'''Move the cursor up one line'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.previous_line()
|
||||||
|
|
||||||
|
class PageUp(Method):
|
||||||
|
'''Move the cursor up one page'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.page_up()
|
||||||
|
class PageDown(Method):
|
||||||
|
'''Move the cursor down one page'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.page_down()
|
||||||
|
|
||||||
|
class GotoBeginning(Method):
|
||||||
|
'''Move the cursor to the beginning of the buffer'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.goto_beginning()
|
||||||
|
class GotoEnd(Method):
|
||||||
|
'''Move the cursor to the end of the buffer'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.goto_end()
|
||||||
|
|
||||||
|
class RightWord(Method):
|
||||||
|
'''Move the cursor to the start of the word to the right'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.right_word()
|
||||||
|
class LeftWord(Method):
|
||||||
|
'''Move the cursor to the start of the word to the left'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.left_word()
|
||||||
|
|
||||||
|
class NextSection(Method):
|
||||||
|
'''Move the cursor to the next section'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
cursor = w.logical_cursor()
|
||||||
|
i = cursor.y + 1
|
||||||
|
seen_null_line = False
|
||||||
|
while i < len(w.buffer.lines):
|
||||||
|
if seen_null_line:
|
||||||
|
w.goto_line(i)
|
||||||
|
break
|
||||||
|
seen_null_line = regex.whitespace.match(w.buffer.lines[i])
|
||||||
|
i += 1
|
||||||
|
class PreviousSection(Method):
|
||||||
|
'''Move the cursor to the previous section'''
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
cursor = w.logical_cursor()
|
||||||
|
i = cursor.y - 1
|
||||||
|
seen_null_line = False
|
||||||
|
while i >= 0:
|
||||||
|
if seen_null_line:
|
||||||
|
w.goto_line(i)
|
||||||
|
break
|
||||||
|
seen_null_line = regex.whitespace.match(w.buffer.lines[i])
|
||||||
|
i -= 1
|
||||||
|
|
||||||
|
class GotoChar(Method):
|
||||||
|
'''Jump to the specified character'''
|
||||||
|
args = [Argument("charno", type=type(0), prompt="Goto char: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.goto_char(vargs["charno"])
|
||||||
|
|
||||||
|
class ForwardChars(Method):
|
||||||
|
'''Move forward the specified number of characters'''
|
||||||
|
args = [Argument("charno", type=type(0), prompt="Forward chars: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.forward_chars(vargs["charno"])
|
||||||
|
|
||||||
|
class GotoLine(Method):
|
||||||
|
'''Jump to the specified line number'''
|
||||||
|
args = [Argument("lineno", type=type(0), prompt="Goto line: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
n = vargs["lineno"]
|
||||||
|
if n < 0:
|
||||||
|
n = len(w.buffer.lines) + n + 1
|
||||||
|
if n > len(w.buffer.lines):
|
||||||
|
n = len(w.buffer.lines)
|
||||||
|
elif n < 1:
|
||||||
|
n = 1
|
||||||
|
w.goto_line(n)
|
||||||
|
|
||||||
|
class ForwardLines(Method):
|
||||||
|
'''Move forward the specified number of characters'''
|
||||||
|
args = [Argument("lineno", type=type(0), prompt="Forward lines: ")]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.forward_lines(vargs["lineno"])
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class Search(Method):
|
||||||
|
'''Interactive search; finds next occurance of text in buffer'''
|
||||||
|
is_literal = True
|
||||||
|
direction = 'next'
|
||||||
|
prompt = 'I-Search: '
|
||||||
|
def execute(self, w, **vargs):
|
||||||
|
self.old_cursor = w.logical_cursor()
|
||||||
|
self.old_window = w
|
||||||
|
w.application.open_mini_buffer(self.prompt, lambda x: None, self, None, 'search')
|
||||||
|
class ReverseSearch(Search):
|
||||||
|
'''Interactive search; finds previous occurance of text in buffer'''
|
||||||
|
direction = 'previous'
|
||||||
|
|
||||||
|
class RegexSearch(Search):
|
||||||
|
'''Interactive search; finds next occurance of regex in buffer'''
|
||||||
|
is_literal = False
|
||||||
|
prompt = 'I-RegexSearch: '
|
||||||
|
class RegexReverseSearch(RegexSearch):
|
||||||
|
'''Interactive search; finds prevoius occurance of regex in buffer'''
|
||||||
|
direction = 'previous'
|
||||||
|
|
||||||
|
class Replace(Method):
|
||||||
|
'''Replace occurances of string X with string Y'''
|
||||||
|
is_literal = True
|
||||||
|
args = [Argument('before', prompt="Replace String: ",
|
||||||
|
default=default.last_replace_before, load_default=True),
|
||||||
|
Argument('after', prompt="Replace With: ",
|
||||||
|
default=default.last_replace_after, load_default=True)]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
a = w.application
|
||||||
|
a.last_replace_before = self.before = vargs['before']
|
||||||
|
a.last_replace_after = self.after = vargs['after']
|
||||||
|
self.old_window = w
|
||||||
|
a.open_mini_buffer('I-Replace: ', lambda x: None, self, None, 'replace')
|
||||||
|
class RegexReplace(Method):
|
||||||
|
'''Replace occurances of string X with string Y'''
|
||||||
|
is_literal = False
|
||||||
|
args = [Argument('before', prompt="Replace Regex: ",
|
||||||
|
default=default.last_replace_before, load_default=True),
|
||||||
|
Argument('after', prompt="Replace With: ",
|
||||||
|
default=default.last_replace_after, load_default=True)]
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
w.application.last_replace_before = self.before = vargs['before']
|
||||||
|
w.application.last_replace_after = self.after = vargs['after']
|
||||||
|
self.old_window = w
|
||||||
|
f = lambda x: None
|
||||||
|
w.application.open_mini_buffer('I-RegexReplace: ', f, self, None, 'replace')
|
|
@ -0,0 +1,74 @@
|
||||||
|
import os, commands, re, sets, tempfile
|
||||||
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
import buffer, default, dirutil, regex, util, window
|
||||||
|
from point import Point
|
||||||
|
|
||||||
|
from method import DATATYPES, Method, Argument
|
||||||
|
|
||||||
|
class Exec(Method):
|
||||||
|
'''Execute a command in a shell and put the output in a new buffer'''
|
||||||
|
args = [Argument('cmd', prompt="Exec: ", datatype='shell')]
|
||||||
|
def _doit(self, w, path, cmd):
|
||||||
|
if path:
|
||||||
|
try:
|
||||||
|
cmd = cmd % {'path': path}
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
(status, output) = commands.getstatusoutput(cmd)
|
||||||
|
bufname = '*%s*' % self.name.title()
|
||||||
|
w.application.data_buffer(bufname, output, switch_to=True)
|
||||||
|
w.set_error("Shell exited with %d" % status)
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
if w.buffer.btype == 'dir':
|
||||||
|
name = dirutil.resolve_name(w)
|
||||||
|
path = dirutil.resolve_path(w)
|
||||||
|
self._doit(w, path, vargs['cmd'])
|
||||||
|
dirutil.find_name(w, name)
|
||||||
|
elif hasattr(w.buffer, 'path'):
|
||||||
|
path = w.buffer.path
|
||||||
|
self._doit(w, path, vargs['cmd'])
|
||||||
|
else:
|
||||||
|
self._doit(w, None, vargs['cmd'])
|
||||||
|
|
||||||
|
class Pipe(Method):
|
||||||
|
'''Pipe the buffer's contents through the command, and display the output in a new buffer'''
|
||||||
|
args = [Argument('cmd', datatype="str", prompt="Command: ")]
|
||||||
|
def _parse(self, w, **vargs):
|
||||||
|
# return 3 things: prog name, cmd, and whether to use the shell
|
||||||
|
m = regex.shell_command.match(vargs['cmd'])
|
||||||
|
if m:
|
||||||
|
prog = m.group(0)
|
||||||
|
return (prog, vargs['cmd'], True)
|
||||||
|
else:
|
||||||
|
return (None, None, False)
|
||||||
|
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
(prog, cmd, shell) = self._parse(w, **vargs)
|
||||||
|
if prog is None or not cmd:
|
||||||
|
return
|
||||||
|
|
||||||
|
pipe = Popen(cmd, shell=shell, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
|
||||||
|
pid = pipe.pid
|
||||||
|
|
||||||
|
indata = w.buffer.make_string()
|
||||||
|
pipe.stdin.write(indata)
|
||||||
|
pipe.stdin.close()
|
||||||
|
|
||||||
|
outdata = pipe.stdout.read()
|
||||||
|
status = pipe.wait() >> 8
|
||||||
|
|
||||||
|
bufname = '*%s*' % self.name.title()
|
||||||
|
w.application.data_buffer(bufname, outdata, switch_to=True)
|
||||||
|
w.set_error("%s exited with status %d" % (prog, status))
|
||||||
|
|
||||||
|
class Grep(Pipe):
|
||||||
|
'''Grep the buffer's contents for instances of a pattern, and display them in a new buffer'''
|
||||||
|
args = [Argument('pattern', datatype="str", prompt="Pattern: ")]
|
||||||
|
def _parse(self, w, **vargs):
|
||||||
|
return ('grep', ('grep', '-E', '-n', vargs['pattern']), False)
|
||||||
|
class Sed(Pipe):
|
||||||
|
'''Push the buffer's contents through a sed expression'''
|
||||||
|
args = [Argument('expression', datatype="str", prompt="Expression: ")]
|
||||||
|
def _parse(self, w, **vargs):
|
||||||
|
return ('grep', ('sed', '-r', '-e', vargs['expression']), False)
|
|
@ -170,7 +170,6 @@ class Fundamental(Handler):
|
||||||
self.add_bindings('indent-block', ('C-c >',))
|
self.add_bindings('indent-block', ('C-c >',))
|
||||||
self.add_bindings('unindent-block', ('C-c <',))
|
self.add_bindings('unindent-block', ('C-c <',))
|
||||||
self.add_bindings('token-complete', ('M-c', 'C-c c', 'C-c TAB',))
|
self.add_bindings('token-complete', ('M-c', 'C-c c', 'C-c TAB',))
|
||||||
self.add_bindings('shell-cmd', ('C-c !',))
|
|
||||||
self.add_bindings('open-aes-file', ('C-c a',))
|
self.add_bindings('open-aes-file', ('C-c a',))
|
||||||
self.add_bindings('open-console', ('M-e',))
|
self.add_bindings('open-console', ('M-e',))
|
||||||
self.add_bindings('show-bindings-buffer', ('C-c M-h','C-c M-?',))
|
self.add_bindings('show-bindings-buffer', ('C-c M-h','C-c M-?',))
|
||||||
|
@ -178,7 +177,7 @@ class Fundamental(Handler):
|
||||||
self.add_bindings('cmd-help-buffer', ('M-h',))
|
self.add_bindings('cmd-help-buffer', ('M-h',))
|
||||||
self.add_bindings('set-mode', ('C-x m',))
|
self.add_bindings('set-mode', ('C-x m',))
|
||||||
self.add_bindings('cancel', ('C-]',))
|
self.add_bindings('cancel', ('C-]',))
|
||||||
self.add_bindings('exec', ('C-c e',))
|
self.add_bindings('exec', ('C-c e', 'C-c !'))
|
||||||
self.add_bindings('grep', ('C-c g',))
|
self.add_bindings('grep', ('C-c g',))
|
||||||
self.add_bindings('pipe', ('C-c p',))
|
self.add_bindings('pipe', ('C-c p',))
|
||||||
self.add_bindings('view-buffer-parent', ('C-c .',))
|
self.add_bindings('view-buffer-parent', ('C-c .',))
|
||||||
|
@ -188,9 +187,6 @@ class Fundamental(Handler):
|
||||||
self.add_bindings('insert-escaped-dquote', ('C-c M-"',))
|
self.add_bindings('insert-escaped-dquote', ('C-c M-"',))
|
||||||
self.add_bindings('get-token', ('C-c t',))
|
self.add_bindings('get-token', ('C-c t',))
|
||||||
|
|
||||||
# unbound actions
|
|
||||||
self.add_action(method.GetToken())
|
|
||||||
|
|
||||||
# create all the insert actions for the basic text input
|
# create all the insert actions for the basic text input
|
||||||
for c in string.letters + string.digits + string.punctuation:
|
for c in string.letters + string.digits + string.punctuation:
|
||||||
self.add_binding('insert-string-%s' % c, c)
|
self.add_binding('insert-string-%s' % c, c)
|
||||||
|
|
Loading…
Reference in New Issue