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
|
||||
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)
|
||||
mod = eval(name)
|
||||
for mname in dir(mod):
|
||||
|
|
|
@ -105,213 +105,6 @@ class Method(object):
|
|||
def _execute(self, w, **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):
|
||||
'''Relex the buffer; this resets syntax highlighting'''
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -321,6 +114,7 @@ class RelexBuffer(Method):
|
|||
else:
|
||||
h.highlight(w.buffer.lines)
|
||||
w.set_error("Buffer relexed.")
|
||||
|
||||
class ToggleWindow(Method):
|
||||
'''Move between visible windows'''
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -511,57 +305,6 @@ class DeleteRightSpace(Method):
|
|||
if p > c:
|
||||
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):
|
||||
'''Invoke commands by name'''
|
||||
args = [Argument('method', datatype="method", prompt="M-x ")]
|
||||
|
@ -598,16 +341,25 @@ class InsertSpace(Method):
|
|||
'''Insert space into buffer at the cursor'''
|
||||
def _execute(self, w, **vargs):
|
||||
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):
|
||||
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)
|
||||
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 InsertTab(Method):
|
||||
'''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)
|
||||
else:
|
||||
w.goto(Point(j, cursor.y))
|
||||
|
||||
class KillWhitespace(Method):
|
||||
'''Delete leading whitespace on current line'''
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -645,6 +398,16 @@ class TabBuffer(Method):
|
|||
w.goto_line(i)
|
||||
it.execute(w)
|
||||
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
|
||||
class CommentRegion(Method):
|
||||
|
@ -899,79 +662,6 @@ class Redo(Method):
|
|||
except Exception, 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):
|
||||
'''Prepend 4 spaces to each line in region'''
|
||||
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.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):
|
||||
'''diff the buffer's contents with the given file'''
|
||||
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.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):
|
||||
'''Set the mode of the current buffer'''
|
||||
args = [Argument('mode', datatype='mode', prompt="Enter new mode: ")]
|
||||
|
@ -1174,16 +735,6 @@ class SetMode(Method):
|
|||
w.set_mode(m)
|
||||
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):
|
||||
'''Cancel command in-progress, and return to the main buffer'''
|
||||
def execute(self, w, **vargs):
|
||||
|
@ -1207,29 +758,6 @@ class UnsplitWindow(Method):
|
|||
w.application.single_slot()
|
||||
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):
|
||||
mytag = ')'
|
||||
def _execute(self, w, **vargs):
|
||||
|
@ -1290,15 +818,6 @@ class CloseBrace(CloseTag):
|
|||
class CloseBracket(CloseTag):
|
||||
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):
|
||||
MAX_TXT = 30
|
||||
MAX_REG = 20
|
||||
|
@ -1334,129 +853,3 @@ class RegisterRestore(Method):
|
|||
if len(name) > self.MAX_REG:
|
||||
name = name[0:self.MAX_REG] + '...'
|
||||
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('unindent-block', ('C-c <',))
|
||||
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-console', ('M-e',))
|
||||
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('set-mode', ('C-x m',))
|
||||
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('pipe', ('C-c p',))
|
||||
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('get-token', ('C-c t',))
|
||||
|
||||
# unbound actions
|
||||
self.add_action(method.GetToken())
|
||||
|
||||
# create all the insert actions for the basic text input
|
||||
for c in string.letters + string.digits + string.punctuation:
|
||||
self.add_binding('insert-string-%s' % c, c)
|
||||
|
|
Loading…
Reference in New Issue