jianuo's picture
first
09321b6
raw
history blame
No virus
2.74 kB
import os
import platform
import re
from ..subprocess_code_interpreter import SubprocessCodeInterpreter
class Shell(SubprocessCodeInterpreter):
file_extension = 'sh'
proper_name = 'Shell'
def __init__(self):
super().__init__()
# Determine the start command based on the platform
if platform.system() == 'Windows':
self.start_cmd = 'cmd.exe'
else:
self.start_cmd = os.environ.get('SHELL', 'bash')
def preprocess_code(self, code):
return preprocess_shell(code)
def line_postprocessor(self, line):
return line
def detect_active_line(self, line):
if '##active_line' in line:
return int(line.split('##active_line')[1].split('##')[0])
return None
def detect_end_of_execution(self, line):
return '##end_of_execution##' in line
def preprocess_shell(code):
"""
Add active line markers
Wrap in a try except (trap in shell)
Add end of execution marker
"""
# Add commands that tell us what the active line is
# if it's multiline, just skip this. soon we should make it work with multiline
if not has_multiline_commands(code):
code = add_active_line_prints(code)
# Add end command (we'll be listening for this so we know when it ends)
code += '\necho "##end_of_execution##"'
return code
def add_active_line_prints(code):
"""
Add echo statements indicating line numbers to a shell string.
"""
lines = code.split('\n')
for index, line in enumerate(lines):
# Insert the echo command before the actual line
lines[index] = f'echo "##active_line{index + 1}##"\n{line}'
return '\n'.join(lines)
def has_multiline_commands(script_text):
# Patterns that indicate a line continues
continuation_patterns = [
r'\\$', # Line continuation character at the end of the line
r'\|$', # Pipe character at the end of the line indicating a pipeline continuation
r'&&\s*$', # Logical AND at the end of the line
r'\|\|\s*$', # Logical OR at the end of the line
r'<\($', # Start of process substitution
r'\($', # Start of subshell
r'{\s*$', # Start of a block
r'\bif\b', # Start of an if statement
r'\bwhile\b', # Start of a while loop
r'\bfor\b', # Start of a for loop
r'do\s*$', # 'do' keyword for loops
r'then\s*$', # 'then' keyword for if statements
]
# Check each line for multiline patterns
for line in script_text.splitlines():
if any(
re.search(pattern, line.rstrip())
for pattern in continuation_patterns):
return True
return False