v0.3.0 99dc266

session_connection.go RawHistoryFolder

1package client
2
3import (
4	"errors"
5	"fmt"
6
7	"github.com/bnema/vev/internal/domain"
8	"github.com/bnema/vev/internal/ports"
9)
10
11var (
12	errNilSessionTransport  = errors.New("client: nil session transport")
13	ErrEphemeralSessionName = errors.New("client: ephemeral sessions cannot have a name")
14)
15
16// SessionTarget is the validated daemon-facing session selection. Endpoint
17// details are resolved before a transport is opened and never enter this type.
18type SessionTarget struct {
19	Intent      uint8
20	SessionName string
21}
22
23func (t SessionTarget) validate() error {
24	switch t.Intent {
25	case ports.IntentEphemeral:
26		if t.SessionName != "" {
27			return ErrEphemeralSessionName
28		}
29		return nil
30	case ports.IntentNew, ports.IntentAttach, ports.IntentResume:
31		if t.SessionName == "" {
32			return domain.ErrInvalidSessionName
33		}
34	default:
35		return fmt.Errorf("invalid session intent %d", t.Intent)
36	}
37	return domain.ValidateSessionName(t.SessionName)
38}
39
40// SessionConnection owns one already-open transport and its daemon-facing
41// session target. Local sockets and remote carriages use this same owner.
42type SessionConnection struct {
43	transport ports.Transport
44	target    SessionTarget
45}
46
47// NewSessionConnection creates a connection for an already-selected transport.
48// Target validation happens before the connection is used for a Hello.
49func NewSessionConnection(transport ports.Transport, target SessionTarget) (*SessionConnection, error) {
50	if transport == nil {
51		return nil, errNilSessionTransport
52	}
53	if err := target.validate(); err != nil {
54		return nil, fmt.Errorf("invalid session target: %w", err)
55	}
56	return &SessionConnection{transport: transport, target: target}, nil
57}
58
59// Transport returns the owned carriage for this connection.
60func (c *SessionConnection) Transport() ports.Transport {
61	if c == nil {
62		return nil
63	}
64	return c.transport
65}
66
67// AttachRequest returns the common request shape used after transport
68// selection. It contains no remote/proxy semantic.
69func (c *SessionConnection) AttachRequest() AttachRequest {
70	if c == nil {
71		return AttachRequest{}
72	}
73	return AttachRequest{Intent: c.target.Intent, SessionName: c.target.SessionName}
74}
75
76// cloneAttachRequest keeps the immutable request independent from transport
77// ownership while protecting the exact remote target from caller mutation.
78func cloneAttachRequest(request AttachRequest) AttachRequest {
79	if request.RemoteTarget != nil {
80		target := *request.RemoteTarget
81		request.RemoteTarget = &target
82	}
83	if request.ExactTarget != nil {
84		target := *request.ExactTarget
85		request.ExactTarget = &target
86	}
87	return request
88}
89
90// Close releases the owned transport.
91func (c *SessionConnection) Close() error {
92	if c == nil || c.transport == nil {
93		return nil
94	}
95	return c.transport.Close()
96}

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 12

Tags 11

↑↓ moveenter openesc close