* feat: add T command (branch on no-substitution)
Implements the GNU `T LABEL` command: branch to LABEL if no s///
substitution has succeeded since the last input line was read or the
last t/T was taken. It is the inverse of `t` and shares the same
address and label parsing.
Wires 'T' into get_cmd_spec, resolve_branch_targets, and the processor
branch logic, resetting the substitution flag on evaluation just like
't'. Adds integration tests (simple branch + flag-clear) and a cmd-spec
unit test.
Closes#395
Co-authored-by: Diomidis Spinellis <dds@aueb.gr>
* ci: re-trigger checks (windows runner crates.io download flake)
* Disable T in POSIX mode
---------
Co-authored-by: mukunda katta <mukunda.vjcs6@gmail.com>
* implement version command
* add tests for version option
* fix patch comparsion
* absurd extreme comparsion fix
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* accept missing minor or patch
* guard 'v' with if posix
* add a few tests
* add test_default_version
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* check if minor is empty and push zero instead of shadowing
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* chore: fix typo
* add: standalone e command
Implement the 'e' command. No argument implies execution of pattern space and any respective argument is to run with the output written to stream. Rejected under --posix and --sandbox.
Also stop silently swallowing shell stderr for e and s///e.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* add: e command tests
Includes 17 new tests. Cover both forms of the new 'e' command: with-argument execution (including shell side effects, addressing, ';' not separating the argument, escape decoding, and backslash continuation) and the no-argument pattern-space form. Also cover --posix/--sandbox rejection and stderr surfacing on command failure.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: gate LF-related tests to UNIIX only
* address e command review
Validate shell output as utf-8 and error out instead of lossily converting it. Make CRLF strip conditionally compile to Windows only. Rename execute_pattern_as_shell to execute_pattern_as_shell_command. Add tests for non-utf-8 error paths.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* add: Windows tests for e command with argument
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* fix: broken pipe race in sandbox e command test
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* Apply s/// p and e flags in written order
GNU sed applies the 'p' and 'e' substitution flags in the order they appear. 'pe' prints the pre-execution text then executes, while 'ep' executes then prints the result. Record whether 'p' precedes 'e' and apply them accordingly.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
---------
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
The original Rust implementation assummed a UTF-8 environment, as is
common in modern systems. This commit improves GNU sed compatibility
by changing most processing to run on bytes rather than Rust's Unicode
characters and strings. This change also improves the handling of binary
files. The commit adds a simple POSIX-compatible locale configuration
to support UTF-8 processing when specified. While at it, also fix
script-specified file handling to take place through OsString and
add a few missing unit tests.
The change fixes two failing GNU test suite cases.
The multiline matching resulted in a large performance regression due to
the indiscriminate use of the dotall (?s) flag. Change the regex
selection process to use only the flag when probably needed.
* reject 'i', 'I', 'm', 'M' and 'E' when --posix flag is set
* add test for issue 401
* formatting
* add a test for 'm' flag in test_posix_reject_flags
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update compiler.rs
* cargo fmt
* add a const variable with the err msg
* Update compiler.rs
* cargo fmt
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* feat: introduce e substituion for sed
When the s command is requested for sed, the e substitution flag enables execution of the result of substitution as a shell command. It matches the GNU sed behavior.
On src/sed/command.rs, add 'execute' field to 'Substitution' structure.
On src/sed/compiler.rs, handle 'e' in 'compile_subst_flags' and reject it if --posix or --sandbox flag is used in sed.
On src/sed/processor.rs, spawn /bin/sh with -c flag for a successful match and replace the pattern space with the command's standard output stream.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: comply with rustfmt
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: support for Windows command-line
Instead of calling bourne shell, define a new function: shell_command() with two definitions; conditionally compiling to UNIX-like and Windows. On UNIX-like, executes the bourne shell, whereas command prompt is executed on Windows.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: check newline for Windows
Unix-like system only uses the newline character whereas Windows uses the carriage return as well as newline. Hence, when working on Windows, we need to truncate the last two characters.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* add: 'e' flag tests
Nine new tests have been introduced in regards to new 'e' substitution option. 'test_subst_e_flag_multiline_outuput' is conditionally compiled as printf command is not guaranteed to be present on all Windows systems.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: fallback for shell_command
Executing a shell or a command prompt requires appropriate platforms. WASM does not currently support it.
Also fix a linting issue.
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* chore: linting cleanup
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
---------
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* feat: support zero-address file insertion
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* Polish the handling of 0r
- Use common constant for error message.
- Simplify command check at compile and runtime.
- Separate runtime handling into a function.
---------
Signed-off-by: PranavRJoshi <pranavrjoshi1@gmail.com>
Co-authored-by: PranavRJoshi <pranavrjoshi1@gmail.com>
* exit with code 1 when no arguments
* add a test for no arguments.
* Update test_sed.rs
* cargo fmt
* pass -n for missing script arguments test
Issue: #274
PR: #409
The previous harness tried to extract sed commands from GNU test scripts
via regex pattern matching, which produced false negatives (comparing
against empty expected output) and false positives. This led to inflated
test counts and unreliable pass/fail signals.
The new approach:
- Provides a lightweight shim for the gnulib test framework (init.sh)
with implementations of compare_, returns_, skip_, framework_failure_,
and all require_* functions
- Executes each .sh test script from the GNU testsuite directly,
injecting our Rust sed binary via PATH
- Uses a clean srcdir with symlinks to real test data files
- Adds per-test timeout (10s) to catch infinite loops, with SIGTERM
isolation so timeout signals don't kill the parent script
- Properly propagates exit codes (0=pass, 77=skip, 99=framework failure)
Results are now consistent with CI tracking (~12% pass rate) with
clear PASS/FAIL/SKIP/timeout categorization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove newline swap in exchange and swap content only
* fix: support non empty hold spaces and newline appended hold spaces
* nit: period in comment
* nit: useless comment removal
* chore: clarify newline swap logic for `x`
Before this commit, the output of sed was lagging one line behind, as it
was always checking whether each line was the last one ($). This change
modifies the behavior to make this check only when actually needed.
This brings sed's interactive behavior (when reading from a terminal) in
line with the GNU and FreeBSD implementations.
ls -la sed/${{ env.TEST_FULL_SUMMARY_FILE }} || echo "JSON file not found at sed/${{ env.TEST_FULL_SUMMARY_FILE }}"
ls -la ${{ env.TEST_FULL_SUMMARY_FILE }} || echo "JSON file not found at ${{ env.TEST_FULL_SUMMARY_FILE }}"
find . -name "*json*" -type f || echo "No JSON files found"
- name:Upload full json results
uses:actions/upload-artifact@v7
with:
name:sed-gnu-full-result
path:sed/${{ env.TEST_FULL_SUMMARY_FILE }}
if-no-files-found:warn
- name:Upload test logs
if:always()
uses:actions/upload-artifact@v7
with:
name:test-logs
path:|
sed/test-logs/*.log
sed/test-results/*.json
aggregate:
needs:[native]
permissions:
actions:read
contents:read
pull-requests:read
name:Aggregate GNU test results
runs-on:ubuntu-24.04
steps:
- name:Initialize workflow variables
id:vars
shell:bash
run:|
## VARs setup
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
TEST_SUMMARY_FILE='sed-gnu-result.json'
outputs TEST_SUMMARY_FILE
- name:Checkout code (sed)
uses:actions/checkout@v7
with:
path:'sed'
persist-credentials:false
- name:Retrieve reference artifacts
uses:dawidd6/action-download-artifact@v21
continue-on-error:true
with:
workflow:GnuTests.yml
branch:"${{ env.DEFAULT_BRANCH }}"
workflow_conclusion:completed
path:"reference"
if_no_artifact_found:warn
- name:Download full json results
uses:actions/download-artifact@v8
with:
name:sed-gnu-full-result
path:results
- name:Extract/summarize testing info
id:summary
shell:bash
run:|
## Extract/summarize testing info
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# Check if results directory exists and has JSON files
json_count=0
if [[ -d "results" ]]; then
json_count=$(find results -name "*.json" | wc -l)
fi
if [[ "$json_count" -lt 1 ]]; then
echo "::error ::Failed to download results json files; failing early"
echo "::error ::Contents of results directory:"
ls -lR results || echo "::error ::Results directory does not exist"
File diff suppressed because it is too large.
Load diff
Loaded 20 of 57 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.