mode documentation improvements; better diff; ideas

--HG--
branch : pmacs2
This commit is contained in:
moculus 2009-03-28 03:40:09 +00:00
parent abaaef7c83
commit a971586fed
5 changed files with 69 additions and 32 deletions

12
IDEAS
View File

@ -1,3 +1,15 @@
2009/03/27:
1. Create a Method attribute meaning should-appear-in-help-buffers. Use this to
hide actions that only make sense when the mini-buffer is open, as well as weird
actions like "text-insert-space"
2. Create a way to figure out what actions are legal in the various mini-buffer
modes (search, replace, whatever).
3. Maybe write a per-mode "how to use this mode" document that can be accessed
in a uniform way. This way, various non-discoverable features can be documented.
2009/02/15: 2009/02/15:
Remove $MODE.lib in favor of $MODE.libs[] Remove $MODE.lib in favor of $MODE.libs[]

View File

@ -341,6 +341,7 @@ class UppercaseWord(Method):
w.insert_string(p1, word.upper()) w.insert_string(p1, word.upper())
class MetaX(Method): class MetaX(Method):
'''Call pmacs functions by name (with or without arguments)'''
args = [arg('method', dt="method", p="M-x ", h='Method to execute')] args = [arg('method', dt="method", p="M-x ", h='Method to execute')]
name_re = re.compile(r'[a-z0-9_-]+') name_re = re.compile(r'[a-z0-9_-]+')
@ -572,6 +573,7 @@ class UncommentRegion(Method):
# wrapping/justifying/etc # wrapping/justifying/etc
class WrapLine(Method): class WrapLine(Method):
'''Wrap a line of text based on a predefined margin'''
limit = 80 limit = 80
space_re = re.compile(' +') space_re = re.compile(' +')
def _token_len(self, tokens): def _token_len(self, tokens):
@ -636,6 +638,7 @@ class WrapLine(Method):
w.goto(Point(x, y)) w.goto(Point(x, y))
class WrapParagraph(Method): class WrapParagraph(Method):
'''Wrap contiguous lines of text based on a predefined margin'''
limit = 80 limit = 80
valid_re = re.compile('^( *)([^ ].*)$') valid_re = re.compile('^( *)([^ ].*)$')
empty_re = regex.whitespace empty_re = regex.whitespace
@ -854,31 +857,40 @@ 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 FileDiff(Method): class Diff(Method):
'''diff the buffer's contents with the given file''' '''diff the buffer's contents with the given file'''
args = [arg("path", t=type(""), p="Filename: ", dt='path', args = [arg("path1", t=type(""), p="Filename: ", dt='path', h="left path to diff"),
h="path to diff against current buffer's contents")] arg("path2", t=type(""), p="Filename: ", dt='path', h="right path to diff")]
def _get_cmd(self, w, **vargs):
return ("/usr/bin/diff", '-u', vargs['path1'], vargs['path2'])
def _pipe_write(self, pipe, w, **vargs):
pass
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
cmd = ("/usr/bin/diff", '-u', '-', vargs['path']) cmd = self._get_cmd(w, **vargs)
pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
pid = pipe.pid self._pipe_write(pipe, w, **vargs)
indata = w.buffer.make_string()
pipe.stdin.write(indata)
pipe.stdin.close()
outdata = pipe.stdout.read() outdata = pipe.stdout.read()
errdata = pipe.stderr.read() errdata = pipe.stderr.read()
status = pipe.wait() >> 8 status = pipe.wait()
if status == 0: if status == 0:
w.set_error("No difference found") w.set_error("No difference found" + str(status))
elif status == 1: elif status == 1:
w.application.data_buffer("*Diff*", outdata, switch_to=True, modename='diff') w.application.data_buffer("*Diff*", outdata, switch_to=True, modename='diff')
w.set_error("Differences were found") w.set_error("Differences were found")
else: else:
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" % (pipe.pid, status))
class FileDiff(Diff):
'''diff the buffer's contents with the given file'''
args = [arg("path", t=type(""), p="Filename: ", dt='path',
h="path to diff against current buffer's contents")]
def _get_cmd(self, w, **vargs):
return ("/usr/bin/diff", '-u', '-', vargs['path'])
def _pipe_write(self, pipe, w, **vargs):
indata = w.buffer.make_string()
pipe.stdin.write(indata)
pipe.stdin.close()
class SetMode(Method): class SetMode(Method):
'''Set the mode of the current buffer''' '''Set the mode of the current buffer'''
@ -915,8 +927,9 @@ 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 CloseTag(Method): class CloseParen(Method):
mytag = ')' '''Insert ), matching if applicable'''
mytag = ')'
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
# first, de-reference some variables and actually do the insertion # first, de-reference some variables and actually do the insertion
# NOTE: we derence the cursor *before* inserting the character, so it is # NOTE: we derence the cursor *before* inserting the character, so it is
@ -968,13 +981,10 @@ class CloseTag(Method):
y -= 1 y -= 1
i = len(tokens[y]) - 1 i = len(tokens[y]) - 1
class CloseParen(CloseTag): class CloseBrace(CloseParen):
'''Insert ), matching if applicable'''
mytag = ')'
class CloseBrace(CloseTag):
'''Insert }, matching if applicable''' '''Insert }, matching if applicable'''
mytag = '}' mytag = '}'
class CloseBracket(CloseTag): class CloseBracket(CloseParen):
'''Insert ], matching if applicable''' '''Insert ], matching if applicable'''
mytag = ']' mytag = ']'
@ -982,8 +992,7 @@ class RegisterSave(Method):
'''Save the top item of the kill stack into the named register''' '''Save the top item of the kill stack into the named register'''
MAX_TXT = 30 MAX_TXT = 30
MAX_REG = 18 MAX_REG = 18
args = [arg('name', dt="register", p="Register name: ", args = [arg('name', dt="register", p="Register name: ", h="Register name to use")]
h="Name of the register to use")]
def _pre_execute(self, w, **vargs): def _pre_execute(self, w, **vargs):
if not w.has_kill(): if not w.has_kill():
raise MethodError("No text on the kill stack") raise MethodError("No text on the kill stack")
@ -998,11 +1007,10 @@ class RegisterSave(Method):
w.set_error('Saved %r into register %r' % (text, name)) w.set_error('Saved %r into register %r' % (text, name))
class RegisterRestore(Method): class RegisterRestore(Method):
'''Push the value saved in the named register onto the kill stack''' '''Push the value of the named register onto the kill stack'''
MAX_TXT = 30 MAX_TXT = 30
MAX_REG = 18 MAX_REG = 18
args = [arg('name', dt="register", p="Register name: ", args = [arg('name', dt="register", p="Register name: ", h="Register name to use")]
h="Name of the register to use")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
name = vargs['name'] name = vargs['name']
if name not in w.application.registers: if name not in w.application.registers:
@ -1018,8 +1026,8 @@ class RegisterRestore(Method):
w.set_error('Restored %r from register %r' % (text, name)) w.set_error('Restored %r from register %r' % (text, name))
class GetConfigVariable(Method): class GetConfigVariable(Method):
args = [arg('name', dt='config', p="Variable name: ", '''View the value of a particular config variables'''
h='Name of the configuration parameter')] args = [arg('name', dt='config', p="Config variable: ", h='Config variable name')]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
name = vargs['name'] name = vargs['name']
if name in w.application.config: if name in w.application.config:
@ -1029,6 +1037,7 @@ class GetConfigVariable(Method):
w.set_error("param %r is not set" % (name,)) w.set_error("param %r is not set" % (name,))
class ViewConfigVariables(Method): class ViewConfigVariables(Method):
'''View the value of all config variables'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
lines = ["APPLICATION CONFIGURATION VARIABLES\n"] lines = ["APPLICATION CONFIGURATION VARIABLES\n"]
for name in w.application.config: for name in w.application.config:
@ -1037,10 +1046,9 @@ class ViewConfigVariables(Method):
w.application.data_buffer('*Config*', data, switch_to=True) w.application.data_buffer('*Config*', data, switch_to=True)
class SetConfigVariable(Method): class SetConfigVariable(Method):
args = [arg('name', dt='config', p="Variable name: ", '''Set a particular config variable to a value'''
h='Name of the configuration parameter'), args = [arg('name', dt='config', p="Variable name: ", h='Config variable name'),
arg('value', t=type(''), p="Variable value: ", arg('value', t=type(''), p="Variable value: ", h='Config variable value')]
h='Configuration parameter value to use')]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
name = vargs['name'] name = vargs['name']
found = name in w.application.config found = name in w.application.config
@ -1055,6 +1063,7 @@ class SetConfigVariable(Method):
w.set_error("previously unset param %r set to %r" % (name, value)) w.set_error("previously unset param %r set to %r" % (name, value))
class ToggleHeader(Method): class ToggleHeader(Method):
'''Toggle the visibility of the buffer header'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
if w.mode.showing_header(): if w.mode.showing_header():
w.mode.disable_header() w.mode.disable_header()
@ -1063,7 +1072,9 @@ class ToggleHeader(Method):
w.mode.enable_header() w.mode.enable_header()
w.set_error('Header visible') w.set_error('Header visible')
# TODO: rename to left-margin
class ToggleLineNumbers(Method): class ToggleLineNumbers(Method):
'''Toggle the visibility of the left margin'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
if w.mode.showing_line_numbers(): if w.mode.showing_line_numbers():
w.mode.disable_line_numbers() w.mode.disable_line_numbers()
@ -1073,12 +1084,14 @@ class ToggleLineNumbers(Method):
w.set_error('Line numbers visible') w.set_error('Line numbers visible')
class SetTabWidth(Method): class SetTabWidth(Method):
'''Set the tab-width for the current buffer'''
args = [arg('width', t=type(0), p="Tab Width: ", h='New tab width for buffer')] args = [arg('width', t=type(0), p="Tab Width: ", h='New tab width for buffer')]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
w.mode.tabwidth = vargs['width'] w.mode.tabwidth = vargs['width']
w.set_error('Tab width set to %d' % w.mode.tabwidth) w.set_error('Tab width set to %d' % w.mode.tabwidth)
class SetModeTabWidth(Method): class SetModeTabWidth(Method):
'''Set the default tab-width for the current mode'''
args = [arg('mode', dt='mode', p="Mode: ", h=''), args = [arg('mode', dt='mode', p="Mode: ", h=''),
arg('width', t=type(0), p="Default Tab Width: ", h='New default tab width for mode')] arg('width', t=type(0), p="Default Tab Width: ", h='New default tab width for mode')]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):

View File

@ -66,6 +66,7 @@ class AwkTabber(StackTabber2):
return t.name in ('spaces', 'eol', 'comment') return t.name in ('spaces', 'eol', 'comment')
class AwkFilterFile(Exec): class AwkFilterFile(Exec):
'''Filter a file through the current buffer's AWK program'''
show_success = True show_success = True
args = [arg('path', dt="path", p="Filter File: ", dv=default.path_dirname, ld=True, h="file to open")] args = [arg('path', dt="path", p="Filter File: ", dv=default.path_dirname, ld=True, h="file to open")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
@ -87,6 +88,7 @@ class AwkFilterFile(Exec):
w.set_error("awk exited with status %d" % status) w.set_error("awk exited with status %d" % status)
class AwkFilterBuffer(Pipe): class AwkFilterBuffer(Pipe):
'''Filter a buffer through the current buffer's AWK program'''
args = [arg('name', dt="buffer", p="Filter Buffer: ", h="name of the buffer to switch to")] args = [arg('name', dt="buffer", p="Filter Buffer: ", h="name of the buffer to switch to")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'): if not hasattr(w.buffer, 'path'):
@ -111,6 +113,7 @@ class AwkFilterBuffer(Pipe):
w.set_error("awk exited with status %d" % status) w.set_error("awk exited with status %d" % status)
class AwkFilterInput(Method): class AwkFilterInput(Method):
'''Filter input through the current buffer's AWK program'''
args = [arg('input', p="Data To Filter: ", h="data to filter")] args = [arg('input', p="Data To Filter: ", h="data to filter")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'): if not hasattr(w.buffer, 'path'):

View File

@ -6,6 +6,7 @@ from point import Point
subgroup_re = re.compile(r'((?:\\\\)*)\\(0|[1-9][0-9]*)') subgroup_re = re.compile(r'((?:\\\\)*)\\(0|[1-9][0-9]*)')
class ReplaceOne(method.Method): class ReplaceOne(method.Method):
'In a replace command, replace the next occurance'
def execute(self, w, **vargs): def execute(self, w, **vargs):
m = w.buffer.method m = w.buffer.method
_replace(m) _replace(m)
@ -13,6 +14,7 @@ class ReplaceOne(method.Method):
_finish(m, w) _finish(m, w)
class ReplaceDone(method.Method): class ReplaceDone(method.Method):
'In a replace command, replace the next occurance and exit'
def execute(self, w, **vargs): def execute(self, w, **vargs):
m = w.buffer.method m = w.buffer.method
_replace(m) _replace(m)
@ -20,12 +22,14 @@ class ReplaceDone(method.Method):
w.set_error("Replace done") w.set_error("Replace done")
class SkipReplace(method.Method): class SkipReplace(method.Method):
'In a replace command, skip the next occurance'
def execute(self, w, **vargs): def execute(self, w, **vargs):
m = w.buffer.method m = w.buffer.method
_find_next(m, True) _find_next(m, True)
_finish(m, w) _finish(m, w)
class ReplaceAll(method.Method): class ReplaceAll(method.Method):
'In a replace command, replace all remaining occurances'
def execute(self, w, **vargs): def execute(self, w, **vargs):
m = w.buffer.method m = w.buffer.method
while m.p1 is not None: while m.p1 is not None:
@ -35,6 +39,7 @@ class ReplaceAll(method.Method):
w.set_error("Replace ended") w.set_error("Replace ended")
class CancelReplace(method.Method): class CancelReplace(method.Method):
'Cancel a currently running replace command'
def execute(self, w, **vargs): def execute(self, w, **vargs):
_end(w) _end(w)
w.set_error("Replace cancelled") w.set_error("Replace cancelled")

View File

@ -20,6 +20,7 @@ def _make_regex(w, s):
raise searchutil.IllegalPatternError("failed to compile: %r" % s) raise searchutil.IllegalPatternError("failed to compile: %r" % s)
class SearchNext(method.Method): class SearchNext(method.Method):
'In a search command, move to the next occurance'
def execute(self, w, **vargs): def execute(self, w, **vargs):
w.buffer.method.direction = 'next' w.buffer.method.direction = 'next'
s = w.buffer.make_string() s = w.buffer.make_string()
@ -34,6 +35,7 @@ class SearchNext(method.Method):
action.execute(w) action.execute(w)
class SearchPrevious(method.Method): class SearchPrevious(method.Method):
'In a search command, move to the previous occurance'
def execute(self, w, **vargs): def execute(self, w, **vargs):
w.buffer.method.direction = 'previous' w.buffer.method.direction = 'previous'
if not w.buffer.make_string(): if not w.buffer.make_string():
@ -48,6 +50,7 @@ class SearchPrevious(method.Method):
w.application.clear_highlighted_ranges('search') w.application.clear_highlighted_ranges('search')
class EndSearch(method.Method): class EndSearch(method.Method):
'End the current search command, leaving the cursor in place'
def execute(self, w, **vargs): def execute(self, w, **vargs):
old_w = w.buffer.method.old_window old_w = w.buffer.method.old_window
old_c = w.buffer.method.old_cursor old_c = w.buffer.method.old_cursor
@ -56,6 +59,7 @@ class EndSearch(method.Method):
w.set_error("Mark set to search start") w.set_error("Mark set to search start")
class CancelSearch(method.Method): class CancelSearch(method.Method):
'End the current search command, restoring the cursor to the search start'
def execute(self, w, **vargs): def execute(self, w, **vargs):
w.buffer.method.old_window.goto(w.buffer.method.old_cursor) w.buffer.method.old_window.goto(w.buffer.method.old_cursor)
_end(w) _end(w)