diff --git a/go.mod b/go.mod index b5e36bc..5bb98c1 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/ulikunitz/xz v0.5.12 - golang.org/x/exp v0.0.0-20241210194714-1829a127f884 + golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 golang.org/x/sync v0.10.0 golang.org/x/term v0.27.0 ) @@ -39,7 +39,7 @@ require ( github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/cast v1.7.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/go.sum b/go.sum index d14f718..87a9649 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= -github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -91,8 +91,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= +golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/main.go b/main.go index e5870d5..44251d3 100644 --- a/main.go +++ b/main.go @@ -361,7 +361,7 @@ func openFile(fileName string) (*os.File, error) { return os.Open(fileName) } -// copyOutput just outputs the input (standard input if there is no first file). +// copyOutput outputs the content of the specified file or standard input. func copyOutput(args []string) error { files := argsToFiles(args) fileName := "" diff --git a/oviewer/control.go b/oviewer/control.go index e318506..4645253 100644 --- a/oviewer/control.go +++ b/oviewer/control.go @@ -238,6 +238,8 @@ func (m *Document) requestLoad(chunkNum int) { } // requestLoadSync sends instructions to load chunks into memory. +// requestLoadSync is a synchronous version of [Document.requestLoad]. +// Note: Calling requestLoadSync when not at EOF may result in delayed response. func (m *Document) requestLoadSync(chunkNum int) bool { sc := controlSpecifier{ request: requestLoad, diff --git a/oviewer/doclist.go b/oviewer/doclist.go index ee94f48..f8dd8e7 100644 --- a/oviewer/doclist.go +++ b/oviewer/doclist.go @@ -22,7 +22,7 @@ func (root *Root) getDocument(docNum int) *Document { return root.DocList[docNum] } -// hasDocChanged() returns if doc has changed. +// hasDocChanged checks if any document in the list has changed. func (root *Root) hasDocChanged() bool { root.mu.RLock() defer root.mu.RUnlock() diff --git a/oviewer/document.go b/oviewer/document.go index be29f6c..a67b83c 100644 --- a/oviewer/document.go +++ b/oviewer/document.go @@ -29,21 +29,25 @@ const ( type documentType int -// The Document structure contains the values -// for the logical screen. +// Document represents a document with various properties and methods for handling +// file operations, caching, synchronization, and display settings. type Document struct { // documentType is the type of document. documentType documentType // File is the os.File. file *os.File + // cache is an LRU cache for storing lines. cache *lru.Cache[int, LineC] // parent is the parent document. - parent *Document + parent *Document + // lineNumMap maps line numbers. lineNumMap *biomap.Map[int, int] - ticker *time.Ticker + // ticker is used for periodic updates. + ticker *time.Ticker + // tickerDone is a channel to signal ticker termination. tickerDone chan struct{} // ctlCh is the channel for controlling the reader goroutine. ctlCh chan controlSpecifier @@ -51,7 +55,8 @@ type Document struct { // multiColorRegexps holds multicolor regular expressions in slices. multiColorRegexps []*regexp.Regexp // store represents store management. - store *store + store *store + // followStore represents follow store management. followStore *store // conv is an interface that converts escape sequences, etc. @@ -59,9 +64,10 @@ type Document struct { // alignConv is an interface that converts alignment. alignConv *align + // cond is a condition variable for synchronization. cond *sync.Cond - // fileName is the file name to display. + // FileName is the file name to display. FileName string // Caption is an additional caption to display after the file name. Caption string @@ -97,7 +103,7 @@ type Document struct { // markedPoint is the position of the marked line. markedPoint int - // Last moved Section position. + // lastSectionPosNum is the last moved section position. lastSectionPosNum int // latestNum is the endNum read at the end of the screen update. latestNum int @@ -131,25 +137,27 @@ type Document struct { // CFormat is a compressed format. CFormat Compressed + // watchRestart indicates the number of times the watch has restarted. watchRestart int32 - tickerState int32 - // 1 if there is a closed. + // tickerState indicates the state of the ticker. + tickerState int32 + // closed indicates if the document is closed (1 if closed). closed int32 - // 1 if there is a tmpFollow mode. + // tmpFollow indicates if there is a temporary follow mode (1 if true). tmpFollow int32 // tmpLN is a temporary line number when the number of lines is undetermined. tmpLN int32 - // WatchMode is watch mode. + // WatchMode indicates if watch mode is enabled. WatchMode bool // preventReload is true to prevent reload. preventReload bool - // Is it possible to seek. + // seekable indicates if seeking is possible. seekable bool - // Is it possible to reopen. + // reopenable indicates if reopening is possible. reopenable bool - // If nonMatch is true, non-matching lines are searched. + // nonMatch indicates if non-matching lines are searched. nonMatch bool } @@ -211,7 +219,8 @@ type LineC struct { eolStyle tcell.Style } -// NewDocument returns Document. +// NewDocument creates and initializes a new [Document] with default settings. +// It returns a pointer to the Document and an error if the cache initialization fails. func NewDocument() (*Document, error) { m := &Document{ documentType: DocNormal, @@ -239,7 +248,8 @@ func NewDocument() (*Document, error) { return m, nil } -// NewCache creates a new cache. +// NewCache initializes a new LRU cache for the Document. +// It returns an error if the cache cannot be created. func (m *Document) NewCache() error { cache, err := lru.New[int, LineC](1024) if err != nil { @@ -250,6 +260,11 @@ func (m *Document) NewCache() error { return nil } +// converterType returns the appropriate Converter based on the provided name. +// Parameters: +// - name: a string representing the name of the converter type. +// Returns: +// - A Converter interface corresponding to the specified name. // converterType returns the Converter type. func (m *Document) converterType(name string) Converter { switch name { @@ -263,7 +278,9 @@ func (m *Document) converterType(name string) Converter { return defaultConverter } -// OpenDocument opens a file and returns a Document. +// OpenDocument opens a file specified by fileName and returns a Document. +// If the fileName is "-", it reads from stdin. It returns an error if the file +// cannot be opened, is a directory, or if there are issues initializing the Document. func OpenDocument(fileName string) (*Document, error) { if fileName == "-" { return STDINDocument() @@ -304,7 +321,8 @@ func OpenDocument(fileName string) (*Document, error) { return m, nil } -// STDINDocument returns a Document that reads stdin. +// STDINDocument creates and returns a Document that reads from stdin. +// It returns a pointer to the Document and an error if the Document initialization fails. func STDINDocument() (*Document, error) { m, err := NewDocument() if err != nil { @@ -348,7 +366,13 @@ func (m *Document) Line(n int) ([]byte, error) { return s.GetChunkLine(chunkNum, cn) } -// GetChunkLine returns one line from buffer. +// GetChunkLine returns a specific line from a specified chunk. +// Parameters: +// - chunkNum: the chunk number to retrieve the line from. +// - cn: the line number within the chunk. +// Returns: +// - A byte slice containing the line data. +// - An error if the chunk or line number is out of range. func (s *store) GetChunkLine(chunkNum int, cn int) ([]byte, error) { s.mu.Lock() defer s.mu.Unlock() @@ -363,22 +387,6 @@ func (s *store) GetChunkLine(chunkNum int, cn int) ([]byte, error) { return bytes.TrimSuffix(chunk.lines[cn], []byte("\n")), nil } -// GetLine returns one line from buffer. -// Deprecated: Use LineString instead. -func (m *Document) GetLine(n int) string { - s, err := m.Line(n) - if err != nil { - return "" - } - return string(s) -} - -// LineString returns one line from buffer. -func (m *Document) LineString(n int) string { - str, _ := m.LineStr(n) - return str -} - // LineStr returns one line from buffer. func (m *Document) LineStr(n int) (string, error) { s, err := m.Line(n) @@ -414,7 +422,7 @@ func (m *Document) Export(w io.Writer, start int, end int) error { return nil } -// BufStartNum return start line number. +// BufStartNum returns the starting line number of the buffer. func (m *Document) BufStartNum() int { return int(atomic.LoadInt32(&m.store.startNum)) } @@ -442,17 +450,25 @@ func (m *Document) WaitEOF() { m.cond.Wait() } -// BufEOF return true if EOF is reached. +// BufEOF checks if the end of the file (EOF) has been reached in the document buffer. +// Returns: +// - A boolean value: true if EOF is reached, false otherwise. func (m *Document) BufEOF() bool { return atomic.LoadInt32(&m.store.eof) == 1 } -// ClearCache clears the cache. +// ClearCache clears the LRU cache of the document. +// It does not take any parameters and does not return any values. func (m *Document) ClearCache() { m.cache.Purge() } -// contents returns contents from line number and tabWidth. +// contents returns the contents of a specific line number in the document buffer. +// Parameters: +// - lN: the line number to retrieve the contents for. +// Returns: +// - A contents type representing the line's contents. +// - An error if the line number is out of range or if there is an issue retrieving the line. func (m *Document) contents(lN int) (contents, error) { if lN < 0 || lN >= m.BufEndNum() { return nil, ErrOutOfRange @@ -472,7 +488,7 @@ func (m *Document) contentsLine(lN int) (contents, tcell.Style, error) { return lc, style, err } -// getLineC returns contents from line number and tabWidth. +// getLineC returns the content of the specified line number. // If the line number does not exist, EOF content is returned. func (m *Document) getLineC(lN int) LineC { if line, ok := m.cache.Get(lN); ok { @@ -517,7 +533,7 @@ func (m *Document) firstLine() int { return m.SkipLines + m.Header } -// watchMode sets the document to watch mode. +// watchMode sets the document to watch mode and configures section settings. func (m *Document) watchMode() { m.WatchMode = true if m.SectionDelimiter == "" { @@ -582,3 +598,20 @@ func (m *Document) setColumnWidths() { } m.columnWidths = guesswidth.Positions(buf, header, 2) } + +// GetLine returns one line from buffer. +// Deprecated: Use [Document.LineString] instead. +func (m *Document) GetLine(n int) string { + s, err := m.Line(n) + if err != nil { + return "" + } + return string(s) +} + +// LineString returns one line from buffer. +// Deprecated: Use [Document.LineStr] instead. +func (m *Document) LineString(n int) string { + str, _ := m.LineStr(n) + return str +} diff --git a/oviewer/exec.go b/oviewer/exec.go index d0b057d..153e2d5 100644 --- a/oviewer/exec.go +++ b/oviewer/exec.go @@ -133,7 +133,7 @@ func (command *Command) stderrReload() *bufio.Reader { // ExecCommand return the structure of oviewer. // ExecCommand executes the command and opens stdout/stderr as document. -// obsolete: use NewCommand and Exec instead. +// Deprecated: use [NewCommand] and [Exec] instead. func ExecCommand(cmd *exec.Cmd) (*Root, error) { docout, docerr, err := newOutErrDocument() if err != nil {