mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-11-14 12:11:12 +03:00
More work on pager kitten
This commit is contained in:
parent
b0ab5bd5eb
commit
e7e401c8dd
71
kittens/pager/file_input.go
Normal file
71
kittens/pager/file_input.go
Normal file
@ -0,0 +1,71 @@
|
||||
// License: GPLv3 Copyright: 2024, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package pager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
func read_input(input_file *os.File, input_file_name string, input_channel chan<- input_line_struct) {
|
||||
const buf_capacity = 8192
|
||||
var buf_array [buf_capacity]byte
|
||||
output_buf := strings.Builder{}
|
||||
output_buf.Grow(buf_capacity)
|
||||
var err error
|
||||
var n int
|
||||
|
||||
defer func() {
|
||||
_ = input_file.Close()
|
||||
last := input_line_struct{line: output_buf.String(), err: err}
|
||||
if errors.Is(err, io.EOF) {
|
||||
last.err = nil
|
||||
}
|
||||
if len(last.line) > 0 || last.err != nil {
|
||||
input_channel <- last
|
||||
}
|
||||
close(input_channel)
|
||||
}()
|
||||
|
||||
process_chunk := func(chunk []byte) {
|
||||
for len(chunk) > 0 {
|
||||
idx := bytes.IndexByte(chunk, '\n')
|
||||
switch idx {
|
||||
case -1:
|
||||
_, _ = output_buf.Write(chunk)
|
||||
chunk = nil
|
||||
default:
|
||||
_, _ = output_buf.Write(chunk[idx:])
|
||||
chunk = chunk[idx+1:]
|
||||
input_channel <- input_line_struct{line: output_buf.String()}
|
||||
output_buf.Reset()
|
||||
output_buf.Grow(buf_capacity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
read_with_retry := func(b []byte) (n int, err error) {
|
||||
for {
|
||||
n, err = input_file.Read(b)
|
||||
if err != unix.EAGAIN && err != unix.EINTR {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for err != nil {
|
||||
n, err = read_with_retry(buf_array[:])
|
||||
if n > 0 {
|
||||
process_chunk(buf_array[:n])
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ package pager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/tty"
|
||||
@ -23,7 +24,42 @@ var _ = fmt.Print
|
||||
var debugprintln = tty.DebugPrintln
|
||||
var _ = debugprintln
|
||||
|
||||
type input_line_struct struct {
|
||||
line string
|
||||
err error
|
||||
}
|
||||
|
||||
type global_state_struct struct {
|
||||
input_file_name string
|
||||
opts *Options
|
||||
}
|
||||
|
||||
var global_state global_state_struct
|
||||
|
||||
func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
|
||||
global_state.opts = opts_
|
||||
input_channel := make(chan input_line_struct, 4096)
|
||||
var input_file *os.File
|
||||
if len(args) > 1 {
|
||||
return 1, fmt.Errorf("Only a single file can be viewed at a time")
|
||||
}
|
||||
if len(args) == 0 {
|
||||
if tty.IsTerminal(os.Stdin.Fd()) {
|
||||
return 1, fmt.Errorf("STDIN is a terminal and no filename specified. See --help")
|
||||
}
|
||||
input_file = os.Stdin
|
||||
global_state.input_file_name = "/dev/stdin"
|
||||
} else {
|
||||
input_file, err = os.Open(args[0])
|
||||
if err != nil {
|
||||
return 1, err
|
||||
}
|
||||
if tty.IsTerminal(input_file.Fd()) {
|
||||
return 1, fmt.Errorf("%s is a terminal not paging it", args[0])
|
||||
}
|
||||
global_state.input_file_name = args[0]
|
||||
}
|
||||
go read_input(input_file, global_state.input_file_name, input_channel)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,11 @@ choices=pager,scrollback
|
||||
The role the pager is used for. The default is a standard less like pager.
|
||||
'''.format
|
||||
|
||||
help_text = 'Display text in a pager with various features such as searching, copy/paste, etc. Text can some from the specified file or from STDIN.'
|
||||
help_text = '''\
|
||||
Display text in a pager with various features such as searching, copy/paste, etc.
|
||||
Text can some from the specified file or from STDIN. If no filename is specified
|
||||
and STDIN is not a TTY, it is used.
|
||||
'''
|
||||
usage = '[filename]'
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user