diff --git a/oviewer/document.go b/oviewer/document.go index f2074dd0..0acf2706 100644 --- a/oviewer/document.go +++ b/oviewer/document.go @@ -113,7 +113,7 @@ func NewDocument() (*Document, error) { ColumnDelimiter: "", TabWidth: 8, MarkStyleWidth: 1, - PlainMode: true, + PlainMode: false, }, lastContentsNum: -1, seekable: true, diff --git a/oviewer/help.go b/oviewer/help.go index 8f23ac03..01f580cf 100644 --- a/oviewer/help.go +++ b/oviewer/help.go @@ -1,6 +1,8 @@ package oviewer import ( + "bufio" + "bytes" "fmt" "io" "strings" @@ -29,99 +31,16 @@ func NewHelp(k KeyBind) (*Document, error) { // KeyBindString returns keybind as a string for help. func KeyBindString(k KeyBind) string { - var b strings.Builder - fmt.Fprint(&b, gchalk.Bold("\n\tKey binding\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionExit, "quit") - k.writeKeyBind(&b, actionCancel, "cancel") - k.writeKeyBind(&b, actionWriteExit, "output screen and quit") - k.writeKeyBind(&b, actionWriteBA, "set output screen and quit") - k.writeKeyBind(&b, actionSuspend, "suspend") - k.writeKeyBind(&b, actionHelp, "display help screen") - k.writeKeyBind(&b, actionLogDoc, "display log screen") - k.writeKeyBind(&b, actionSync, "screen sync") - k.writeKeyBind(&b, actionFollow, "follow mode toggle") - k.writeKeyBind(&b, actionFollowAll, "follow all mode toggle") - k.writeKeyBind(&b, actionToggleMouse, "enable/disable mouse") - - fmt.Fprint(&b, gchalk.Bold("\n\tMoving\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionMoveDown, "forward by one line") - k.writeKeyBind(&b, actionMoveUp, "backward by one line") - k.writeKeyBind(&b, actionMoveTop, "go to top of document") - k.writeKeyBind(&b, actionMoveBottom, "go to end of document") - k.writeKeyBind(&b, actionMovePgDn, "forward by page") - k.writeKeyBind(&b, actionMovePgUp, "backward by page") - k.writeKeyBind(&b, actionMoveHfDn, "forward a half page") - k.writeKeyBind(&b, actionMoveHfUp, "backward a half page") - k.writeKeyBind(&b, actionMoveLeft, "scroll to left") - k.writeKeyBind(&b, actionMoveRight, "scroll to right") - k.writeKeyBind(&b, actionMoveHfLeft, "scroll left half screen") - k.writeKeyBind(&b, actionMoveHfRight, "scroll right half screen") - k.writeKeyBind(&b, actionGoLine, "go to line(input number)") - - fmt.Fprint(&b, gchalk.Bold("\n\tMove document\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionNextDoc, "next document") - k.writeKeyBind(&b, actionPreviousDoc, "previous document") - k.writeKeyBind(&b, actionCloseDoc, "close current document") - - fmt.Fprint(&b, gchalk.Bold("\n\tMark position\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionMark, "mark current position") - k.writeKeyBind(&b, actionRemoveMark, "remove mark current position") - k.writeKeyBind(&b, actionRemoveAllMark, "remove all mark") - k.writeKeyBind(&b, actionMoveMark, "move to next marked position") - k.writeKeyBind(&b, actionMovePrevMark, "move to previous marked position") - - fmt.Fprint(&b, gchalk.Bold("\n\tSearch\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionSearch, "forward search mode") - k.writeKeyBind(&b, actionBackSearch, "backward search mode") - k.writeKeyBind(&b, actionNextSearch, "repeat forward search") - k.writeKeyBind(&b, actionNextBackSearch, "repeat backward search") - - fmt.Fprint(&b, gchalk.Bold("\n\tChange display\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionWrap, "wrap/nowrap toggle") - k.writeKeyBind(&b, actionColumnMode, "column mode toggle") - k.writeKeyBind(&b, actionRainbow, "column rainbow toggle") - k.writeKeyBind(&b, actionAlternate, "alternate rows of style toggle") - k.writeKeyBind(&b, actionLineNumMode, "line number toggle") - k.writeKeyBind(&b, actionPlain, "original decoration toggle") - - fmt.Fprint(&b, gchalk.Bold("\n\tChange Display with Input\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionViewMode, "view mode selection") - k.writeKeyBind(&b, actionDelimiter, "column delimiter string") - k.writeKeyBind(&b, actionHeader, "number of header lines") - k.writeKeyBind(&b, actionSkipLines, "number of skip lines") - k.writeKeyBind(&b, actionTabWidth, "TAB width") - k.writeKeyBind(&b, actionMultiColor, "multi color highlight") - k.writeKeyBind(&b, actionJumpTarget, "jump target") - - fmt.Fprint(&b, gchalk.Bold("\n\tSection\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionSection, "section delimiter regular expression") - k.writeKeyBind(&b, actionSectionStart, "section start position") - k.writeKeyBind(&b, actionNextSection, "next section") - k.writeKeyBind(&b, actionPrevSection, "previous section") - k.writeKeyBind(&b, actionLastSection, "last section") - k.writeKeyBind(&b, actionFollowSection, "follow section mode toggle") - - fmt.Fprint(&b, gchalk.Bold("\n\tClose and reload\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, actionCloseFile, "close file") - k.writeKeyBind(&b, actionReload, "reload file") - k.writeKeyBind(&b, actionWatch, "watch mode") - k.writeKeyBind(&b, actionWatchInterval, "set watch interval") - - fmt.Fprint(&b, gchalk.Bold("\n\tKey binding when typing\n")) - fmt.Fprint(&b, "\n") - k.writeKeyBind(&b, inputCaseSensitive, "case-sensitive toggle") - k.writeKeyBind(&b, inputRegexpSearch, "regular expression search toggle") - k.writeKeyBind(&b, inputIncSearch, "incremental search toggle") - return b.String() + s := bufio.NewScanner(bytes.NewBufferString(k.String())) + var buf bytes.Buffer + for s.Scan() { + line := s.Text() + if strings.HasPrefix(line, "\t") { + line = gchalk.Bold(line) + } + fmt.Fprintln(&buf, line) + } + return buf.String() } func (k KeyBind) writeKeyBind(w io.Writer, action string, detail string) { diff --git a/oviewer/keybind.go b/oviewer/keybind.go index cb6ce0a8..e0c901aa 100644 --- a/oviewer/keybind.go +++ b/oviewer/keybind.go @@ -76,8 +76,8 @@ const ( inputRegexpSearch = "input_regexp_search" ) -// handlerMap returns a map of the action's handlers. -func (root *Root) handlerMap() map[string]func() { +// handlers returns a map of the action's handlers. +func (root *Root) handlers() map[string]func() { return map[string]func(){ actionExit: root.Quit, actionWriteBA: root.setWriteBAMode, @@ -149,7 +149,7 @@ func (root *Root) handlerMap() map[string]func() { type KeyBind map[string][]string // defaultKeyBinds are the default keybindings. -func defaultKeyBinds() map[string][]string { +func defaultKeyBinds() KeyBind { return map[string][]string{ actionExit: {"Escape", "q"}, actionWriteBA: {"ctrl+q"}, @@ -217,8 +217,105 @@ func defaultKeyBinds() map[string][]string { } } +// String returns keybind as a string for help. +func (k KeyBind) String() string { + var b strings.Builder + fmt.Fprint(&b, "\n\tKey binding\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionExit, "quit") + k.writeKeyBind(&b, actionCancel, "cancel") + k.writeKeyBind(&b, actionWriteExit, "output screen and quit") + k.writeKeyBind(&b, actionWriteBA, "set output screen and quit") + k.writeKeyBind(&b, actionSuspend, "suspend") + k.writeKeyBind(&b, actionHelp, "display help screen") + k.writeKeyBind(&b, actionLogDoc, "display log screen") + k.writeKeyBind(&b, actionSync, "screen sync") + k.writeKeyBind(&b, actionFollow, "follow mode toggle") + k.writeKeyBind(&b, actionFollowAll, "follow all mode toggle") + k.writeKeyBind(&b, actionToggleMouse, "enable/disable mouse") + + fmt.Fprint(&b, "\n\tMoving\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionMoveDown, "forward by one line") + k.writeKeyBind(&b, actionMoveUp, "backward by one line") + k.writeKeyBind(&b, actionMoveTop, "go to top of document") + k.writeKeyBind(&b, actionMoveBottom, "go to end of document") + k.writeKeyBind(&b, actionMovePgDn, "forward by page") + k.writeKeyBind(&b, actionMovePgUp, "backward by page") + k.writeKeyBind(&b, actionMoveHfDn, "forward a half page") + k.writeKeyBind(&b, actionMoveHfUp, "backward a half page") + k.writeKeyBind(&b, actionMoveLeft, "scroll to left") + k.writeKeyBind(&b, actionMoveRight, "scroll to right") + k.writeKeyBind(&b, actionMoveHfLeft, "scroll left half screen") + k.writeKeyBind(&b, actionMoveHfRight, "scroll right half screen") + k.writeKeyBind(&b, actionGoLine, "go to line(input number)") + + fmt.Fprint(&b, "\n\tMove document\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionNextDoc, "next document") + k.writeKeyBind(&b, actionPreviousDoc, "previous document") + k.writeKeyBind(&b, actionCloseDoc, "close current document") + + fmt.Fprint(&b, "\n\tMark position\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionMark, "mark current position") + k.writeKeyBind(&b, actionRemoveMark, "remove mark current position") + k.writeKeyBind(&b, actionRemoveAllMark, "remove all mark") + k.writeKeyBind(&b, actionMoveMark, "move to next marked position") + k.writeKeyBind(&b, actionMovePrevMark, "move to previous marked position") + + fmt.Fprint(&b, "\n\tSearch\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionSearch, "forward search mode") + k.writeKeyBind(&b, actionBackSearch, "backward search mode") + k.writeKeyBind(&b, actionNextSearch, "repeat forward search") + k.writeKeyBind(&b, actionNextBackSearch, "repeat backward search") + + fmt.Fprint(&b, "\n\tChange display\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionWrap, "wrap/nowrap toggle") + k.writeKeyBind(&b, actionColumnMode, "column mode toggle") + k.writeKeyBind(&b, actionRainbow, "column rainbow toggle") + k.writeKeyBind(&b, actionAlternate, "alternate rows of style toggle") + k.writeKeyBind(&b, actionLineNumMode, "line number toggle") + k.writeKeyBind(&b, actionPlain, "original decoration toggle") + + fmt.Fprint(&b, "\n\tChange Display with Input\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionViewMode, "view mode selection") + k.writeKeyBind(&b, actionDelimiter, "column delimiter string") + k.writeKeyBind(&b, actionHeader, "number of header lines") + k.writeKeyBind(&b, actionSkipLines, "number of skip lines") + k.writeKeyBind(&b, actionTabWidth, "TAB width") + k.writeKeyBind(&b, actionMultiColor, "multi color highlight") + k.writeKeyBind(&b, actionJumpTarget, "jump target") + + fmt.Fprint(&b, "\n\tSection\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionSection, "section delimiter regular expression") + k.writeKeyBind(&b, actionSectionStart, "section start position") + k.writeKeyBind(&b, actionNextSection, "next section") + k.writeKeyBind(&b, actionPrevSection, "previous section") + k.writeKeyBind(&b, actionLastSection, "last section") + k.writeKeyBind(&b, actionFollowSection, "follow section mode toggle") + + fmt.Fprint(&b, "\n\tClose and reload\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, actionCloseFile, "close file") + k.writeKeyBind(&b, actionReload, "reload file") + k.writeKeyBind(&b, actionWatch, "watch mode") + k.writeKeyBind(&b, actionWatchInterval, "set watch interval") + + fmt.Fprint(&b, "\n\tKey binding when typing\n") + fmt.Fprint(&b, "\n") + k.writeKeyBind(&b, inputCaseSensitive, "case-sensitive toggle") + k.writeKeyBind(&b, inputRegexpSearch, "regular expression search toggle") + k.writeKeyBind(&b, inputIncSearch, "incremental search toggle") + return b.String() +} + // GetKeyBinds returns the current key mapping. -func GetKeyBinds(config Config) map[string][]string { +func GetKeyBinds(config Config) KeyBind { keyBind := make(map[string][]string) if strings.ToLower(config.DefaultKeyBind) != "disable" { keyBind = defaultKeyBinds() @@ -227,18 +324,18 @@ func GetKeyBinds(config Config) map[string][]string { return keyBind } -func updateKeyBind(keyBind map[string][]string, bind map[string][]string) map[string][]string { +func updateKeyBind(keyBind KeyBind, bind KeyBind) KeyBind { for k, v := range bind { keyBind[k] = v } return keyBind } -func (root *Root) setKeyBind(keyBind map[string][]string) error { +func (root *Root) setKeyBind(keyBind KeyBind) error { c := root.keyConfig in := root.inputKeyConfig - actionHandlers := root.handlerMap() + actionHandlers := root.handlers() for name, keys := range keyBind { handler := actionHandlers[name] diff --git a/oviewer/keybind_test.go b/oviewer/keybind_test.go new file mode 100644 index 00000000..7deec2a6 --- /dev/null +++ b/oviewer/keybind_test.go @@ -0,0 +1,64 @@ +package oviewer + +import ( + "bufio" + "bytes" + "strings" + "testing" + + "github.com/gdamore/tcell/v2" +) + +func Test_defaultKeyBinds(t *testing.T) { + tests := []struct { + name string + }{ + { + name: "KeyBind", + }, + } + tcellNewScreen = fakeScreen + defer func() { + tcellNewScreen = tcell.NewScreen + }() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root, err := NewRoot(bytes.NewBufferString("test")) + if err != nil { + t.Fatal("NewRoot failed: ", err) + } + hm := root.handlers() + kb := defaultKeyBinds() + if len(hm) != len(kb) { + t.Errorf("number of KeyBind = %v, want %v", len(hm), len(kb)) + } + }) + } +} + +func TestKeyBind_String(t *testing.T) { + tests := []struct { + name string + k KeyBind + }{ + { + name: "KeyBind String", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + kb := defaultKeyBinds() + kbStr := kb.String() + count := 0 + s := bufio.NewScanner(bytes.NewBufferString(kbStr)) + for s.Scan() { + if strings.HasPrefix(s.Text(), " ") { + count++ + } + } + if count != len(kb) { + t.Errorf("number of KeyBind String = %v, want %v", count, len(kb)) + } + }) + } +}