mirror of
https://github.com/ddworken/hishtory.git
synced 2025-02-13 00:50:22 +01:00
* Add support for custom key bindings for #190 * Add tests for configuring custom key bindings * Simplify key bindings test * Add docs on custom key bindings + error message for unhandled actions
This commit is contained in:
parent
d6a60214a2
commit
c933cbc792
@ -121,6 +121,13 @@ You can customize hishtory's color scheme for the TUI. Run `hishtory config-set
|
|||||||
|
|
||||||
</blockquote></details>
|
</blockquote></details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Custom Key Bindings</summary><blockquote>
|
||||||
|
|
||||||
|
You can customize hishtory's key bindings for the TUI. Run `hishtory config-get key-bindings` to see the current key bindings. You can then run `hishtory config-set key-bindings $action $keybinding` to configure custom key bindings.
|
||||||
|
|
||||||
|
</blockquote></details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Disabling Control+R integration</summary><blockquote>
|
<summary>Disabling Control+R integration</summary><blockquote>
|
||||||
|
|
||||||
@ -195,7 +202,6 @@ Note that this uses [HTTP Basic Auth](https://en.wikipedia.org/wiki/Basic_access
|
|||||||
|
|
||||||
</blockquote></details>
|
</blockquote></details>
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Customizing the install folder</summary><blockquote>
|
<summary>Customizing the install folder</summary><blockquote>
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ func TestParam(t *testing.T) {
|
|||||||
t.Run("testTui/delete", wrapTestForSharding(testTui_delete))
|
t.Run("testTui/delete", wrapTestForSharding(testTui_delete))
|
||||||
t.Run("testTui/color", wrapTestForSharding(testTui_color))
|
t.Run("testTui/color", wrapTestForSharding(testTui_color))
|
||||||
t.Run("testTui/errors", wrapTestForSharding(testTui_errors))
|
t.Run("testTui/errors", wrapTestForSharding(testTui_errors))
|
||||||
|
t.Run("testTui/keybindings", wrapTestForSharding(testTui_keybindings))
|
||||||
t.Run("testTui/ai", wrapTestForSharding(testTui_ai))
|
t.Run("testTui/ai", wrapTestForSharding(testTui_ai))
|
||||||
t.Run("testTui/defaultFilter", wrapTestForSharding(testTui_defaultFilter))
|
t.Run("testTui/defaultFilter", wrapTestForSharding(testTui_defaultFilter))
|
||||||
|
|
||||||
@ -2140,6 +2141,46 @@ func testTui_general(t *testing.T, onlineStatus OnlineStatus) {
|
|||||||
assertNoLeakedConnections(t)
|
assertNoLeakedConnections(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTui_keybindings(t *testing.T) {
|
||||||
|
// Setup
|
||||||
|
defer testutils.BackupAndRestore(t)()
|
||||||
|
tester, _, _ := setupTestTui(t, Online)
|
||||||
|
|
||||||
|
// Check the default config
|
||||||
|
testutils.CompareGoldens(t,
|
||||||
|
tester.RunInteractiveShell(t, `hishtory config-get key-bindings`),
|
||||||
|
"TestTui-KeyBindings-Default",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configure some custom key bindings
|
||||||
|
tester.RunInteractiveShell(t, `hishtory config-set key-bindings down '?'`)
|
||||||
|
tester.RunInteractiveShell(t, `hishtory config-set key-bindings help ctrl+j`)
|
||||||
|
|
||||||
|
// Check that they got configured
|
||||||
|
testutils.CompareGoldens(t,
|
||||||
|
tester.RunInteractiveShell(t, `hishtory config-get key-bindings`),
|
||||||
|
"TestTui-KeyBindings-Configured",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Record a command and demo searching for it
|
||||||
|
tester.RunInteractiveShell(t, `echo 1`)
|
||||||
|
tester.RunInteractiveShell(t, `echo 2`)
|
||||||
|
out := captureTerminalOutput(t, tester, []string{
|
||||||
|
"hishtory SPACE tquery ENTER",
|
||||||
|
"C-j",
|
||||||
|
})
|
||||||
|
out = stripTuiCommandPrefix(t, out)
|
||||||
|
testutils.CompareGoldens(t, out, "TestTui-KeyBindings-Help")
|
||||||
|
|
||||||
|
// Use the custom key binding for scrolling down
|
||||||
|
out = captureTerminalOutput(t, tester, []string{
|
||||||
|
"hishtory SPACE tquery ENTER",
|
||||||
|
"'?' Enter",
|
||||||
|
})
|
||||||
|
out = stripTuiCommandPrefix(t, out)
|
||||||
|
require.Regexp(t, regexp.MustCompile(`^ls ~/\n`), out)
|
||||||
|
}
|
||||||
|
|
||||||
func testTui_errors(t *testing.T) {
|
func testTui_errors(t *testing.T) {
|
||||||
// Setup
|
// Setup
|
||||||
defer testutils.BackupAndRestore(t)()
|
defer testutils.BackupAndRestore(t)()
|
||||||
|
90
client/cmd/configKeyBindings.go
Normal file
90
client/cmd/configKeyBindings.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ddworken/hishtory/client/hctx"
|
||||||
|
"github.com/ddworken/hishtory/client/lib"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var getKeyBindingsCmd = &cobra.Command{
|
||||||
|
Use: "key-bindings",
|
||||||
|
Short: "Get the currently configured key bindings for the TUI",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
ctx := hctx.MakeContext()
|
||||||
|
config := hctx.GetConf(ctx)
|
||||||
|
fmt.Println("up: \t\t\t" + strings.Join(config.KeyBindings.Up, " "))
|
||||||
|
fmt.Println("down: \t\t\t" + strings.Join(config.KeyBindings.Down, " "))
|
||||||
|
fmt.Println("page-up: \t\t" + strings.Join(config.KeyBindings.PageUp, " "))
|
||||||
|
fmt.Println("page-down: \t\t" + strings.Join(config.KeyBindings.PageDown, " "))
|
||||||
|
fmt.Println("select-entry: \t\t" + strings.Join(config.KeyBindings.SelectEntry, " "))
|
||||||
|
fmt.Println("select-entry-and-cd: \t" + strings.Join(config.KeyBindings.SelectEntryAndChangeDir, " "))
|
||||||
|
fmt.Println("left: \t\t\t" + strings.Join(config.KeyBindings.Left, " "))
|
||||||
|
fmt.Println("right: \t\t\t" + strings.Join(config.KeyBindings.Right, " "))
|
||||||
|
fmt.Println("table-left: \t\t" + strings.Join(config.KeyBindings.TableLeft, " "))
|
||||||
|
fmt.Println("table-right: \t\t" + strings.Join(config.KeyBindings.TableRight, " "))
|
||||||
|
fmt.Println("delete-entry: \t\t" + strings.Join(config.KeyBindings.DeleteEntry, " "))
|
||||||
|
fmt.Println("help: \t\t\t" + strings.Join(config.KeyBindings.Help, " "))
|
||||||
|
fmt.Println("quit: \t\t\t" + strings.Join(config.KeyBindings.Quit, " "))
|
||||||
|
fmt.Println("jump-start-of-input: \t" + strings.Join(config.KeyBindings.JumpStartOfInput, " "))
|
||||||
|
fmt.Println("jump-end-of-input: \t" + strings.Join(config.KeyBindings.JumpEndOfInput, " "))
|
||||||
|
fmt.Println("word-left: \t\t" + strings.Join(config.KeyBindings.WordLeft, " "))
|
||||||
|
fmt.Println("word-right: \t\t" + strings.Join(config.KeyBindings.WordRight, " "))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var setKeyBindingsCmd = &cobra.Command{
|
||||||
|
Use: "key-bindings",
|
||||||
|
Short: "Set custom key bindings for the TUI",
|
||||||
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
ctx := hctx.MakeContext()
|
||||||
|
config := hctx.GetConf(ctx)
|
||||||
|
switch args[0] {
|
||||||
|
case "up":
|
||||||
|
config.KeyBindings.Up = args[1:]
|
||||||
|
case "down":
|
||||||
|
config.KeyBindings.Down = args[1:]
|
||||||
|
case "page-up":
|
||||||
|
config.KeyBindings.PageUp = args[1:]
|
||||||
|
case "page-down":
|
||||||
|
config.KeyBindings.PageDown = args[1:]
|
||||||
|
case "select-entry":
|
||||||
|
config.KeyBindings.SelectEntry = args[1:]
|
||||||
|
case "select-entry-and-cd":
|
||||||
|
config.KeyBindings.SelectEntryAndChangeDir = args[1:]
|
||||||
|
case "left":
|
||||||
|
config.KeyBindings.Left = args[1:]
|
||||||
|
case "right":
|
||||||
|
config.KeyBindings.Right = args[1:]
|
||||||
|
case "table-left":
|
||||||
|
config.KeyBindings.TableLeft = args[1:]
|
||||||
|
case "table-right":
|
||||||
|
config.KeyBindings.TableRight = args[1:]
|
||||||
|
case "delete-entry":
|
||||||
|
config.KeyBindings.DeleteEntry = args[1:]
|
||||||
|
case "help":
|
||||||
|
config.KeyBindings.Help = args[1:]
|
||||||
|
case "quit":
|
||||||
|
config.KeyBindings.Quit = args[1:]
|
||||||
|
case "jump-start-of-input":
|
||||||
|
config.KeyBindings.JumpStartOfInput = args[1:]
|
||||||
|
case "jump-end-of-input":
|
||||||
|
config.KeyBindings.JumpEndOfInput = args[1:]
|
||||||
|
case "word-left":
|
||||||
|
config.KeyBindings.WordLeft = args[1:]
|
||||||
|
case "word-right":
|
||||||
|
config.KeyBindings.WordRight = args[1:]
|
||||||
|
default:
|
||||||
|
lib.CheckFatalError(fmt.Errorf("unknown action %q, run `hishtory config-get keybindings` to see the list of currently configured key bindings", args[0]))
|
||||||
|
}
|
||||||
|
lib.CheckFatalError(hctx.SetConfig(config))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
configGetCmd.AddCommand(getKeyBindingsCmd)
|
||||||
|
configSetCmd.AddCommand(setKeyBindingsCmd)
|
||||||
|
}
|
@ -11,6 +11,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ddworken/hishtory/client/data"
|
"github.com/ddworken/hishtory/client/data"
|
||||||
|
"github.com/ddworken/hishtory/client/tui/keybindings"
|
||||||
"github.com/ddworken/hishtory/shared"
|
"github.com/ddworken/hishtory/shared"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -208,6 +209,8 @@ type ClientConfig struct {
|
|||||||
DefaultFilter string `json:"default_filter"`
|
DefaultFilter string `json:"default_filter"`
|
||||||
// The endpoint to use for AI suggestions
|
// The endpoint to use for AI suggestions
|
||||||
AiCompletionEndpoint string `json:"ai_completion_endpoint"`
|
AiCompletionEndpoint string `json:"ai_completion_endpoint"`
|
||||||
|
// Custom key bindings for the TUI
|
||||||
|
KeyBindings keybindings.SerializableKeyMap `json:"key_bindings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ColorScheme struct {
|
type ColorScheme struct {
|
||||||
@ -260,6 +263,7 @@ func GetConfig() (ClientConfig, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ClientConfig{}, fmt.Errorf("failed to parse config file: %w", err)
|
return ClientConfig{}, fmt.Errorf("failed to parse config file: %w", err)
|
||||||
}
|
}
|
||||||
|
config.KeyBindings = config.KeyBindings.WithDefaults()
|
||||||
if config.DisplayedColumns == nil || len(config.DisplayedColumns) == 0 {
|
if config.DisplayedColumns == nil || len(config.DisplayedColumns) == 0 {
|
||||||
config.DisplayedColumns = []string{"Hostname", "CWD", "Timestamp", "Runtime", "Exit Code", "Command"}
|
config.DisplayedColumns = []string{"Hostname", "CWD", "Timestamp", "Runtime", "Exit Code", "Command"}
|
||||||
}
|
}
|
||||||
|
17
client/testdata/TestTui-KeyBindings-Configured
vendored
Normal file
17
client/testdata/TestTui-KeyBindings-Configured
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
up: up alt+OA ctrl+p
|
||||||
|
down: ?
|
||||||
|
page-up: pgup
|
||||||
|
page-down: pgdown
|
||||||
|
select-entry: enter
|
||||||
|
select-entry-and-cd: ctrl+x
|
||||||
|
left: left
|
||||||
|
right: right
|
||||||
|
table-left: shift+left
|
||||||
|
table-right: shift+right
|
||||||
|
delete-entry: ctrl+k
|
||||||
|
help: ctrl+j
|
||||||
|
quit: esc ctrl+c ctrl+d
|
||||||
|
jump-start-of-input: ctrl+a
|
||||||
|
jump-end-of-input: ctrl+e
|
||||||
|
word-left: ctrl+left
|
||||||
|
word-right: ctrl+right
|
17
client/testdata/TestTui-KeyBindings-Default
vendored
Normal file
17
client/testdata/TestTui-KeyBindings-Default
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
up: up alt+OA ctrl+p
|
||||||
|
down: down alt+OB ctrl+n
|
||||||
|
page-up: pgup
|
||||||
|
page-down: pgdown
|
||||||
|
select-entry: enter
|
||||||
|
select-entry-and-cd: ctrl+x
|
||||||
|
left: left
|
||||||
|
right: right
|
||||||
|
table-left: shift+left
|
||||||
|
table-right: shift+right
|
||||||
|
delete-entry: ctrl+k
|
||||||
|
help: ctrl+h
|
||||||
|
quit: esc ctrl+c ctrl+d
|
||||||
|
jump-start-of-input: ctrl+a
|
||||||
|
jump-end-of-input: ctrl+e
|
||||||
|
word-left: ctrl+left
|
||||||
|
word-right: ctrl+right
|
31
client/testdata/TestTui-KeyBindings-Help
vendored
Normal file
31
client/testdata/TestTui-KeyBindings-Help
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Search Query: > ls
|
||||||
|
|
||||||
|
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Hostname CWD Timestamp Runtime Exit Code Command │
|
||||||
|
│────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||||
|
│ localhost /tmp/ Oct 17 2022 21:43:21 PDT 3s 2 echo 'aaaaaa bbbb' │
|
||||||
|
│ localhost /tmp/ Oct 17 2022 21:43:16 PDT 3s 2 ls ~/ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
└────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
hiSHtory: Search your shell history
|
||||||
|
↑ scroll up ? scroll down pgup page up pgdn page down
|
||||||
|
← move left → move right shift+← scroll the table left shift+→ scroll the table right
|
||||||
|
enter select an entry ctrl+k delete the highlighted entry esc exit hiSHtory ctrl+j help
|
||||||
|
ctrl+x select an entry and cd into that directory
|
326
client/tui/keybindings/keybindings.go
Normal file
326
client/tui/keybindings/keybindings.go
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
package keybindings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/key"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SerializableKeyMap struct {
|
||||||
|
Up []string
|
||||||
|
Down []string
|
||||||
|
PageUp []string
|
||||||
|
PageDown []string
|
||||||
|
SelectEntry []string
|
||||||
|
SelectEntryAndChangeDir []string
|
||||||
|
Left []string
|
||||||
|
Right []string
|
||||||
|
TableLeft []string
|
||||||
|
TableRight []string
|
||||||
|
DeleteEntry []string
|
||||||
|
Help []string
|
||||||
|
Quit []string
|
||||||
|
JumpStartOfInput []string
|
||||||
|
JumpEndOfInput []string
|
||||||
|
WordLeft []string
|
||||||
|
WordRight []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func prettifyKeyBinding(kb string) string {
|
||||||
|
if kb == "up" {
|
||||||
|
return "↑ "
|
||||||
|
}
|
||||||
|
if kb == "down" {
|
||||||
|
return "↓ "
|
||||||
|
}
|
||||||
|
if kb == "left" {
|
||||||
|
return "←"
|
||||||
|
}
|
||||||
|
if kb == "right" {
|
||||||
|
return "→"
|
||||||
|
}
|
||||||
|
subs := [][]string{
|
||||||
|
{"+left", "+← "},
|
||||||
|
{"+right", "+→ "},
|
||||||
|
{"+down", "+↓ "},
|
||||||
|
{"+up", "+↑ "},
|
||||||
|
{"pgdown", "pgdn"},
|
||||||
|
}
|
||||||
|
for _, sub := range subs {
|
||||||
|
kb = strings.ReplaceAll(kb, sub[0], sub[1])
|
||||||
|
}
|
||||||
|
return kb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SerializableKeyMap) ToKeyMap() KeyMap {
|
||||||
|
if len(s.Up) == 0 {
|
||||||
|
panic(fmt.Sprintf("%#v", s))
|
||||||
|
}
|
||||||
|
return KeyMap{
|
||||||
|
Up: key.NewBinding(
|
||||||
|
key.WithKeys(s.Up...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Up[0]), "scroll up "),
|
||||||
|
),
|
||||||
|
Down: key.NewBinding(
|
||||||
|
key.WithKeys(s.Down...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Down[0]), "scroll down "),
|
||||||
|
),
|
||||||
|
PageUp: key.NewBinding(
|
||||||
|
key.WithKeys(s.PageUp...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.PageUp[0]), "page up "),
|
||||||
|
),
|
||||||
|
PageDown: key.NewBinding(
|
||||||
|
key.WithKeys(s.PageDown...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.PageDown[0]), "page down "),
|
||||||
|
),
|
||||||
|
SelectEntry: key.NewBinding(
|
||||||
|
key.WithKeys(s.SelectEntry...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.SelectEntry[0]), "select an entry "),
|
||||||
|
),
|
||||||
|
SelectEntryAndChangeDir: key.NewBinding(
|
||||||
|
key.WithKeys(s.SelectEntryAndChangeDir...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.SelectEntryAndChangeDir[0]), "select an entry and cd into that directory"),
|
||||||
|
),
|
||||||
|
Left: key.NewBinding(
|
||||||
|
key.WithKeys(s.Left...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Left[0]), "move left "),
|
||||||
|
),
|
||||||
|
Right: key.NewBinding(
|
||||||
|
key.WithKeys(s.Right...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Right[0]), "move right "),
|
||||||
|
),
|
||||||
|
TableLeft: key.NewBinding(
|
||||||
|
key.WithKeys(s.TableLeft...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.TableLeft[0]), "scroll the table left "),
|
||||||
|
),
|
||||||
|
TableRight: key.NewBinding(
|
||||||
|
key.WithKeys(s.TableRight...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.TableRight[0]), "scroll the table right "),
|
||||||
|
),
|
||||||
|
DeleteEntry: key.NewBinding(
|
||||||
|
key.WithKeys(s.DeleteEntry...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.DeleteEntry[0]), "delete the highlighted entry "),
|
||||||
|
),
|
||||||
|
Help: key.NewBinding(
|
||||||
|
key.WithKeys(s.Help...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Help[0]), "help "),
|
||||||
|
),
|
||||||
|
Quit: key.NewBinding(
|
||||||
|
key.WithKeys(s.Quit...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.Quit[0]), "exit hiSHtory "),
|
||||||
|
),
|
||||||
|
JumpStartOfInput: key.NewBinding(
|
||||||
|
key.WithKeys(s.JumpStartOfInput...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.JumpStartOfInput[0]), "jump to the start of the input "),
|
||||||
|
),
|
||||||
|
JumpEndOfInput: key.NewBinding(
|
||||||
|
key.WithKeys(s.JumpEndOfInput...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.JumpEndOfInput[0]), "jump to the end of the input "),
|
||||||
|
),
|
||||||
|
WordLeft: key.NewBinding(
|
||||||
|
key.WithKeys(s.WordLeft...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.WordLeft[0]), "jump left one word "),
|
||||||
|
),
|
||||||
|
WordRight: key.NewBinding(
|
||||||
|
key.WithKeys(s.WordRight...),
|
||||||
|
key.WithHelp(prettifyKeyBinding(s.WordRight[0]), "jump right one word "),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SerializableKeyMap) WithDefaults() SerializableKeyMap {
|
||||||
|
if len(s.Up) == 0 {
|
||||||
|
s.Up = DefaultKeyMap.Up.Keys()
|
||||||
|
}
|
||||||
|
if len(s.Down) == 0 {
|
||||||
|
s.Down = DefaultKeyMap.Down.Keys()
|
||||||
|
}
|
||||||
|
if len(s.PageUp) == 0 {
|
||||||
|
s.PageUp = DefaultKeyMap.PageUp.Keys()
|
||||||
|
}
|
||||||
|
if len(s.PageDown) == 0 {
|
||||||
|
s.PageDown = DefaultKeyMap.PageDown.Keys()
|
||||||
|
}
|
||||||
|
if len(s.SelectEntry) == 0 {
|
||||||
|
s.SelectEntry = DefaultKeyMap.SelectEntry.Keys()
|
||||||
|
}
|
||||||
|
if len(s.SelectEntryAndChangeDir) == 0 {
|
||||||
|
s.SelectEntryAndChangeDir = DefaultKeyMap.SelectEntryAndChangeDir.Keys()
|
||||||
|
}
|
||||||
|
if len(s.Left) == 0 {
|
||||||
|
s.Left = DefaultKeyMap.Left.Keys()
|
||||||
|
}
|
||||||
|
if len(s.Right) == 0 {
|
||||||
|
s.Right = DefaultKeyMap.Right.Keys()
|
||||||
|
}
|
||||||
|
if len(s.TableLeft) == 0 {
|
||||||
|
s.TableLeft = DefaultKeyMap.TableLeft.Keys()
|
||||||
|
}
|
||||||
|
if len(s.TableRight) == 0 {
|
||||||
|
s.TableRight = DefaultKeyMap.TableRight.Keys()
|
||||||
|
}
|
||||||
|
if len(s.DeleteEntry) == 0 {
|
||||||
|
s.DeleteEntry = DefaultKeyMap.DeleteEntry.Keys()
|
||||||
|
}
|
||||||
|
if len(s.Help) == 0 {
|
||||||
|
s.Help = DefaultKeyMap.Help.Keys()
|
||||||
|
}
|
||||||
|
if len(s.Quit) == 0 {
|
||||||
|
s.Quit = DefaultKeyMap.Quit.Keys()
|
||||||
|
}
|
||||||
|
if len(s.JumpStartOfInput) == 0 {
|
||||||
|
s.JumpStartOfInput = DefaultKeyMap.JumpStartOfInput.Keys()
|
||||||
|
}
|
||||||
|
if len(s.JumpEndOfInput) == 0 {
|
||||||
|
s.JumpEndOfInput = DefaultKeyMap.JumpEndOfInput.Keys()
|
||||||
|
}
|
||||||
|
if len(s.WordLeft) == 0 {
|
||||||
|
s.WordLeft = DefaultKeyMap.WordLeft.Keys()
|
||||||
|
}
|
||||||
|
if len(s.WordRight) == 0 {
|
||||||
|
s.WordRight = DefaultKeyMap.WordRight.Keys()
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyMap struct {
|
||||||
|
Up key.Binding
|
||||||
|
Down key.Binding
|
||||||
|
PageUp key.Binding
|
||||||
|
PageDown key.Binding
|
||||||
|
SelectEntry key.Binding
|
||||||
|
SelectEntryAndChangeDir key.Binding
|
||||||
|
Left key.Binding
|
||||||
|
Right key.Binding
|
||||||
|
TableLeft key.Binding
|
||||||
|
TableRight key.Binding
|
||||||
|
DeleteEntry key.Binding
|
||||||
|
Help key.Binding
|
||||||
|
Quit key.Binding
|
||||||
|
JumpStartOfInput key.Binding
|
||||||
|
JumpEndOfInput key.Binding
|
||||||
|
WordLeft key.Binding
|
||||||
|
WordRight key.Binding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k KeyMap) ToSerializable() SerializableKeyMap {
|
||||||
|
return SerializableKeyMap{
|
||||||
|
Up: k.Up.Keys(),
|
||||||
|
Down: k.Down.Keys(),
|
||||||
|
PageUp: k.PageUp.Keys(),
|
||||||
|
PageDown: k.PageDown.Keys(),
|
||||||
|
SelectEntry: k.SelectEntry.Keys(),
|
||||||
|
SelectEntryAndChangeDir: k.SelectEntryAndChangeDir.Keys(),
|
||||||
|
Left: k.Left.Keys(),
|
||||||
|
Right: k.Right.Keys(),
|
||||||
|
TableLeft: k.TableLeft.Keys(),
|
||||||
|
TableRight: k.TableRight.Keys(),
|
||||||
|
DeleteEntry: k.DeleteEntry.Keys(),
|
||||||
|
Help: k.Help.Keys(),
|
||||||
|
Quit: k.Quit.Keys(),
|
||||||
|
JumpStartOfInput: k.JumpStartOfInput.Keys(),
|
||||||
|
JumpEndOfInput: k.JumpEndOfInput.Keys(),
|
||||||
|
WordLeft: k.WordLeft.Keys(),
|
||||||
|
WordRight: k.WordRight.Keys(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fakeTitleKeyBinding key.Binding = key.NewBinding(
|
||||||
|
key.WithKeys(""),
|
||||||
|
key.WithHelp("hiSHtory: Search your shell history", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
var fakeEmptyKeyBinding key.Binding = key.NewBinding(
|
||||||
|
key.WithKeys(""),
|
||||||
|
key.WithHelp("", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
func (k KeyMap) ShortHelp() []key.Binding {
|
||||||
|
return []key.Binding{fakeTitleKeyBinding, k.Help}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k KeyMap) FullHelp() [][]key.Binding {
|
||||||
|
return [][]key.Binding{
|
||||||
|
{fakeTitleKeyBinding, k.Up, k.Left, k.SelectEntry, k.SelectEntryAndChangeDir},
|
||||||
|
{fakeEmptyKeyBinding, k.Down, k.Right, k.DeleteEntry},
|
||||||
|
{fakeEmptyKeyBinding, k.PageUp, k.TableLeft, k.Quit},
|
||||||
|
{fakeEmptyKeyBinding, k.PageDown, k.TableRight, k.Help},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Binding struct {
|
||||||
|
Keys []string `json:"keys"`
|
||||||
|
Help key.Help `json:"help"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultKeyMap = KeyMap{
|
||||||
|
Up: key.NewBinding(
|
||||||
|
key.WithKeys("up", "alt+OA", "ctrl+p"),
|
||||||
|
key.WithHelp("↑ ", "scroll up "),
|
||||||
|
),
|
||||||
|
Down: key.NewBinding(
|
||||||
|
key.WithKeys("down", "alt+OB", "ctrl+n"),
|
||||||
|
key.WithHelp("↓ ", "scroll down "),
|
||||||
|
),
|
||||||
|
PageUp: key.NewBinding(
|
||||||
|
key.WithKeys("pgup"),
|
||||||
|
key.WithHelp("pgup", "page up "),
|
||||||
|
),
|
||||||
|
PageDown: key.NewBinding(
|
||||||
|
key.WithKeys("pgdown"),
|
||||||
|
key.WithHelp("pgdn", "page down "),
|
||||||
|
),
|
||||||
|
SelectEntry: key.NewBinding(
|
||||||
|
key.WithKeys("enter"),
|
||||||
|
key.WithHelp("enter", "select an entry "),
|
||||||
|
),
|
||||||
|
SelectEntryAndChangeDir: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+x"),
|
||||||
|
key.WithHelp("ctrl+x", "select an entry and cd into that directory"),
|
||||||
|
),
|
||||||
|
Left: key.NewBinding(
|
||||||
|
key.WithKeys("left"),
|
||||||
|
key.WithHelp("← ", "move left "),
|
||||||
|
),
|
||||||
|
Right: key.NewBinding(
|
||||||
|
key.WithKeys("right"),
|
||||||
|
key.WithHelp("→ ", "move right "),
|
||||||
|
),
|
||||||
|
TableLeft: key.NewBinding(
|
||||||
|
key.WithKeys("shift+left"),
|
||||||
|
key.WithHelp("shift+← ", "scroll the table left "),
|
||||||
|
),
|
||||||
|
TableRight: key.NewBinding(
|
||||||
|
key.WithKeys("shift+right"),
|
||||||
|
key.WithHelp("shift+→ ", "scroll the table right "),
|
||||||
|
),
|
||||||
|
DeleteEntry: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+k"),
|
||||||
|
key.WithHelp("ctrl+k", "delete the highlighted entry "),
|
||||||
|
),
|
||||||
|
Help: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+h"),
|
||||||
|
key.WithHelp("ctrl+h", "help "),
|
||||||
|
),
|
||||||
|
Quit: key.NewBinding(
|
||||||
|
key.WithKeys("esc", "ctrl+c", "ctrl+d"),
|
||||||
|
key.WithHelp("esc", "exit hiSHtory "),
|
||||||
|
),
|
||||||
|
JumpStartOfInput: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+a"),
|
||||||
|
key.WithHelp("ctrl+a", "jump to the start of the input "),
|
||||||
|
),
|
||||||
|
JumpEndOfInput: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+e"),
|
||||||
|
key.WithHelp("ctrl+e", "jump to the end of the input "),
|
||||||
|
),
|
||||||
|
WordLeft: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+left"),
|
||||||
|
key.WithHelp("ctrl+left", "jump left one word "),
|
||||||
|
),
|
||||||
|
WordRight: key.NewBinding(
|
||||||
|
key.WithKeys("ctrl+right"),
|
||||||
|
key.WithHelp("ctrl+right", "jump right one word "),
|
||||||
|
),
|
||||||
|
}
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/ddworken/hishtory/client/hctx"
|
"github.com/ddworken/hishtory/client/hctx"
|
||||||
"github.com/ddworken/hishtory/client/lib"
|
"github.com/ddworken/hishtory/client/lib"
|
||||||
"github.com/ddworken/hishtory/client/table"
|
"github.com/ddworken/hishtory/client/table"
|
||||||
|
"github.com/ddworken/hishtory/client/tui/keybindings"
|
||||||
"github.com/ddworken/hishtory/shared"
|
"github.com/ddworken/hishtory/shared"
|
||||||
"github.com/muesli/termenv"
|
"github.com/muesli/termenv"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
@ -42,120 +43,6 @@ var LAST_DISPATCHED_QUERY_ID = 0
|
|||||||
var LAST_DISPATCHED_QUERY_TIMESTAMP time.Time
|
var LAST_DISPATCHED_QUERY_TIMESTAMP time.Time
|
||||||
var LAST_PROCESSED_QUERY_ID = -1
|
var LAST_PROCESSED_QUERY_ID = -1
|
||||||
|
|
||||||
type keyMap struct {
|
|
||||||
Up key.Binding
|
|
||||||
Down key.Binding
|
|
||||||
PageUp key.Binding
|
|
||||||
PageDown key.Binding
|
|
||||||
SelectEntry key.Binding
|
|
||||||
SelectEntryAndChangeDir key.Binding
|
|
||||||
Left key.Binding
|
|
||||||
Right key.Binding
|
|
||||||
TableLeft key.Binding
|
|
||||||
TableRight key.Binding
|
|
||||||
DeleteEntry key.Binding
|
|
||||||
Help key.Binding
|
|
||||||
Quit key.Binding
|
|
||||||
JumpStartOfInput key.Binding
|
|
||||||
JumpEndOfInput key.Binding
|
|
||||||
JumpWordLeft key.Binding
|
|
||||||
JumpWordRight key.Binding
|
|
||||||
}
|
|
||||||
|
|
||||||
var fakeTitleKeyBinding key.Binding = key.NewBinding(
|
|
||||||
key.WithKeys(""),
|
|
||||||
key.WithHelp("hiSHtory: Search your shell history", ""),
|
|
||||||
)
|
|
||||||
|
|
||||||
var fakeEmptyKeyBinding key.Binding = key.NewBinding(
|
|
||||||
key.WithKeys(""),
|
|
||||||
key.WithHelp("", ""),
|
|
||||||
)
|
|
||||||
|
|
||||||
func (k keyMap) ShortHelp() []key.Binding {
|
|
||||||
return []key.Binding{fakeTitleKeyBinding, k.Help}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k keyMap) FullHelp() [][]key.Binding {
|
|
||||||
return [][]key.Binding{
|
|
||||||
{fakeTitleKeyBinding, k.Up, k.Left, k.SelectEntry, k.SelectEntryAndChangeDir},
|
|
||||||
{fakeEmptyKeyBinding, k.Down, k.Right, k.DeleteEntry},
|
|
||||||
{fakeEmptyKeyBinding, k.PageUp, k.TableLeft, k.Quit},
|
|
||||||
{fakeEmptyKeyBinding, k.PageDown, k.TableRight, k.Help},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = keyMap{
|
|
||||||
Up: key.NewBinding(
|
|
||||||
key.WithKeys("up", "alt+OA", "ctrl+p"),
|
|
||||||
key.WithHelp("↑ ", "scroll up "),
|
|
||||||
),
|
|
||||||
Down: key.NewBinding(
|
|
||||||
key.WithKeys("down", "alt+OB", "ctrl+n"),
|
|
||||||
key.WithHelp("↓ ", "scroll down "),
|
|
||||||
),
|
|
||||||
PageUp: key.NewBinding(
|
|
||||||
key.WithKeys("pgup"),
|
|
||||||
key.WithHelp("pgup", "page up "),
|
|
||||||
),
|
|
||||||
PageDown: key.NewBinding(
|
|
||||||
key.WithKeys("pgdown"),
|
|
||||||
key.WithHelp("pgdn", "page down "),
|
|
||||||
),
|
|
||||||
SelectEntry: key.NewBinding(
|
|
||||||
key.WithKeys("enter"),
|
|
||||||
key.WithHelp("enter", "select an entry "),
|
|
||||||
),
|
|
||||||
SelectEntryAndChangeDir: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+x"),
|
|
||||||
key.WithHelp("ctrl+x", "select an entry and cd into that directory"),
|
|
||||||
),
|
|
||||||
Left: key.NewBinding(
|
|
||||||
key.WithKeys("left"),
|
|
||||||
key.WithHelp("← ", "move left "),
|
|
||||||
),
|
|
||||||
Right: key.NewBinding(
|
|
||||||
key.WithKeys("right"),
|
|
||||||
key.WithHelp("→ ", "move right "),
|
|
||||||
),
|
|
||||||
TableLeft: key.NewBinding(
|
|
||||||
key.WithKeys("shift+left"),
|
|
||||||
key.WithHelp("shift+← ", "scroll the table left "),
|
|
||||||
),
|
|
||||||
TableRight: key.NewBinding(
|
|
||||||
key.WithKeys("shift+right"),
|
|
||||||
key.WithHelp("shift+→ ", "scroll the table right "),
|
|
||||||
),
|
|
||||||
DeleteEntry: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+k"),
|
|
||||||
key.WithHelp("ctrl+k", "delete the highlighted entry "),
|
|
||||||
),
|
|
||||||
Help: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+h"),
|
|
||||||
key.WithHelp("ctrl+h", "help "),
|
|
||||||
),
|
|
||||||
Quit: key.NewBinding(
|
|
||||||
key.WithKeys("esc", "ctrl+c", "ctrl+d"),
|
|
||||||
key.WithHelp("esc", "exit hiSHtory "),
|
|
||||||
),
|
|
||||||
JumpStartOfInput: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+a"),
|
|
||||||
key.WithHelp("ctrl+a", "jump to the start of the input "),
|
|
||||||
),
|
|
||||||
JumpEndOfInput: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+e"),
|
|
||||||
key.WithHelp("ctrl+e", "jump to the end of the input "),
|
|
||||||
),
|
|
||||||
JumpWordLeft: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+left"),
|
|
||||||
key.WithHelp("ctrl+left", "jump left one word "),
|
|
||||||
),
|
|
||||||
JumpWordRight: key.NewBinding(
|
|
||||||
key.WithKeys("ctrl+right"),
|
|
||||||
key.WithHelp("ctrl+right", "jump right one word "),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelectStatus int64
|
type SelectStatus int64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -164,6 +51,8 @@ const (
|
|||||||
SelectedWithChangeDir
|
SelectedWithChangeDir
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var loadedKeyBindings keybindings.KeyMap = keybindings.DefaultKeyMap
|
||||||
|
|
||||||
type model struct {
|
type model struct {
|
||||||
// context
|
// context
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -330,20 +219,20 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch {
|
switch {
|
||||||
case key.Matches(msg, keys.Quit):
|
case key.Matches(msg, loadedKeyBindings.Quit):
|
||||||
m.quitting = true
|
m.quitting = true
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
case key.Matches(msg, keys.SelectEntry):
|
case key.Matches(msg, loadedKeyBindings.SelectEntry):
|
||||||
if len(m.tableEntries) != 0 && m.table != nil {
|
if len(m.tableEntries) != 0 && m.table != nil {
|
||||||
m.selected = Selected
|
m.selected = Selected
|
||||||
}
|
}
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
case key.Matches(msg, keys.SelectEntryAndChangeDir):
|
case key.Matches(msg, loadedKeyBindings.SelectEntryAndChangeDir):
|
||||||
if len(m.tableEntries) != 0 && m.table != nil {
|
if len(m.tableEntries) != 0 && m.table != nil {
|
||||||
m.selected = SelectedWithChangeDir
|
m.selected = SelectedWithChangeDir
|
||||||
}
|
}
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
case key.Matches(msg, keys.DeleteEntry):
|
case key.Matches(msg, loadedKeyBindings.DeleteEntry):
|
||||||
if m.table == nil {
|
if m.table == nil {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@ -355,16 +244,16 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
cmd := runQueryAndUpdateTable(m, true, true)
|
cmd := runQueryAndUpdateTable(m, true, true)
|
||||||
preventTableOverscrolling(m)
|
preventTableOverscrolling(m)
|
||||||
return m, cmd
|
return m, cmd
|
||||||
case key.Matches(msg, keys.Help):
|
case key.Matches(msg, loadedKeyBindings.Help):
|
||||||
m.help.ShowAll = !m.help.ShowAll
|
m.help.ShowAll = !m.help.ShowAll
|
||||||
return m, nil
|
return m, nil
|
||||||
case key.Matches(msg, keys.JumpStartOfInput):
|
case key.Matches(msg, loadedKeyBindings.JumpStartOfInput):
|
||||||
m.queryInput.SetCursor(0)
|
m.queryInput.SetCursor(0)
|
||||||
return m, nil
|
return m, nil
|
||||||
case key.Matches(msg, keys.JumpEndOfInput):
|
case key.Matches(msg, loadedKeyBindings.JumpEndOfInput):
|
||||||
m.queryInput.SetCursor(len(m.queryInput.Value()))
|
m.queryInput.SetCursor(len(m.queryInput.Value()))
|
||||||
return m, nil
|
return m, nil
|
||||||
case key.Matches(msg, keys.JumpWordLeft):
|
case key.Matches(msg, loadedKeyBindings.WordLeft):
|
||||||
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
|
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
|
||||||
lastBoundary := 0
|
lastBoundary := 0
|
||||||
for _, boundary := range wordBoundaries {
|
for _, boundary := range wordBoundaries {
|
||||||
@ -375,7 +264,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
lastBoundary = boundary
|
lastBoundary = boundary
|
||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
case key.Matches(msg, keys.JumpWordRight):
|
case key.Matches(msg, loadedKeyBindings.WordRight):
|
||||||
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
|
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
|
||||||
for _, boundary := range wordBoundaries {
|
for _, boundary := range wordBoundaries {
|
||||||
if boundary > m.queryInput.Position() {
|
if boundary > m.queryInput.Position() {
|
||||||
@ -509,7 +398,7 @@ func (m model) View() string {
|
|||||||
if isExtraCompactHeightMode() {
|
if isExtraCompactHeightMode() {
|
||||||
additionalMessagesStr = "\n"
|
additionalMessagesStr = "\n"
|
||||||
}
|
}
|
||||||
helpView := m.help.View(keys)
|
helpView := m.help.View(loadedKeyBindings)
|
||||||
if isExtraCompactHeightMode() {
|
if isExtraCompactHeightMode() {
|
||||||
helpView = ""
|
helpView = ""
|
||||||
}
|
}
|
||||||
@ -751,10 +640,10 @@ func makeTable(ctx context.Context, shellName string, rows []table.Row) (table.M
|
|||||||
return table.Model{}, err
|
return table.Model{}, err
|
||||||
}
|
}
|
||||||
km := table.KeyMap{
|
km := table.KeyMap{
|
||||||
LineUp: keys.Up,
|
LineUp: loadedKeyBindings.Up,
|
||||||
LineDown: keys.Down,
|
LineDown: loadedKeyBindings.Down,
|
||||||
PageUp: keys.PageUp,
|
PageUp: loadedKeyBindings.PageUp,
|
||||||
PageDown: keys.PageDown,
|
PageDown: loadedKeyBindings.PageDown,
|
||||||
GotoTop: key.NewBinding(
|
GotoTop: key.NewBinding(
|
||||||
key.WithKeys("home"),
|
key.WithKeys("home"),
|
||||||
key.WithHelp("home", "go to start"),
|
key.WithHelp("home", "go to start"),
|
||||||
@ -763,8 +652,8 @@ func makeTable(ctx context.Context, shellName string, rows []table.Row) (table.M
|
|||||||
key.WithKeys("end"),
|
key.WithKeys("end"),
|
||||||
key.WithHelp("end", "go to end"),
|
key.WithHelp("end", "go to end"),
|
||||||
),
|
),
|
||||||
MoveLeft: keys.TableLeft,
|
MoveLeft: loadedKeyBindings.TableLeft,
|
||||||
MoveRight: keys.TableRight,
|
MoveRight: loadedKeyBindings.TableRight,
|
||||||
}
|
}
|
||||||
_, terminalHeight, err := getTerminalSize()
|
_, terminalHeight, err := getTerminalSize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -954,6 +843,7 @@ func configureColorProfile(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TuiQuery(ctx context.Context, shellName, initialQuery string) error {
|
func TuiQuery(ctx context.Context, shellName, initialQuery string) error {
|
||||||
|
loadedKeyBindings = hctx.GetConf(ctx).KeyBindings.ToKeyMap()
|
||||||
configureColorProfile(ctx)
|
configureColorProfile(ctx)
|
||||||
p := tea.NewProgram(initialModel(ctx, shellName, initialQuery), tea.WithOutput(os.Stderr))
|
p := tea.NewProgram(initialModel(ctx, shellName, initialQuery), tea.WithOutput(os.Stderr))
|
||||||
// Async: Get the initial set of rows
|
// Async: Get the initial set of rows
|
||||||
|
Loading…
Reference in New Issue
Block a user