Skip to content

Commit 3980234

Browse files
lieryanjonathanslenders
authored andcommitted
Implement basic :s[ubstitute] command
1 parent aeb9264 commit 3980234

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

pyvim/commands/commands.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from __future__ import unicode_literals, print_function
22
from prompt_toolkit.application import run_in_terminal
3+
from prompt_toolkit.document import Document
4+
35
import os
6+
import re
47
import six
58

69
__all__ = (
@@ -704,3 +707,26 @@ def set_scroll_offset(editor, value):
704707
'Invalid value. Expecting comma separated list of integers')
705708
else:
706709
editor.colorcolumn = numbers
710+
711+
712+
def substitute(editor, range_start, range_end, search, replace, flags):
713+
if flags == 'g':
714+
transform_callback = lambda s: re.sub(search, replace, s)
715+
else:
716+
transform_callback = lambda s: re.sub(search, replace, s, count=1)
717+
718+
buffer = editor.current_editor_buffer.buffer
719+
current_row = buffer.document.cursor_position_row
720+
721+
if not range_end:
722+
range_end = range_start
723+
if range_start and range_end:
724+
line_index_iterator = range(int(range_start) - 1, int(range_end))
725+
else:
726+
line_index_iterator = range(current_row, current_row + 1)
727+
728+
new_text = buffer.transform_lines(line_index_iterator, transform_callback)
729+
buffer.document = Document(
730+
new_text,
731+
Document(new_text).translate_row_col_to_index(current_row, 0))
732+
buffer.cursor_position += buffer.document.get_start_of_line_position(after_whitespace=True)

pyvim/commands/grammar.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
:*
1212
\s*
1313
(
14+
# Substitute command
15+
((?P<range_start>\d+)(,(?P<range_end>\d+))?)? (?P<command>s|substitute) \s* / (?P<search>[^/]*) / (?P<replace>[^/]*) (?P<flags> /g )? |
16+
1417
# Commands accepting a location.
1518
(?P<command>%(commands_taking_locations)s)(?P<force>!?) \s+ (?P<location>[^\s]+) |
1619

pyvim/commands/handler.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import unicode_literals
22

33
from .grammar import COMMAND_GRAMMAR
4-
from .commands import call_command_handler, has_command_handler
4+
from .commands import call_command_handler, has_command_handler, substitute
55

66
__all__ = (
77
'handle_command',
@@ -21,6 +21,11 @@ def handle_command(editor, input_string):
2121
command = variables.get('command')
2222
go_to_line = variables.get('go_to_line')
2323
shell_command = variables.get('shell_command')
24+
range_start = variables.get('range_start')
25+
range_end = variables.get('range_end')
26+
search = variables.get('search')
27+
replace = variables.get('replace')
28+
flags = variables.get('flags', '')
2429

2530
# Call command handler.
2631

@@ -35,6 +40,11 @@ def handle_command(editor, input_string):
3540
elif has_command_handler(command):
3641
# Handle other 'normal' commands.
3742
call_command_handler(command, editor, variables)
43+
44+
elif command in ('s', 'substitute'):
45+
flags = flags.lstrip('/')
46+
substitute(editor, range_start, range_end, search, replace, flags)
47+
3848
else:
3949
# For unknown commands, show error message.
4050
editor.show_message('Not an editor command: %s' % input_string)

0 commit comments

Comments
 (0)