mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-16 02:26:24 -04:00
Escaping a patch explorer (staging / patch building) back to the focused main view it was entered from used to replay a numeric scroll position and selection index captured on the way in. But the reason to escape after staging or dropping a hunk is that the content changed, so a saved index points at the wrong line — and the host auto-advances the explorer's selection to a still-valid line anyway, which is the line the user actually cares about returning to. Restore by *patch identity* instead. On escape, read the (file, type, source line) the explorer currently has selected, then have the main view's re-render land on the row that matches it: scan the incoming content as it loads (the inverse of the diff-line primitive), and once the matching row plus a screenful below it have loaded, swap the off-screen render in and scroll to / select that row in one step. FocusPoint with scrollIntoView centres the row only if it's off-screen, so the common unchanged-content escape — where the row is already where it was — doesn't move at all. If the line is gone (the content really changed), nothing is forced. This generalizes the scroll restore from a fixed origin to a predicate (RenderRestore: FirstPaintReady decides when the saved position is reachable, Apply re-establishes it), folding the separate selection restore into the same first paint — so it no longer rides a post-load callback that could fire early. The restore also now survives task replacement, which the numeric version did not: a periodic refresh can stop the escape's re-render before it first-paints. The pending restore is held on the buffer manager and is *not* cleared when a task starts, so the replacement task picks it up. It is not gated on the command key — staging the last unstaged hunk re-renders `git diff` as `git diff --cached`, a different command, yet the line to land on is still in the new content — but validates itself: the scan finds the target line only when the content still contains it, so applying it to a different item is a harmless no-op. A task clears it once it has applied it (found or not), so it lives for exactly one re-render. Because the restore is anchored on content identity and is idempotent, "survive replacement" and "restore by identity" are one mechanism, not two. With the identity in hand the snapshot no longer needs the captured scroll/index; they're derived from the explorer's live selection. |
||
|---|---|---|
| .. | ||
| attribute.go | ||
| AUTHORS | ||
| block_events_test.go | ||
| CHANGES_tcell.md | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| doc.go | ||
| double_click_test.go | ||
| edit.go | ||
| escape.go | ||
| escape_test.go | ||
| flush_test.go | ||
| gui.go | ||
| gui_others.go | ||
| gui_windows.go | ||
| key.go | ||
| keybinding.go | ||
| LICENSE | ||
| mouse_capture_test.go | ||
| README.md | ||
| scrollbar.go | ||
| scrollbar_test.go | ||
| suspend_test.go | ||
| task.go | ||
| task_manager.go | ||
| task_manager_test.go | ||
| tcell_driver.go | ||
| tcell_driver_test.go | ||
| text_area.go | ||
| text_area_test.go | ||
| user_event_queue_test.go | ||
| view.go | ||
| view_test.go | ||
GOCUI - Go Console User Interface
Minimalist Go package aimed at creating Console User Interfaces. A community fork based on the amazing work of jroimartin
Features
- Minimalist API.
- Views (the "windows" in the GUI) implement the interface io.ReadWriter.
- Support for overlapping views.
- The GUI can be modified at runtime (concurrent-safe).
- Global and view-level keybindings.
- Mouse support.
- Colored text.
- Customizable editing mode.
- Easy to build reusable widgets, complex layouts...
About fork
This fork has many improvements over the original work from jroimartin.
- Written ontop of TCell
- Better wide character support
- Support for 1 Line height views
- Better support for running in docker container
- Customize frame colors
- Improved code comments and quality
- Many small improvements
- Change Visibility of views
For information about this org see: awesome-gocui/about.
Installation
Execute:
$ go get github.com/awesome-gocui/gocui
Documentation
Execute:
$ go doc github.com/awesome-gocui/gocui
Or visit godoc.org to read it online.
Example
See the _example folder for more examples
package main
import (
"fmt"
"log"
"github.com/awesome-gocui/gocui"
)
func main() {
g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.SetManagerFunc(layout)
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
log.Panicln(err)
}
}
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2, 0); err != nil {
if !gocui.IsUnknownView(err) {
return err
}
if _, err := g.SetCurrentView("hello"); err != nil {
return err
}
fmt.Fprintln(v, "Hello world!")
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
Screenshots
Projects using gocui
- komanda-cli: IRC Client For Developers.
- vuls: Agentless vulnerability scanner for Linux/FreeBSD.
- wuzz: Interactive cli tool for HTTP inspection.
- httplab: Interactive web server.
- domainr: Tool that checks the availability of domains based on keywords.
- gotime: Time tracker for projects and tasks.
- claws: Interactive command line client for testing websockets.
- terminews: Terminal based RSS reader.
- diagram: Tool to convert ascii arts into hand drawn diagrams.
- pody: CLI app to manage Pods in a Kubernetes cluster.
- kubexp: Kubernetes client.
- kcli: Tool for inspecting kafka topics/partitions/messages.
- fac: git merge conflict resolver
- jsonui: Interactive JSON explorer for your terminal.
- cointop: Interactive terminal based UI application for tracking cryptocurrencies.
- lazygit: simple terminal UI for git commands.
- lazydocker: The lazier way to manage everything docker.
Note: if your project is not listed here, let us know! :)


