Skip to content

Halfway down a long method or class, I can't see what I'm inside of #349

Description

@a-team-app

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

Options considered

  1. 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.
  2. Go to symbol opens on the symbol you're in. Cheap: gs highlights your method, and Esc takes you back. Still something you ask for rather than see, and it hides the code while it's open.
  3. 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.
  4. 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.
  5. 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 gs opening 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, which ts (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

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

  1. added
    a-team:ideaFound by the a-team Lead; give it a Priority to have it pitched
    on Sep 29, 2026
  2. added
    pitchAn a-team pitch: Lead shapes it, reviewer approves it
    on Oct 8, 2026
  3. a-team-app commented on Oct 8, 2026

    @a-team-app
    ContributorAuthor

    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.

  4. a-team-app commented on Oct 8, 2026

    @a-team-app
    ContributorAuthor

    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.

  5. a-team-app commented on Oct 11, 2026

    @a-team-app
    ContributorAuthor

    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:214 puts the line right under the pins with no margin. Filed as Idea #504.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a-team:ideaFound by the a-team Lead; give it a Priority to have it pitchedpitchAn a-team pitch: Lead shapes it, reviewer approves it

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions