Skip to content

Commit cabc9ed

Browse files
committed
feat(shellflow): enhance command execution with sequential output handling
1 parent 43d8503 commit cabc9ed

1 file changed

Lines changed: 65 additions & 17 deletions

File tree

src/shellflow.py

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,38 +1294,90 @@ def _execute_block_commands_sequential(
12941294
) -> ExecutionResult:
12951295
"""Execute block commands sequentially, printing output after each command.
12961296
1297+
For local blocks, commands are executed one at a time for verbose output.
1298+
For remote blocks, all commands are executed in a single SSH connection
1299+
to preserve execution state (e.g., working directory) between commands.
1300+
12971301
Returns:
12981302
ExecutionResult combining all command outputs.
12991303
"""
1300-
# ANSI color codes
1301-
RED = "\033[91m"
1302-
DIM = "\033[90m"
1304+
if verbose:
1305+
_print_block_header(block, block_index, total_blocks)
1306+
1307+
commands_to_execute = _iter_display_commands(block.commands)
1308+
1309+
if block.is_remote:
1310+
return _execute_remote_block_sequential(block, context, no_input, verbose, commands_to_execute)
1311+
1312+
return _execute_local_block_sequential(block, context, no_input, verbose, commands_to_execute)
1313+
1314+
1315+
def _print_block_header(block: Block, block_index: int, total_blocks: int) -> None:
1316+
"""Print block header for verbose output."""
13031317
BLUE = "\033[94m"
13041318
YELLOW = "\033[93m"
13051319
RESET = "\033[0m"
13061320

1307-
# Print block header if verbose
1321+
if block.is_local:
1322+
print(f"{BLUE}[{block_index}/{total_blocks}] LOCAL{RESET}")
1323+
else:
1324+
host = block.host or "unknown"
1325+
print(f"{YELLOW}[{block_index}/{total_blocks}] REMOTE: {host}{RESET}")
1326+
1327+
1328+
def _execute_remote_block_sequential(
1329+
block: Block,
1330+
context: ExecutionContext,
1331+
no_input: bool,
1332+
verbose: bool,
1333+
commands_to_execute: list[str],
1334+
) -> ExecutionResult:
1335+
"""Execute remote block commands in a single SSH connection."""
1336+
RED = "\033[91m"
1337+
DIM = "\033[90m"
1338+
RESET = "\033[0m"
1339+
13081340
if verbose:
1309-
if block.is_local:
1310-
print(f"{BLUE}[{block_index}/{total_blocks}] LOCAL{RESET}")
1311-
else:
1312-
host = block.host or "unknown"
1313-
print(f"{YELLOW}[{block_index}/{total_blocks}] REMOTE: {host}{RESET}")
1341+
for cmd in commands_to_execute:
1342+
print(f"{DIM}$ {cmd}{RESET}")
1343+
1344+
result = _execute_block_once(block, context, no_input=no_input)
1345+
1346+
if verbose and result.output:
1347+
truncated = _truncate_output_lines(result.output, MAX_OUTPUT_LINES)
1348+
print(truncated)
1349+
1350+
context.last_output = result.output
1351+
context.success = result.success
1352+
1353+
if not result.success and verbose:
1354+
print(f"{RED}✗ Command failed with exit code {result.exit_code}{RESET}\n")
1355+
1356+
return result
1357+
1358+
1359+
def _execute_local_block_sequential(
1360+
block: Block,
1361+
context: ExecutionContext,
1362+
no_input: bool,
1363+
verbose: bool,
1364+
commands_to_execute: list[str],
1365+
) -> ExecutionResult:
1366+
"""Execute local block commands one at a time for verbose output."""
1367+
RED = "\033[91m"
1368+
DIM = "\033[90m"
1369+
RESET = "\033[0m"
13141370

13151371
all_outputs: list[str] = []
13161372
all_stdout: list[str] = []
13171373
all_stderr: list[str] = []
13181374
final_exit_code = 0
13191375
success = True
13201376

1321-
commands_to_execute = _iter_display_commands(block.commands)
1322-
13231377
for cmd in commands_to_execute:
1324-
# Print the command being executed
13251378
if verbose:
13261379
print(f"{DIM}$ {cmd}{RESET}")
13271380

1328-
# Execute single command using a single-command block
13291381
single_block = Block(
13301382
target=block.target,
13311383
commands=[cmd],
@@ -1334,19 +1386,16 @@ def _execute_block_commands_sequential(
13341386
)
13351387
result = _execute_block_once(single_block, context, no_input=no_input)
13361388

1337-
# Store outputs
13381389
all_outputs.append(result.output)
13391390
if result.stdout:
13401391
all_stdout.append(result.stdout)
13411392
if result.stderr:
13421393
all_stderr.append(result.stderr)
13431394

1344-
# Print output immediately with truncation
13451395
if verbose and result.output:
13461396
truncated = _truncate_output_lines(result.output, MAX_OUTPUT_LINES)
13471397
print(truncated)
13481398

1349-
# Check for failure
13501399
if not result.success:
13511400
final_exit_code = result.exit_code
13521401
success = False
@@ -1358,7 +1407,6 @@ def _execute_block_commands_sequential(
13581407
combined_stdout = "\n".join(filter(None, all_stdout))
13591408
combined_stderr = "\n".join(filter(None, all_stderr))
13601409

1361-
# Update context
13621410
context.last_output = combined_output
13631411
context.success = success
13641412

0 commit comments

Comments
 (0)