Skip to content

feat: REPL highlighting + live completion, forge doc/fmt fixes#9

Merged
humancto merged 3 commits into
mainfrom
phase-1-fmt-doc-repl
Apr 11, 2026
Merged

feat: REPL highlighting + live completion, forge doc/fmt fixes#9
humancto merged 3 commits into
mainfrom
phase-1-fmt-doc-repl

Conversation

@humancto
Copy link
Copy Markdown
Owner

Summary

Phase 1 final batch — REPL, formatter, and doc generator improvements.

REPL:

  • Syntax highlighting: keywords (magenta), builtins (blue), modules (green), strings (yellow), numbers (cyan), comments (dim)
  • Tab completion now includes user-defined variables and functions from the live interpreter environment
  • env command shows all defined variables and values (not just _last)

forge doc:

  • Fix let/let mut declarations being silently skipped (the _ => {} catch-all was swallowing them)
  • // comments preceding declarations are now extracted and displayed using SpannedStmt.line

forge fmt:

  • Parenthesis depth tracking for multi-line function call continuation indentation

Infrastructure:

  • Environment::all_names() method for REPL tab completion
  • Roadmap updated: Phase 1 items 1.1-1.4, 1.6-1.8 complete (1.5 spans deferred)

Test plan

  • 826 cargo tests pass (2 new formatter, 13 total)
  • forge run examples/hello.fg passes
  • forge run examples/functional.fg passes
  • Manual: forge repl — verify syntax colors, define a variable, tab-complete it
  • Manual: forge doc examples/ — verify variables and comments appear
  • Manual: forge fmt --check on a file with multi-line function call

Archith added 2 commits April 10, 2026 23:54
REPL:
- Syntax highlighting: keywords (magenta), builtins (blue), modules
  (green), strings (yellow), numbers (cyan), comments (dim)
- Tab completion now includes user-defined variables and functions
  from the interpreter environment, updated after each evaluation
- `env` command shows all defined variables instead of just _last

forge doc:
- Fix variable extraction: let/let mut declarations now appear in output
- Extract // comments preceding declarations using SpannedStmt.line
- Remove unused `self` import

Interpreter:
- Add Environment::all_names() for REPL tab completion
Formatter:
- Add parenthesis depth tracking for multi-line function call indentation
- 2 new tests (13 total formatter tests)

forge doc:
- Fix let/let mut declarations being silently skipped in doc output
- Implement comment extraction using SpannedStmt.line
- Remove unused ast self-import

Roadmap: Phase 1 items 1.6-1.8 complete
Copy link
Copy Markdown
Owner Author

@humancto humancto left a comment

Choose a reason for hiding this comment

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

Review: REPL highlighting + live completion, forge doc/fmt fixes

Nice batch of improvements — clean, focused changes across three areas with good test coverage. The REPL syntax highlighting, doc generator fixes, and formatter paren tracking are all well-implemented.

What looks good

  • extract_preceding_comments — Clean implementation. The 1-based → 0-based conversion via spanned.line.saturating_sub(1) is correct, and the backward walk with proper bounds checking is solid.
  • Environment::all_names() — Good use of unwrap_or_else(|p| p.into_inner()) for poisoned mutex recovery, consistent with the rest of the interpreter.
  • Arc<Mutex<Vec<String>>> for shared tab-completion state — The right pattern for sharing mutable state between the Helper and the REPL main loop.
  • forge fmt paren tracking — Minimal, correct change. The two new tests cover the important cases.
  • forge doc Stmt::Let handling — Removes the _ => {} catch-all swallowing declarations. Good catch.
  • CHANGELOG and ROADMAP updates — Well-structured entries.
  • Unused ast::self import cleanup — Correct; nothing uses the ast:: prefix.

Issues

  1. Bug (highlighter): true/false boolean highlighting is dead code — they're already in the KEYWORDS array so they match the keyword branch first and get magenta, never reaching the intended cyan branch. See inline comment.
  2. Minor (highlighter): Number highlighting consumes .. (range operator) as part of the number. 1..10 highlights as one cyan token instead of 1, .., 10.
  3. Minor (highlighter): Single-quoted strings aren't highlighted — the formatter already treats ' as a string delimiter, so the highlighter should too for consistency.
  4. Nit (formatter): count_braces now counts parens but the name doesn't reflect it.

None of these are blocking — the dead-code boolean bug (#1) is worth fixing before merge, the rest are minor polish.


Generated by Claude Code

Comment thread src/repl/mod.rs Outdated
Comment on lines +297 to +300
result.push_str("\x1B[0m");
} else if word == "true" || word == "false" {
result.push_str("\x1B[36m"); // cyan for booleans
result.push_str(&word);
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.

Bug: true and false are already in the KEYWORDS array (lines 148-149), so they'll be matched by the KEYWORDS.contains() check above and highlighted in magenta. This else if branch is unreachable dead code.

To get the intended cyan highlighting for booleans, either:

  1. Remove "true" and "false" from KEYWORDS and rely on this explicit check, or
  2. Move this check before the KEYWORDS.contains() check

Option 1 seems cleaner since true/false are really literals, not keywords.


Generated by Claude Code

Comment thread src/repl/mod.rs Outdated
Comment on lines +257 to +262
// Numbers
if chars[i].is_ascii_digit() {
result.push_str("\x1B[36m"); // cyan
while i < len && (chars[i].is_ascii_digit() || chars[i] == '.') {
result.push(chars[i]);
i += 1;
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.

Minor: This will consume the range operator .. as part of a number literal. For example, range(1..10) would highlight 1..10 as a single cyan number instead of 1, .., 10.

Consider tightening to allow at most one . (and only if followed by a digit):

if chars[i].is_ascii_digit() {
    result.push_str("\x1B[36m");
    while i < len && chars[i].is_ascii_digit() {
        result.push(chars[i]);
        i += 1;
    }
    // Allow one decimal point followed by digits
    if i < len && chars[i] == '.' && i + 1 < len && chars[i + 1].is_ascii_digit() {
        result.push(chars[i]);
        i += 1;
        while i < len && chars[i].is_ascii_digit() {
            result.push(chars[i]);
            i += 1;
        }
    }
    result.push_str("\x1B[0m");
    continue;
}

Not blocking, but would improve highlighting accuracy for Forge's range() and similar patterns.


Generated by Claude Code

Comment thread src/repl/mod.rs
result.push_str("\x1B[33m\""); // yellow
i += 1;
while i < len && chars[i] != '"' {
if chars[i] == '\\' && i + 1 < len {
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.

Nit: The highlighter handles double-quoted strings but not single-quoted ones. The formatter's count_braces already treats both '"' and '\'' as string delimiters, so Forge does support single-quoted strings. Adding a chars[i] == '\'' branch here (same logic, same color) would be a nice consistency improvement.


Generated by Claude Code

Comment thread src/formatter.rs

// Count braces and brackets outside strings
if c == '{' || c == '[' {
// Count braces, brackets, and parens outside strings
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.

Nit: Now that this function counts parentheses too, the name count_braces is slightly misleading. Consider renaming to count_delimiters or count_nesting. Not blocking — just a readability note since the test name count_braces_includes_parens already hints at the mismatch.


Generated by Claude Code

…xes, rename

- Move true/false check before KEYWORDS check so booleans get cyan (not magenta)
- Numbers no longer consume range operator (..) — require digit after dot
- Add single-quoted string highlighting
- Rename count_braces to count_delimiters (now tracks braces, brackets, parens)
@humancto humancto merged commit 0d251a2 into main Apr 11, 2026
7 of 9 checks passed
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.

1 participant