feature: phase 2 implemented#14
Merged
Merged
Conversation
- new -a/--archive: -r + preserve mode/owner/time, copy symlinks as links - link-aware lstat-driven tree walk never follows symlinks (TOCTOU-safe) - fix -p preserving only mode: now also sets owner + atime/mtime - add fs::lstat and fs::set_times (utimensat, AT_SYMLINK_NOFOLLOW) - directory attrs applied last so child writes don't reset dir mtime - fs_util.hpp: include <vector> (was relying on transitive include)
- integer operands validated via from_chars (abc -eq abc now exits 2) - recursive-descent parser: -o/-a/!/( ) with correct precedence - arity/syntax errors unified to exit 2 (bare -z, unknown -op, stray paren) - add -h/-b/-c/-p/-S file tests, -nt/-ot/-ef file comparisons, string < > - HELP.extra synced
- -R/--recursive: GNU-style blocks with 'path:' headers, blank-line separated - --color[=always|auto|never]: type-based ANSI colors (isatty gates auto) - symlinked directories not descended into (cycle-safe) - extract print_entry/collect_visible to dedup long/short/single-file paths - fix format_permissions emitting a stray '-' before the type char (ls -l showed 'd-rwxr-xr-x' instead of 'drwxr-xr-x')
- -A/-B/-C NUM: trailing/leading/both context; -C sets A=B - leading context via a bounded ring buffer, trailing via after_pending - '--' separator between non-contiguous match groups - context lines honor -n line numbers and multi-file path: prefix - context disabled under -q/-l/-c (only counting/quiet apply) - default path (no -A/-B/-C) byte-identical to before
- expression AST replaces flat AND chain: -a (implicit), -o, ! / -not, ( )
- recursive-descent parser with correct precedence (AND binds tighter than OR)
- -maxdepth hoisted to a global option; -exec stays an action leaf
- unknown primary / unbalanced paren / missing operand -> exit 1
- PATH vs expression disambiguation (leading '(' or '!' starts an expression)
- $((expr)) recursive-descent evaluator: + - * / %, comparisons, && || !, parens, integer literals, variables (bare or $VAR; unset/non-numeric -> 0) - fix assignment RHS not being expanded (X=$((i+1)) now works; was stored raw) - integration +5 arithmetic cases incl. a real counting while loop
- case WORD in PATTERN(|PATTERN)) body;; ... esac via CaseClause AST node - lexer emits DSemi (;;) so case bodies terminate correctly - patterns matched with fnmatch; * ? [ ] are pattern syntax, not filename globs - add expand_noglob: expand param/arith/command without field-split/glob, for case words/patterns (fixes * matching cwd files instead of any string) - integration +4 case cases: | alternation, * default, f* prefix, loop dispatch
- FuncDef AST node; name() { body; } parsed and registered in ShellState
- function calls run the body in-process with new positional params ($1..)
- return N sets a pending flag consumed at the call site, propagating through
AndOr / while / for execution
- local declares function-scoped vars via a scope stack; get_var/set_var are
scope-aware so locals do not leak to globals
- integration +4: definition+call, params, return status, local isolation
- lexer reads <<DELIM / <<-DELIM and collects the body up to the delimiter line (<<- strips leading tabs); body carried by the DLess/DLessDash token - parser maps it to Redir::HereDoc; executor writes the body to a temp file and redirects stdin from it - unquoted here-doc bodies expand param/arith/command via expand_noglob - constraint: <<DELIM ends the command line (the common form) - integration +3: plain body, var expansion, arithmetic expansion
- ${#VAR} length
- ${VAR#pat} / ${VAR##pat} strip shortest/longest matching prefix
- ${VAR%pat} / ${VAR%%pat} strip shortest/longest matching suffix
- ${VAR:-def} default, ${VAR:+alt} alternative
- glob prefix/suffix matching via fnmatch over increasing lengths
- integration +5 incl. the ${P##*/} basename idiom
- break N / continue: ShellState break_depth counts enclosing loops; the AndOr executor stops on pending break/continue so loop bodies abort early - add break/continue builtins (were missing entirely — loop flags were never set, so break/continue silently did nothing) - fix parse_compound_list corrupting a trailing && / || when merging across ';': it rewrote the last entry's operator to Semi, so 'false && echo M; echo X' wrongly ran echo M. Entries are now concatenated unchanged. - integration +3: break, continue, break 2 across nested loops
- read -p PROMPT writes the prompt to stderr before reading
- read -r recognized (raw mode; backslashes already preserved)
- fix the last variable receiving a leading IFS char ('echo a b c | read x y z'
now yields z='c', not ' c')
- integration +3: single/multi-var read, -p prompt
- ShellState holds a sig->command trap table; builtin_trap parses names (EXIT/INT/TERM/.../numeric), installs a handler that records the pending signal, or clears with 'trap - SIG' - the AndOr executor runs the trap command at the next safe point; run_string and run_interactive run the EXIT trap before returning - make every waitpid retry on EINTR so a signal-fired trap doesn't corrupt child-status retrieval - integration +2: EXIT trap fires on exit, 'trap - EXIT' clears it
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.