Repository navigation
Halfway down a long method or class, I can't see what I'm inside of #349
Description
Opportunity
Halfway down a long method or class, I can't see what I'm inside of.
The vision's user spends most of the day reading code they didn't write, often in a narrow terminal over SSH. Once a method's signature scrolls off the top, nothing on screen says which method or class the lines in front of you belong to. You scroll back up to find out and lose your place, or open Go to symbol (gs) just to read where you are. That's worst in the files you're trying to understand: long classes, nested types, and big Markdown docs where the heading you're under scrolled away pages ago. Jumping in from Find, blame, Back or a diff's Enter lands you mid-file with no context at all.
A terminal makes it worse. Fewer rows fit, so the signature scrolls away sooner than in a GUI.
Evidence
- JetBrains added sticky lines in IntelliJ IDEA 2024.1, on by default, "to simplify working with large files and exploring new codebases".
- VS Code has Sticky Scroll, on by default, pinning class, function and Markdown heading lines. It also has breadcrumbs above the editor.
- Terminal editors: Neovim users install nvim-treesitter-context. Helix users have asked for it (#2740, #10672, a statusline variant in discussion #7813), and a 140-comment sticky context PR closed unmerged. People want it, and it's harder than it looks.
- Inward: Go to symbol (Go to symbol in the current file #137, Go to symbol (gs): jump to a type, method or property in the current file #224–Go to symbol covers fields, enum members and Markdown headings #226) already finds every class, method, property and Markdown heading in a file, with its line and nesting. TuiCode knows what you're inside of. It just never shows you unless you ask.
Options considered
- Do nothing; use
gs. It's free, and it lists everything. But it tells you what's in the file, not where you are, and you have to ask every time. - Go to symbol opens on the symbol you're in. Cheap:
gshighlights your method, andEsctakes you back. Still something you ask for rather than see, and it hides the code while it's open. - A breadcrumb in the status bar (
Workbench › OpenFolder), like the statusline Helix users asked for. It costs no rows. But it's names without signatures, at the bottom of the screen away from where you're reading, it truncates on a narrow terminal, and The status bar is crowded with key hints, and the keys that only work where I am are hard to find #406 has just cleared the status bar back to status. - Sticky lines at the top of the editor (chosen). The class and method lines you're inside stay pinned above the text as you scroll, as in VS Code and JetBrains. It's the real lines, with their parameters and colours, right where you're reading, and it's what users of both editors already know. It costs up to three rows, and it touches how the editor scrolls, which is where Helix's attempt stalled.
- The innermost symbol in the editor's frame title (
┤Editor · OpenFolder├). No rows, but only one name, and nested types or Markdown sections lose the outer levels.
Sticky lines are the only option that answers "where am I?" without asking and without looking away. Three rows is a real cost in a terminal, so it's capped, and it can be turned off.
Proposal
As you scroll, the lines that open the class, method or heading you're inside stay pinned at the top of the editor.
- What sticks: the first line of each definition Go to symbol finds that encloses the top line on screen: classes, interfaces, structs, enums, methods, properties with a body, and Markdown headings. Fields, enum members and one-line properties never stick, because nothing sits inside them.
- What "inside" means: a definition encloses the lines below it that are indented deeper than it, up to and including its closing line. A Markdown heading encloses everything up to the next heading of the same or a higher level.
- How it looks: each pinned line is drawn as it is in the file, with its syntax colours and its own line number in the gutter, on the theme's current-line background so it reads as a header, not text you're editing.
- At most three lines. Deeper nesting keeps the innermost three. On an editor fewer than 12 rows tall, none are shown.
- Scrolling stays honest. The cursor is never hidden under a pinned line: moving up into one scrolls the text instead. Every jump (Go to line, Go to symbol, a Find result, Back) still lands its line two rows below the pinned ones, not behind them.
- Clicking a pinned line goes to that line, as Go to symbol does, so Back returns you. The keyboard way is
gs, unchanged. - After an edit the pinned lines catch up once the file's been rescanned, which is a few frames in a large file. They don't flicker or vanish meanwhile.
- Settings › Editor gets a
CheckBox,[x] Show sticky lines, on by default, like Wrap long lines.
Mockup
Scrolled into OpenFolder in Workbench.cs, with the class and method lines pinned:
File Edit Selection View Go Diff Review Help
┌──────────────────────┐┌┤Editor├────────────────────────────────────────────────┐
│ Explorer Find Review││╭────────────╮ │
│└-📂 TuiCode │││Workbench.cs│ │
│ ├+📁 docs │││ ╰─────────────────────────────────────────╮│
│ ├-📂 src ││││ 11 public sealed class Workbench : Window ││
│ │ ├+📁 TuiCode ││││ 186 public void OpenFolder(IDirectoryInfo dire… ││
│ │ └+📁 TuiCode.Work…││││ 191 Sidebar.Search.RunSearch(); ││
│ └─📄 README.md ││││ 192 RefreshReviewIfShowing(); ││
│ ││││ 193 StatusBar.SetMessage($"Opened folder:… ││
│ ││││ 194 ││
│ ││││ 195 RestoreOpenFiles(directory); ││
└──────────────────────┘└───────────────────────────────────────────────────────────┘
Editor • Workbench.cs • C# Ln 193, Col 9
Rows 11 and 186 are drawn on the current-line background. Scrolling past line 198, the method's closing }, drops 186 and pins the next method instead.
Settings › Editor, with the new CheckBox under Wrap long lines:
Indent size 4 ▲▼
[x] Indent with spaces
Line endings (•) Keep each file's ( ) LF ( ) CRLF
[x] Insert final newline
[ ] Wrap long lines
[x] Show sticky lines
Wrap by language
…
Scope
In
- Sticky lines in editor tabs for every language Go to symbol reads, Markdown included.
- The cap of three, and none on a short editor.
- Keeping the cursor and every jump clear of the pinned lines.
- Clicking a pinned line to go there.
- The Settings › Editor checkbox.
Out
- Diff tabs and document tabs (the PR overview). A diff is a different view with its own scrolling.
- A breadcrumb bar or status-bar readout (option 3), and
gsopening on the current symbol (option 2). Either can be its own idea later. - Language-server or syntax-tree accuracy. Enclosure comes from indentation, like VS Code's indentation fallback.
- Pinning blocks that aren't definitions (
if,for,using). - A command to toggle it, and a configurable line count.
Delivery
One PR.
Decided
Each of these was the Lead's call, accepted when you approved.
- Indentation decides what encloses a line. Go to symbol records where a definition starts, not where it ends, and indentation is the one signal every grammar shares. Its nesting already works this way. Misformatted code can pin the wrong line; that's the trade VS Code makes too.
- Three lines, innermost first. Enough for class › nested type › method, and the cost of a fourth row on a 30-row terminal outweighs it. VS Code's default is five, for taller windows.
- On by default, with a Settings checkbox and no command. It's a set-and-forget preference like Wrap long lines' checkbox, not something you flip mid-task. VS Code and JetBrains both ship it on. A Toggle sticky lines command would need
tsl, whichts(toggle sidebar) already prefixes. - The pinned lines come from the same scan as Go to symbol, so a file with no grammar (plain text) has none, and nothing new goes in the binary.
- Word wrap on: a long pinned line shows its first row only, cut with
….
Original idea
The idea as filed
Opportunity
Halfway down a long method or class, I can't see what I'm inside of.
The vision's user spends most of the day reading code they didn't write, often in a narrow terminal over SSH. Once a method's signature scrolls off the top, there's nothing on screen that says which method, or which class, the lines in front of you belong to. You scroll back up to find out and lose your place, or open Go to symbol (gs) just to read where you are. It gets worse in exactly the files you're trying to understand: long classes, nested types, and big Markdown docs where the heading you're under scrolled away pages ago. Jumping in from Find results, blame or a diff lands you mid-file with no context at all.
Evidence
- JetBrains added sticky lines in IntelliJ IDEA 2024.1, on by default, "to simplify working with large files and exploring new codebases": the enclosing class and method signatures stay pinned at the top of the editor.
- VS Code has Sticky Scroll (View › Appearance › Sticky Scroll), which pins class, function and Markdown heading lines the same way.
- Terminal editors: Neovim users install nvim-treesitter-context (3.2k stars) for this. Helix users asked for it (#2740, #10672, and a statusline variant in discussion #7813), and a 140-comment sticky context PR closed unmerged. People want it, and it's harder than it looks.
- Inward: Go to symbol (Go to symbol in the current file #137, Go to symbol (gs): jump to a type, method or property in the current file #224–Go to symbol covers fields, enum members and Markdown headings #226) already reads each file's classes, methods, properties and Markdown headings, with their line and nesting depth. TuiCode knows what you're inside of; it just never tells you unless you ask. It only records where a definition starts, though, not where it ends, so "what encloses this line" would need working out.
Why it fits
- Vision, Who it's for: "spend most of their time navigating code bases, reviewing PRs and trying to understand existing/new code". Knowing where you are is the first step in understanding code.
- Familiar: VS Code and JetBrains users both have this on by default now, and they'll notice it's missing.
- Terminal-honest: a narrow terminal shows fewer lines, so the signature scrolls away sooner, which makes the need bigger in a terminal than in a GUI. Sticky rows cost screen height, though, and a status-bar or tab-title readout would cost none. That trade-off is for the pitch.
- Nothing is added to the binary. It reuses the symbol scan that's already there.
Activity
a-team-app commentedon Oct 8, 2026
Now in front of you, in place of #62 (this one's High, that one's Low). I checked it against main: it still holds as drafted, so nothing's changed. Everything I settled is under Assumed; comment to change any of it.
a-team-app commentedon Oct 8, 2026
Broken down into one task: #474. It waits on #442 (Terminal.Gui 2.5), which changes the editor's draw loop the pinned lines draw into.
Nothing was left open; Assumed is now Decided.
a-team-app commentedon Oct 11, 2026
Tried on a fresh build of main: class and method lines pin as you scroll, clicking a pinned line jumps there, Go to line lands two rows below the pins, and Settings › Editor has Show sticky lines. One gap:
tuicode file.cs:214puts the line right under the pins with no margin. Filed as Idea #504.