@@ -615,7 +615,10 @@ def _load_registry_bundle():
615615
616616def _split_args_safe (text : str ):
617617 try :
618- return shlex .split (text )
618+ lexer = shlex .shlex (str (text or "" ), posix = True )
619+ lexer .whitespace_split = True
620+ lexer .commenters = "#"
621+ return list (lexer )
619622 except Exception :
620623 return [t for t in text .split () if t ]
621624
@@ -1494,7 +1497,7 @@ def exec_line(raw_line, line_no=None):
14941497 ln = raw_line .strip ()
14951498 if not ln or ln .startswith ('#' ):
14961499 return
1497- parts = shlex . split (ln )
1500+ parts = _split_args_safe (ln )
14981501 command , args , properties = parse_input (parts )
14991502 if command :
15001503 # Set context line for single-line 'if' error reporting
@@ -1578,7 +1581,7 @@ def _parse_repeat_count(header_tokens):
15781581 return count_int
15791582
15801583 def _parse_for_header (header_raw ):
1581- raw_tokens = shlex . split (header_raw )
1584+ raw_tokens = _split_args_safe (header_raw )
15821585 if not raw_tokens :
15831586 return None
15841587 var_name = raw_tokens [0 ]
@@ -1605,7 +1608,7 @@ def _parse_for_header(header_raw):
16051608 return var_name , item_type , props
16061609
16071610 def _parse_while_header (header_raw ):
1608- raw_tokens = shlex . split (header_raw )
1611+ raw_tokens = _split_args_safe (header_raw )
16091612 max_raw = None
16101613 cond_tokens = []
16111614 for tok in raw_tokens :
@@ -1676,7 +1679,7 @@ def collect_commands(start_idx):
16761679 if sl .startswith ('repeat ' ) and sl .endswith (' then' ):
16771680 block , i = collect_block (i )
16781681 header = stripped [7 :- 5 ].strip ()
1679- header_tokens = _V .expand_list (shlex . split (header ))
1682+ header_tokens = _V .expand_list (_split_args_safe (header ))
16801683 count = _parse_repeat_count (header_tokens )
16811684 if not count :
16821685 print ("❌ Invalid repeat count. Use: repeat count:<n> then" )
@@ -1770,7 +1773,7 @@ def collect_commands(start_idx):
17701773
17711774 if sl .startswith ('if ' ) and sl .endswith (' then' ):
17721775 header = stripped [3 :- 5 ].strip ()
1773- header_parts = shlex . split (header )
1776+ header_parts = _split_args_safe (header )
17741777 cond_tokens = _V .expand_list (header_parts )
17751778 cond_line_no = i + 1
17761779 blocks = [(cond_tokens , [], cond_line_no )]
@@ -1783,7 +1786,7 @@ def collect_commands(start_idx):
17831786 sl2 = s .lower ()
17841787 if sl2 .startswith ('elseif ' ) and sl2 .endswith (' then' ):
17851788 elif_header = s [7 :- 5 ].strip ()
1786- parts2 = shlex . split (elif_header )
1789+ parts2 = _split_args_safe (elif_header )
17871790 cond2 = _V .expand_list (parts2 )
17881791 elif_line_no = i + 1
17891792 i += 1
@@ -1938,7 +1941,7 @@ def collect_commands(start_idx):
19381941 # Join all arguments into a single string to handle quotes correctly
19391942 user_input_str = ' ' .join (cli_args )
19401943 # Use shlex.split to parse the string, respecting quotes
1941- parts = shlex . split (user_input_str )
1944+ parts = _split_args_safe (user_input_str )
19421945 command , args , properties = parse_input (parts )
19431946 if command :
19441947 if command .lower () in {"exit" , "quit" }:
@@ -2037,7 +2040,7 @@ def _(event):
20372040 time .sleep (1 )
20382041 _play_cli_sound ("exit" , wait = True )
20392042 break
2040- parts = shlex . split (user_input )
2043+ parts = _split_args_safe (user_input )
20412044 command , args , properties = parse_input (parts )
20422045 if command :
20432046 invoke_command (command , args , properties .copy ())
@@ -2076,7 +2079,7 @@ def _(event):
20762079 break
20772080
20782081 # Use shlex.split for interactive input to handle quotes
2079- parts = shlex . split (user_input )
2082+ parts = _split_args_safe (user_input )
20802083 command , args , properties = parse_input (parts )
20812084
20822085 if command :
0 commit comments