Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

buffer translateToString()/getChars() return '' for empty cells, collapsing cursor-positioned text

Open Beginner friendly
#205 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
api

Research direction

Start in lib/buffer.ts, where getChars() returns an empty string for cells with codepoint === 0, and in the translateToString implementation that builds on it. Use TerminalCore.getSelection() as the reference, since it already substitutes a space for empty cells. Done means the reproduction in the issue yields "a b" from translateToString(true), with trailing trimming still working.

Written by the indexing model from the issue text.

Description

Summary

IBufferLine.translateToString() (and IBufferCell.getChars()) return '' for empty cells (codepoint === 0), so text that an application positioned with cursor movement collapses: every blank run is removed and the remaining characters are glued together. xterm.js returns a space for an empty cell (translateToString(trimRight) keeps the layout). TerminalCore.getSelection() already does the right thing (k += " " for codepoint === 0), so the two disagree on the same screen.

This is separate from #200 (multi-codepoint graphemes truncated); the blank-cell case affects plain ASCII. Seen on [email protected]; lib/buffer.ts on main has the same codepoint === 0 ? '' in getChars().

Minimal reproduction

<div id="t"></div>
<script type="module">
  import { init, Terminal } from 'ghostty-web';
  await init();
  const term = new Terminal({ cols: 40, rows: 5 });
  term.open(document.getElementById('t'));
  // "a", move right 5 columns (CUF), "b": what vim/htop/tmux status bars do all the time
  term.write('a\x1b[5Cb', () => {
    const line = term.buffer.active.getLine(0);
    console.log(JSON.stringify(line.translateToString(true))); // actual: "ab"   expected: "a     b"
    term.select(0, 0, 7);
    console.log(JSON.stringify(term.getSelection()));           // "a     b" (selection is correct)
  });
</script>

Anything built on the public buffer API (search, serialize, accessibility mirrors, "copy line", tests) sees the collapsed text.

Suggested fix

getChars() returns ' ' for codepoint === 0 (width 1), or translateToString substitutes ' ' for empty cells before trimEnd().

Found while comparing renderers for https://github.com/erisera-code/clawser.

Dominant language
TypeScript
Stars
2.9k
Forks
182
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from coder/ghostty-web

All issues in coder/ghostty-web

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.