Skip to content

Commit b2701ee

Browse files
committed
Handle EdScript content with ReplaceClause
1 parent 63af393 commit b2701ee

File tree

2 files changed

+75
-5
lines changed

2 files changed

+75
-5
lines changed

src/cedarscript_editor/cedarscript_editor.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
from cedarscript_ast_parser import Command, RmFileCommand, MvFileCommand, UpdateCommand, \
66
SelectCommand, CreateCommand, IdentifierFromFile, Segment, Marker, MoveClause, DeleteClause, \
7-
InsertClause, ReplaceClause, EditingAction, BodyOrWhole, RegionClause, MarkerType
7+
InsertClause, ReplaceClause, EditingAction, BodyOrWhole, RegionClause, MarkerType, EdScript
8+
from ed_script_filter import process_ed_script
89
from cedarscript_ast_parser.cedarscript_ast_parser import MarkerCompatible, RelativeMarker, \
910
RelativePositionType, Region, SingleFileClause
1011
from text_manipulation import (
@@ -148,6 +149,13 @@ def _update_command(self, cmd: UpdateCommand):
148149

149150

150151
match content:
152+
case EdScript() as ed_script:
153+
if not isinstance(action, ReplaceClause):
154+
raise ValueError("ED scripts can only be used with REPLACE actions")
155+
# Process ED script on just the lines in the search range
156+
range_lines = search_range.read(lines)
157+
processed_lines = process_ed_script(range_lines, ed_script.script)
158+
content = processed_lines
151159
case str() | [str(), *_] | (str(), *_):
152160
pass
153161
case (region, relindent_level):
@@ -161,10 +169,6 @@ def _update_command(self, cmd: UpdateCommand):
161169
case _:
162170
match action:
163171
case MoveClause(insert_position=region, relative_indentation=relindent_level):
164-
# dest_range = restrict_search_range_for_marker(
165-
# region, action, lines, RangeSpec.EMPTY, identifier_finder
166-
# )
167-
# TODO Are the 3 lines above needed?
168172
content = IndentationInfo.shift_indentation(
169173
move_src_range.read(lines), lines, search_range.indent, relindent_level
170174
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import subprocess
2+
import tempfile
3+
import os
4+
from typing import Union, Sequence
5+
from pathlib import Path
6+
7+
8+
def process_ed_script(file_input: Union[str, Path, Sequence[str]], ed_script: str, is_path: bool = False) -> list[str]:
9+
"""
10+
Process an ed script on file content or file by streaming to the ed command.
11+
12+
Args:
13+
file_input: Either file content as string, path to file, or sequence of strings
14+
ed_script (str): The ed script commands as a string
15+
is_path (bool): If True, file_input is treated as a path, otherwise as content
16+
17+
Returns:
18+
list[str]: The modified content as a list of strings (lines)
19+
20+
Raises:
21+
FileNotFoundError: If is_path is True and the file doesn't exist
22+
RuntimeError: If ed command fails
23+
"""
24+
temp_filename = None
25+
26+
try:
27+
if is_path:
28+
# Convert to Path object for better path handling
29+
file_path = Path(file_input)
30+
if not file_path.exists():
31+
raise FileNotFoundError(f"File not found: {file_path}")
32+
input_file = str(file_path.absolute())
33+
else:
34+
# Create a temporary file for the content
35+
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
36+
# Handle both string and sequence input
37+
if isinstance(file_input, str):
38+
temp_file.write(file_input)
39+
else:
40+
temp_file.write('\n'.join(file_input))
41+
temp_filename = input_file = temp_file.name
42+
43+
# Run ed with the script as input
44+
process = subprocess.Popen(
45+
['ed', '-s', input_file], # -s for silent mode
46+
stdin=subprocess.PIPE,
47+
stderr=subprocess.PIPE,
48+
text=True
49+
)
50+
51+
# Send the ed script and get output
52+
_, errors = process.communicate(ed_script + 'w\nq\n') # write and quit commands
53+
54+
if process.returncode != 0:
55+
raise RuntimeError(f"ed failed with error: {errors}")
56+
57+
# Read the modified content and return as list of strings
58+
with open(input_file, 'r') as f:
59+
result = f.read().splitlines()
60+
61+
return result
62+
63+
finally:
64+
# Clean up the temporary file if we created one
65+
if temp_filename and os.path.exists(temp_filename):
66+
os.unlink(temp_filename)

0 commit comments

Comments
 (0)