Repository navigation
Conversation
`.erb` files opened as plain text. They now highlight the markup outside the tags as HTML and the code inside `<% %>` and `<%= %>` as Ruby. Tag delimiters and `<%# %>` comments take the comment color. The highlighter had one grammar and one tree per buffer, so a template could only be parsed as one of its two languages. A language can now declare an embedded language and a function that finds its tags. The syntax tree state then keeps two trees per buffer version: the host tree parses the text outside the tags and the embedded tree parses the code inside them, both through tree-sitter's included ranges. Languages without an embedded language go through the same path with one tree, as before. ERB tags are found by a small scanner instead of a tree-sitter grammar. arborium has no ERB grammar, and a standalone C grammar would need its own sysroot to build for wasm, which arborium only provides for its own grammars. ERB's tag syntax is small enough that the scanner covers it: output, trim and comment tags, the `<%%` and `%%>` escapes, and a tag left open while typing. Refs warpdotdev#55 Co-Authored-By: Claude <noreply@anthropic.com>
|
@miggyjv, your GitHub account is not connected to Warp. Connect your GitHub account, then retry GitHub PR opened from warp-terminal-factory. |
|
/warp-agent-review |
|
This PR was generated with Warp. Comment |
There was a problem hiding this comment.
Overview
Adds ERB (.erb / .html.erb) highlighting by scanning <% %> tags and parsing HTML outside them and Ruby inside them, with erb/eruby fence aliases in Agent output; the design matches #55 and the reported tests and clippy pass. Net position: request changes on comment-rule cleanup before merge.
Verdict
Checks: build pass, tests pass (cargo test -p languages -p syntax_tree: 16 + 21), clippy pass (-D warnings), CI n/a (no checks configured on the branch), visual proof present
Found: 0 critical, 2 important, 2 suggestions, 0 nits
--
Responding as warp-terminal-factory: Open session · View in factory
| highlights | ||
| } | ||
|
|
||
| /// Returns the bytes of the syntax tree that `range` can show. The result is a character wider |
There was a problem hiding this comment.
The doc promises "a character wider than range on each side," but the body pads by WIDEST_CHAR (4) buffer bytes and then compares that span to tree-sitter's 0-based included_ranges — a different unit and coordinate space than the comment describes. A later edit that trusts the comment will mis-map the range. Rewrite it to describe the 1-based buffer vs 0-based tree mapping (as char_offset's tree_byte + 1 already does), or drop the padding and do that conversion instead.
| #[test] | ||
| fn erb_colors_markup_as_html_and_tags_as_ruby() { | ||
| check_highlights("show.html.erb", VIEW, |highlights| { | ||
| // HTML outside the tags. |
There was a problem hiding this comment.
These narration comments ("HTML outside the tags", "Ruby inside the tags", ...) only restate the asserts below them, which AGENTS.md's no-line-by-line-narrations rule forbids, and they will drift when the asserts change. Delete them; the test names and assert_eq! lines already carry the meaning.
| /// Returns the bytes of the syntax tree that `range` can show. The result is a character wider | ||
| /// than `range` on each side, which covers the block marker that the buffer's offsets count and | ||
| /// the tree's offsets do not. | ||
| fn visible_byte_range(range: &Range<CharOffset>, buffer: &Buffer) -> Range<usize> { |
There was a problem hiding this comment.
visible_byte_range converts to buffer bytes, pads ±4, and treats the result as tree bytes, so viewport-clipped highlighting is only accidentally correct. Every new test highlights the whole document, so an off-by-one at a range edge would not fail CI. Convert to tree bytes explicitly (buffer_byte.saturating_sub(1)) and add a case that highlights only part of a tag.
| ); | ||
| // The quoted attribute value spans the tag, but its color stays out of the Ruby. | ||
| assert_eq!(highlights.color_of("<%= 1 + 2 %>", " + "), None); | ||
| assert_ne!( |
There was a problem hiding this comment.
assert_ne!(color_of("card_class"), Some(STRING)) still passes if the Ruby overlay is lost entirely and the identifier renders None. The spanning-attribute contract deserves a positive pin: assert the actual expected color rather than "not the HTML string color".
Review feedback on the ERB highlighting. `visible_byte_range` padded the buffer's byte offsets by four and used the result as tree offsets, and its comment described a different unit than the code used. It now converts each end of the range with `tree_byte`, the inverse of `char_offset`, so no padding is needed. Every highlight test covered the whole document, so a mistake at the edge of a range could not fail. A new test highlights a range that starts and ends inside a tag delimiter and checks that nothing outside the range is colored. The spanning-attribute test now asserts the color the Ruby actually gets instead of only ruling out the HTML string color, and the test comments that restated their asserts are gone. Refs warpdotdev#55 Co-Authored-By: Claude <noreply@anthropic.com>
|
/warp-agent-review |
There was a problem hiding this comment.
Overview
Re-review of e78e56b: the visible range is now mapped to tree bytes explicitly, and all four findings from the previous review are addressed with no new findings. Ready to merge from our side.
Note: HighlightQuery::get_highlighted_chunks still treats buffer bytes as tree bytes — pre-existing, untouched by this PR, and not counted as a finding.
Verdict
Checks: build pass, tests pass (cargo test -p syntax_tree: 22), clippy pass (-D warnings), CI n/a (no checks configured on the branch), visual proof present
Found: 0 critical, 0 important, 0 suggestions, 0 nits
--
Responding as warp-terminal-factory: Open session · View in factory



Description
Adds syntax highlighting for ERB templates (
.erb,.html.erb). The markup outside the tags is highlighted as HTML and the code inside<% %>and<%= %>is highlighted as Ruby. Tag delimiters and<%# %>comments take the comment color, the same color the editor already gives HTML's<and>.Why this needed more than a new language entry. The highlighter had one grammar and one syntax tree per buffer and no language injection, so a template could only be parsed as one of its two languages. This PR lets a language declare an embedded language:
crates/languages:Languagegets an optionalembedded: EmbeddedLanguage, which names the embedded language and a function that finds the template's tags.erbis registered with HTML as its own grammar and Ruby as its embedded language.crates/syntax_tree: the state keepsSyntaxTrees { host, embedded }per buffer version instead of oneTree. For a template, the host tree parses the text outside the tags and the embedded tree parses the code inside them, both through tree-sitter's included ranges. Edits are applied to both trees and both are reparsed incrementally. Every other language takes the same path with one tree, as before.class="card <%= kind %>"), so painting the tags also keeps the HTML string color out of the Ruby.app/src/ai/agent:```erband```erubycode blocks in Agent output are highlighted.Why a scanner and not a tree-sitter ERB grammar. arborium 2.13 has no ERB or embedded-template grammar, and neither does the latest release (2.18.2). The standalone
tree-sitter-embedded-templatecrate compiles C withcc, and arborium's grammars only build forwasm32-unknown-unknownbecause arborium supplies its own sysroot to its own crates, so an outside C grammar would likely break the wasm jobs. ERB's tag syntax is small, socrates/languages/src/erb.rsfinds the tags directly:<% %>,<%= %>,<%== %>,<%- -%>,<%# %>, the<%%and%%>escapes, multi-line tags, and a tag that is still open while you type (it runs to the end of the document, as ERB reads it). No new dependency and no licensing question.Behavior change:
.erbfiles are now a supported language, so they get an editor language and semantic chunking like.htmlfiles do.Known limitations:
.erbfile is treated as HTML outside its tags, including.js.erbor.yml.erb.<% a %><% b %>) read asa b.Linked Issue
Closes #55 (upstream warpdotdev#7901)
ready-to-specorready-to-implement.Upstream warpdotdev#7901 is labeled
triaged. It is on the Stanford starter list.Testing
Automated, all run locally (
cargo test -p languages -p syntax_tree, 16 and 22 tests pass;cargo clippy -p languages -p syntax_tree --all-targets --tests -- -D warningsis clean):crates/languages/src/erb_tests.rs: the tag scanner. Each kind of tag, comment tags, multi-line tags, unclosed tags, the escapes, empty tags, plain markup, and multibyte text.crates/languages/src/lib_tests.rs:.erband.html.erbresolve to ERB, ERB embeds the same cached Ruby language, andall_supported_languages_load_successfullycovers the new config.crates/syntax_tree/src/lib_tests.rs: highlights of a fixture view, asserted by color. HTML outside the tags, Ruby inside them, delimiters and comment tags, Ruby keywords in prose staying plain, an attribute string that spans a tag, multibyte text next to a tag, a template with no Ruby, a template that is only tags, an unclosed tag, a visible range that starts and ends inside a tag delimiter, and plain.rbunchanged. Also: the HTML tree has no parse errors because it never sees a tag, the parser's ranges do not leak into the next parse, an incremental reparse after an edit equals a fresh parse, and the range splitting has correct rows and columns.erbanderubytotest_programming_language_to_extension, which passes (cargo test -p warp --lib test_programming_language_to_extension).Manual: built
warp-ossfrom this branch and frommasterand opened the same Rails view in both../script/runI ran the binary from
cargo build --bin warp-oss --features guidirectly instead of through./script/run, becausecargo-bundleis not installed on my machine.Screenshots / Videos
Before (
master):After (this branch):
Agent Mode
This PR was written with AI assistance (Claude Code). I reviewed the diff, ran the tests and the app myself, and took the screenshots.
CHANGELOG-IMPROVEMENT: Added syntax highlighting for ERB templates (.erb, .html.erb), with HTML outside the tags and Ruby inside them.
🤖 Generated with Claude Code