feat/focused-dot 6314afc

app.go RawHistoryFolder

1package main
2
3import (
4	"context"
5	"flag"
6	"fmt"
7	"os"
8
9	"github.com/bnema/neferbar/internal/app"
10)
11
12const appUsage = `usage: neferbar app [-once] <field>...
13
14Prints fields of the window that has the focus: one line now, then one more
15each time it changes. With several fields, a tab separates them on the line
16(a title never contains a tab). Fields are empty when no window has the focus.
17
18fields:
19  id     the application id, such as com.github.bnema.dumber
20  name   the short form of the id, such as dumber
21  title  the window title, without control characters
22
23flags:
24`
25
26// runApp is "neferbar app <field>": the focused window, for scripts.
27func runApp(ctx context.Context, args []string, display string) error {
28	fs := flag.NewFlagSet("neferbar app", flag.ContinueOnError)
29	once := fs.Bool("once", false, "print the current value and exit")
30	fs.Usage = func() { fmt.Fprint(os.Stderr, appUsage); fs.PrintDefaults() }
31	if err := fs.Parse(args); err != nil {
32		return err
33	}
34	if fs.NArg() == 0 {
35		fs.Usage()
36		return fmt.Errorf("give at least one field: id, name or title")
37	}
38	var picks []func(app.Window) string
39	for _, field := range fs.Args() {
40		switch field {
41		case "id":
42			picks = append(picks, func(w app.Window) string { return app.Clean(w.ID) })
43		case "name":
44			picks = append(picks, func(w app.Window) string { return app.Clean(app.Name(w.ID)) })
45		case "title":
46			picks = append(picks, func(w app.Window) string { return app.Clean(w.Title) })
47		default:
48			return fmt.Errorf("%q is not a field; use id, name or title", field)
49		}
50	}
51	ctx, cancel := context.WithCancel(ctx)
52	defer cancel()
53	return app.Watch(ctx, display, func(w app.Window) error {
54		var line []byte
55		for i, pick := range picks {
56			if i > 0 {
57				line = append(line, '\t')
58			}
59			line = append(line, pick(w)...)
60		}
61		if _, err := os.Stdout.Write(append(line, '\n')); err != nil {
62			return err
63		}
64		if *once {
65			cancel()
66		}
67		return nil
68	})
69}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 5

Tags 4

↑↓ moveenter openesc close