Skip to content

Add pwd, clear, and help builtins to /bin/sh#907

Merged
dburkart merged 2 commits into
mainfrom
m901-sh-builtins
May 6, 2026
Merged

Add pwd, clear, and help builtins to /bin/sh#907
dburkart merged 2 commits into
mainfrom
m901-sh-builtins

Conversation

@dburkart
Copy link
Copy Markdown
Owner

@dburkart dburkart commented May 6, 2026

Closes #901

Summary

  • Adds three new shell builtins: pwd, clear, and help
  • pwd prints $PWD from the environment, falling back to std::env::current_dir() if unset
  • clear writes ANSI escape sequences (\x1b[2J\x1b[H) to clear the screen and home the cursor
  • help with no args lists all builtins with one-line descriptions; help <name> shows detailed usage
  • Includes a static BUILTIN_HELP table covering all 17 builtins with short and long descriptions
  • Unit tests for all three new builtins, including dispatch and is_builtin coverage

Test plan

  • cd base/sh && cargo test — all 412 tests pass (was 396 before, +16 new)
  • cargo fmt --all -- --check — clean

Implements the three new shell builtins requested in #901:

- pwd: prints $PWD, falls back to std::env::current_dir()
- clear: writes ANSI \x1b[2J\x1b[H to clear screen
- help: lists all builtins with descriptions; help <name> shows detail

Includes a static BUILTIN_HELP table with short and long descriptions
for every builtin, and unit tests for all three new commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Adds three shell builtins—pwd, clear, and help—by extending builtin recognition and dispatch in base/sh/src/builtins.rs, implementing builtin_pwd and builtin_clear, expanding the builtins help table, and adding tests covering recognition, dispatch, behavior, and help output.

Changes

Shell Builtin Additions

Layer / File(s) Summary
Builtin Recognition
base/sh/src/builtins.rs
is_builtin expanded to recognize pwd, clear, and help.
Dispatch Wiring
base/sh/src/builtins.rs
run_builtin dispatcher updated to route pwd, clear, and help to handlers.
pwd Implementation
base/sh/src/builtins.rs
New builtin_pwd(args: &[String], env: &mut Environment) -> i32: validates no extra args, prints $PWD when present, falls back to std::env::current_dir() when unset, returns status codes (0 success, 2 for extra args).
clear Implementation
base/sh/src/builtins.rs
New builtin_clear() -> i32: writes ANSI clear sequence to stdout, flushes, returns 0 on success, 1 on I/O error.
Help Table
base/sh/src/builtins.rs
Builtins help table extended with entries and long descriptions for pwd, clear, and help, integrating with existing builtin_help flow.
Tests
base/sh/src/builtins.rs (tests)
Added unit/integration tests for pwd (env and fallback, arg rejection, dispatch), clear (dispatch/integration, sequence emission), and help (listing, per-command description, help coverage for all builtins).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • dburkart/vibix#892: Adds new builtins and extends is_builtin/run_builtin dispatch used by the executor—directly related.
  • dburkart/vibix#893: Modifies base/sh/src/builtins.rs to add builtins and update dispatch logic—overlapping changes.
  • dburkart/vibix#891: Updates the same builtins implementation and dispatch/help registry—code-level overlap.

Poem

🐰
I twitch my whiskers, press enter with cheer,
pwd shows our burrow, clear makes it clear,
help tells the secrets of each cozy trick—
three tiny hops to make the shell click!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary change: adding three new shell builtins (pwd, clear, and help) to /bin/sh.
Description check ✅ Passed The description is directly related to the changeset, providing implementation details, test results, and linking to the closed issue #901.
Linked Issues check ✅ Passed The PR implements all required objectives from #901: pwd with $PWD and getcwd fallback, clear with ANSI sequences and stdout flush, help listing and detailed descriptions, BUILTIN_HELP table with all 17 builtins, and comprehensive unit tests.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the three new builtins in base/sh/src/builtins.rs with tests; no out-of-scope work like standalone /bin/ utilities or kernel debug commands is included.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch m901-sh-builtins

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
base/sh/src/builtins.rs (1)

2011-2023: ⚡ Quick win

Consider removing duplicated builtin-name lists in tests.

The hardcoded known array can drift from dispatch/help tables. Prefer deriving test inputs from a single source used by builtin metadata to keep coverage future-proof.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@base/sh/src/builtins.rs` around lines 2011 - 2023, The test
help_each_builtin_has_entry duplicates the builtin name list; instead of the
hardcoded known array, iterate the canonical builtin registry used by is_builtin
(the dispatch/metadata table that defines available builtins) and call
builtin_help(&args(&[name])) for each entry; update the test to pull names from
that single source of truth (the same dispatch/metadata used by is_builtin) so
the test always reflects the runtime builtin set while keeping
help_each_builtin_has_entry, is_builtin, builtin_help and args as the used
symbols.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@base/sh/src/builtins.rs`:
- Around line 1941-1955: The tests pwd_prints_env_pwd and
pwd_fallback_when_unset only assert exit status; update them to also capture and
assert the command output: use the same test harness that runs builtin_pwd (via
builtin_pwd, env(), args()) but capture stdout/stderr and assert that
pwd_prints_env_pwd yields the exact PWD string ("/home/user") and that
pwd_fallback_when_unset yields the current directory string
(std::env::current_dir() formatted as string). Apply the same pattern to the
other failing tests referenced (the clear/escape-sequence and help/listing tests
at the other locations) by asserting their stdout contains the expected escape
sequence or help text content/format rather than only checking status. Ensure
you reference and use builtin_pwd, env, args and the help/clear builtin test
functions when adding the output assertions.
- Around line 1118-1121: The builtin_clear function writes ANSI sequences but
doesn't flush stdout; modify builtin_clear (fn builtin_clear) to call
std::io::stdout().flush() after print! to ensure the clear is sent
immediately—import std::io::Write if needed and handle the Result from flush()
(e.g., ignore error or map it to the return code) so the function still returns
an i32.
- Around line 1096-1109: The builtin_pwd function currently ignores any
operands; change it to reject unexpected args by using the passed-in args slice
(remove the leading underscore from _args or otherwise reference it) and if
args.len() > 0 print an error to stderr (consistent with existing style, e.g.
eprintln!("sh: pwd: too many operands" or "sh: pwd: too many arguments")) and
return a non-zero exit code (1) before proceeding to read PWD or current_dir;
keep the existing PWD/current_dir logic unchanged and only run it when no
operands are supplied.

---

Nitpick comments:
In `@base/sh/src/builtins.rs`:
- Around line 2011-2023: The test help_each_builtin_has_entry duplicates the
builtin name list; instead of the hardcoded known array, iterate the canonical
builtin registry used by is_builtin (the dispatch/metadata table that defines
available builtins) and call builtin_help(&args(&[name])) for each entry; update
the test to pull names from that single source of truth (the same
dispatch/metadata used by is_builtin) so the test always reflects the runtime
builtin set while keeping help_each_builtin_has_entry, is_builtin, builtin_help
and args as the used symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ff70d307-da38-4a7c-9ac8-c272eef8760f

📥 Commits

Reviewing files that changed from the base of the PR and between 46c38d0 and 434f4f1.

📒 Files selected for processing (1)
  • base/sh/src/builtins.rs

Comment thread base/sh/src/builtins.rs Outdated
Comment thread base/sh/src/builtins.rs
Comment thread base/sh/src/builtins.rs
Comment on lines +1941 to +1955
#[test]
fn pwd_prints_env_pwd() {
let mut e = env();
e.set("PWD", "/home/user", None);
let status = builtin_pwd(&args(&[]), &mut e);
assert_eq!(status, 0);
}

#[test]
fn pwd_fallback_when_unset() {
let mut e = env();
// PWD is not set — should fall back to std::env::current_dir()
let status = builtin_pwd(&args(&[]), &mut e);
assert_eq!(status, 0);
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

New builtin tests miss output-contract assertions.

These tests validate status codes but not the required observable output (pwd text, clear escape sequence, help listing format/content). That leaves regressions undetected in the core behavior promised by this PR.

Also applies to: 1973-1976, 1993-1996

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@base/sh/src/builtins.rs` around lines 1941 - 1955, The tests
pwd_prints_env_pwd and pwd_fallback_when_unset only assert exit status; update
them to also capture and assert the command output: use the same test harness
that runs builtin_pwd (via builtin_pwd, env(), args()) but capture stdout/stderr
and assert that pwd_prints_env_pwd yields the exact PWD string ("/home/user")
and that pwd_fallback_when_unset yields the current directory string
(std::env::current_dir() formatted as string). Apply the same pattern to the
other failing tests referenced (the clear/escape-sequence and help/listing tests
at the other locations) by asserting their stdout contains the expected escape
sequence or help text content/format rather than only checking status. Ensure
you reference and use builtin_pwd, env, args and the help/clear builtin test
functions when adding the output assertions.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deferred to future work -- the existing test patterns in this file (echo_basic, echo_no_args, etc.) also only assert status codes, not output content. Adding stdout capture infrastructure is out of scope for this PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dburkart, understood — that's a fair call. The existing echo_basic and similar tests confirm the same status-only pattern, so keeping the new builtin tests consistent makes sense. Happy to revisit output-capture assertions in a follow-up once the infrastructure is in place.


✏️ Learnings added
Learnt from: dburkart
Repo: dburkart/vibix PR: 907
File: base/sh/src/builtins.rs:1950-1964
Timestamp: 2026-05-06T05:16:34.614Z
Learning: In `base/sh/src/builtins.rs`, the test module does not yet have stdout/stderr capture infrastructure. All existing builtin tests (echo_basic, echo_no_args, pwd_prints_env_pwd, clear_returns_zero, help_no_args_lists_all, etc.) only assert exit status codes, not output content. Adding output-content assertions is deferred to future work.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

- pwd now rejects unexpected operands with exit status 2
- clear now flushes stdout after writing escape sequences
- Added test for pwd extra-args rejection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
base/sh/src/builtins.rs (1)

1950-1964: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Tests still miss output-contract assertions for new builtins.

At Line 1954, Line 1991, and Line 2011 (and related tests), assertions only check exit status. This leaves regressions in visible behavior (pwd text, clear escape sequence, help content/format) undetected, even though those behaviors are core to this PR objective.

Based on learnings: tests currently only assert exit status codes; add stdout/stderr capture and assert actual output content for pwd, clear, and help.

Also applies to: 1990-1993, 2010-2025

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@base/sh/src/builtins.rs` around lines 1950 - 1964, The tests for pwd
(pwd_prints_env_pwd, pwd_fallback_when_unset) and the related clear/help tests
only assert exit status and must also capture and assert stdout/stderr content
to prevent behavioral regressions; update these tests to run builtin_pwd /
builtin_clear / builtin_help with the existing test helpers (e.g., env(),
args()) while capturing output (use the project’s test capture helper or wrap
the call to builtin_* and collect printed stdout/stderr), then assert the
expected text: for pwd tests assert the printed path equals the PWD env value or
the current_dir fallback, for clear assert the expected escape sequence is
written to stdout, and for help assert the help string contains the expected
sections/commands. Locate and modify the test functions named
pwd_prints_env_pwd, pwd_fallback_when_unset and the tests around lines 1990–1993
and 2010–2025 to add these stdout/stderr assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@base/sh/src/builtins.rs`:
- Around line 1950-1964: The tests for pwd (pwd_prints_env_pwd,
pwd_fallback_when_unset) and the related clear/help tests only assert exit
status and must also capture and assert stdout/stderr content to prevent
behavioral regressions; update these tests to run builtin_pwd / builtin_clear /
builtin_help with the existing test helpers (e.g., env(), args()) while
capturing output (use the project’s test capture helper or wrap the call to
builtin_* and collect printed stdout/stderr), then assert the expected text: for
pwd tests assert the printed path equals the PWD env value or the current_dir
fallback, for clear assert the expected escape sequence is written to stdout,
and for help assert the help string contains the expected sections/commands.
Locate and modify the test functions named pwd_prints_env_pwd,
pwd_fallback_when_unset and the tests around lines 1990–1993 and 2010–2025 to
add these stdout/stderr assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5ee66a39-d200-48bc-a81b-2060f932c9e9

📥 Commits

Reviewing files that changed from the base of the PR and between 434f4f1 and b738fe2.

📒 Files selected for processing (1)
  • base/sh/src/builtins.rs

@dburkart dburkart merged commit f9a6416 into main May 6, 2026
32 checks passed
@dburkart dburkart deleted the m901-sh-builtins branch May 6, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add pwd, clear, and help builtins to /bin/sh

2 participants