Documentation
¶
Overview ¶
Package ui renders the interactive host browser and hands the terminal over to an SSH session when a host is chosen.
Index ¶
- func HumanBytes(n int64) string
- func RunHostBrowser(opts BrowserOptions) error
- func TransferEnds(direction sshclient.Direction, local, remote string) (from, to string)
- type AddHostFunc
- type BrowserOptions
- type RemoteEntry
- type RemoteSession
- type RemoteSessionFunc
- type RemoveHostFunc
- type SessionFunc
- type TransferProgress
- type TransferRequest
- type TransferSummary
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HumanBytes ¶
HumanBytes renders a byte count the way a person reads it. The steps are the 1024 the sizes of files are actually counted in, labelled the way they are usually written.
func RunHostBrowser ¶
func RunHostBrowser(opts BrowserOptions) error
RunHostBrowser shows the host list and blocks until the user quits. Selecting a host releases the terminal, runs an SSH session, then returns to the list.
func TransferEnds ¶
TransferEnds orders the two ends of a transfer the way the bytes travel, so a summary reads forwards whichever direction it went. Both front ends quote the ends through here, which is what keeps them saying the same thing.
Types ¶
type AddHostFunc ¶
AddHostFunc writes a host the user filled in and returns the hosts as they read afterwards, so the browser can show the new one without reading the config again. Where the host is written and what counts as a clash are the service's business; the fields are the form's.
type BrowserOptions ¶
type BrowserOptions struct {
Hosts []config.SSHHost
// Session runs the session behind a selected host.
Session SessionFunc
// Remote opens the file view's session on the host under the cursor, which
// the U and D keys show. A nil Remote leaves those keys saying so.
Remote RemoteSessionFunc
// Add writes a host typed into the form, which the A key shows. A nil Add
// leaves that key saying so.
Add AddHostFunc
// Remove deletes a host from the list, which the X key asks about. A nil
// Remove leaves that key saying so.
Remove RemoveHostFunc
// HostsFile is the file Add writes. The form shows it before it writes there,
// so that a host the user cannot then find is at least a host the browser
// said where it would put.
HostsFile string
// Filter seeds the search box.
Filter string
}
BrowserOptions configures the host browser.
type RemoteEntry ¶
RemoteEntry is one entry the file view's remote pane lists. It is the browser's own shape rather than the protocol's: a pane needs a name, whether it is a directory and how big it is, and nothing else an SFTP listing carries is drawn.
type RemoteSession ¶
type RemoteSession interface {
// Home is the directory the remote pane opens in: where the login landed,
// which is the user's home directory. It is read when the session is built
// rather than asked for here, so that drawing a frame never waits on a
// round trip.
Home() string
// ReadDir lists one remote directory. Paths are the pane's own, so the
// listing is of exactly the string the pane is showing.
ReadDir(path string) ([]RemoteEntry, error)
// Transfer moves one path, reporting progress as it goes. Which way the
// bytes go is what req.Direction says, as it is everywhere else.
Transfer(ctx context.Context, req TransferRequest, progress sshclient.ProgressFunc) error
// Close releases the session and the connection under it.
Close() error
}
RemoteSession is a connection the file view walks and copies over.
It is opened when the view goes up and closed when it comes down, which is what makes browsing a directory tree one dial rather than one per directory. A transfer the user starts reuses this connection too, so a host with a saved password moves every file of a browse without being asked again.
Transfer is called on a goroutine of the view's own, and ctx is cancelled when the user backs out of it: an implementation must return once ctx is done and must not wait on the terminal, which the view still owns.
type RemoteSessionFunc ¶
RemoteSessionFunc opens a session on a host for the file view.
It is the browser's own type rather than the service's, for the same reason SessionFunc is: service imports ui and not the other way round. Passing a nil one leaves the upload and download keys saying that transfers are unavailable, rather than opening a view that could not fill itself.
type RemoveHostFunc ¶
RemoveHostFunc deletes a host and returns the hosts as they read afterwards, so the browser can take the row off screen without reading the config again. Which hosts may be deleted at all — the file ohmyssh writes, and only that one — is the service's business; asking the user whether they meant this one is the browser's.
type SessionFunc ¶
SessionFunc runs a session on a host and returns when it ends. The browser calls it only after the terminal has been released for the session; dialling, the command to run and the exit status are all its business, not the browser's.
type TransferProgress ¶
type TransferProgress struct {
// contains filtered or unexported fields
}
TransferProgress draws a transfer's progress on a writer.
On a terminal it redraws a bar in place, one line for the file being copied and one for the transfer as a whole. Anywhere else — a pipe, a CI log, a file — a stream of cursor moves is unreadable once captured, so it prints one line per completed file instead.
What it writes is dropped on the floor rather than reported: the bar is a convenience, and a terminal that has gone away — a closed pipe, a lost SSH session carrying the output — is not a reason to fail a transfer that is otherwise copying perfectly well.
func NewTransferProgress ¶
func NewTransferProgress(out io.Writer) *TransferProgress
NewTransferProgress returns a reporter that writes to out.
The totals a bar needs are not passed in: they arrive with the first report, which the transfer sends once it has measured its plan.
func (*TransferProgress) Done ¶
func (p *TransferProgress) Done()
Done closes the live display, leaving the cursor on a fresh line so whatever is printed next is not written over the progress bar.
func (*TransferProgress) Update ¶
func (p *TransferProgress) Update(prog sshclient.Progress)
Update draws what the report says. It is safe to call from the copy loop: the work is one formatted line, and a report that changes nothing visible is not redrawn.
type TransferRequest ¶
TransferRequest is one transfer the browser asked for: the two paths and which way the bytes go.
It is the browser's own type rather than the service's, because service imports ui and not the other way round — the same reason SessionFunc exists.
type TransferSummary ¶
type TransferSummary struct {
Direction sshclient.Direction
// From and To are the two ends as the user named them.
From, To string
Files int
Bytes int64
// Err, when set, is why the transfer failed. The line then reports that
// instead of the counts: a transfer that stopped early has no total worth
// quoting.
Err error
}
TransferSummary is what there is to say about a transfer that has finished.
func (TransferSummary) Line ¶
func (s TransferSummary) Line() string
Line renders a transfer the way both the command line and the browser say it, so the same operation reads the same in either.
func (TransferSummary) Report ¶
func (s TransferSummary) Report() string
Report is the finished line a command prints for a transfer that worked: Line with the tick and the colour in front of it, both of which belong to the renderer rather than to the wording.
A transfer that failed is not reported this way. Its error goes back up the call chain instead, so the runner turns it into one prefixed line and an exit status rather than the two lines a report of it would produce.
The styles collapse to plain text when the output is not a terminal, which is what keeps a redirected run free of escape codes.