mirror of
https://github.com/eeeXun/GTT.git
synced 2025-05-16 07:40:44 -07:00
feat: support Alt prefix
This commit is contained in:
parent
f425ec196d
commit
9ee23aedea
28
README.md
28
README.md
@ -161,14 +161,30 @@ Switch pop out window.
|
||||
|
||||
### Customize key map
|
||||
|
||||
You can overwrite the following key
|
||||
|
||||
- `translate`: Translate from source to destination window.
|
||||
- `swap_language`: Swap language.
|
||||
- `clear`: Clear all text in source of translation window.
|
||||
- `copy_selected`: Copy selected text.
|
||||
- `copy_source`: Copy all text in source of translation window.
|
||||
- `copy_destination`: Copy all text in destination of translation window.
|
||||
- `tts_source`: Play text to speech on source of translation window.
|
||||
- `tts_destination`: Play text to speech on destination of translation window.
|
||||
- `stop_tts`: Stop playing text to speech.
|
||||
- `toggle_transparent`: Toggle transparent.
|
||||
- `toggle_below`: Toggle Definition/Example & Part of speech.
|
||||
|
||||
For key to combine with `Ctrl`, the value can be `"C-space"`, `"C-\\"`, `"C-]"`, `"C-^"`, `"C-_"` or `"C-a"` to `"C-z"`.
|
||||
|
||||
⚠️ Note, don't use `"C-c"`, `<C-c>` is for exit program.
|
||||
|
||||
For key to combine with `Alt`, the value can be `"A-space"` or `"A-"` + the character you want.
|
||||
|
||||
Or you can use function key, the value can be `"F1"` to `"F64"`.
|
||||
|
||||
See the example in [keymap.yaml](example/keymap.yaml) file. This file should located at `$XDG_CONFIG_HOME/gtt/keymap.yaml` or `$HOME/.config/gtt/keymap.yaml`.
|
||||
|
||||
For key to combine with `Ctrl`, value can be `" "` (Space), `"\\"` or `'\'` (backslash), `"]"`, `"^"`, `"_"`, `"a"` to `"z"` (lower case).
|
||||
|
||||
Or the function key, value can be `"F1"` to `"F64"`.
|
||||
|
||||
⚠️ Note, don't use `"c"`, `<C-c>` is for exit program.
|
||||
|
||||
## Credit
|
||||
|
||||
[soimort/translate-shell](https://github.com/soimort/translate-shell),
|
||||
|
29
config.go
29
config.go
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/eeeXun/gtt/internal/style"
|
||||
"github.com/eeeXun/gtt/internal/translate"
|
||||
"github.com/eeeXun/gtt/internal/ui"
|
||||
config "github.com/spf13/viper"
|
||||
)
|
||||
|
||||
@ -17,17 +16,17 @@ func configInit() {
|
||||
themeConfig = config.New()
|
||||
keyMapConfig = config.New()
|
||||
defaultKeyMaps = map[string]string{
|
||||
"translate": "j",
|
||||
"swap_language": "s",
|
||||
"clear": "q",
|
||||
"copy_selected": "y",
|
||||
"copy_source": "g",
|
||||
"copy_destination": "r",
|
||||
"tts_source": "o",
|
||||
"tts_destination": "p",
|
||||
"stop_tts": "x",
|
||||
"toggle_transparent": "t",
|
||||
"toggle_below": "\\",
|
||||
"translate": "C-j",
|
||||
"swap_language": "C-s",
|
||||
"clear": "C-q",
|
||||
"copy_selected": "C-y",
|
||||
"copy_source": "C-g",
|
||||
"copy_destination": "C-r",
|
||||
"tts_source": "C-o",
|
||||
"tts_destination": "C-p",
|
||||
"stop_tts": "C-x",
|
||||
"toggle_transparent": "C-t",
|
||||
"toggle_below": "C-\\",
|
||||
}
|
||||
defaultConfig = map[string]interface{}{
|
||||
"hide_below": false,
|
||||
@ -123,14 +122,14 @@ func configInit() {
|
||||
if err := keyMapConfig.ReadInConfig(); err == nil {
|
||||
for action, key := range defaultKeyMaps {
|
||||
if keyMapConfig.Get(action) == nil {
|
||||
keyMaps[action] = ui.NewKeyData(key)
|
||||
keyMaps[action] = key
|
||||
} else {
|
||||
keyMaps[action] = ui.NewKeyData(keyMapConfig.GetString(action))
|
||||
keyMaps[action] = keyMapConfig.GetString(action)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for action, key := range defaultKeyMaps {
|
||||
keyMaps[action] = ui.NewKeyData(key)
|
||||
keyMaps[action] = key
|
||||
}
|
||||
}
|
||||
// Setup
|
||||
|
@ -1,27 +1,34 @@
|
||||
# This file should located at $XDG_CONFIG_HOME/gtt/keymap.yaml or $HOME/.config/gtt/keymap.yaml
|
||||
# For key to combine with Ctrl, value can be " " (Space), "\\" or '\' (backslash), "]", "^", "_", "a" to "z" (lower case)
|
||||
# ⚠️ Note, don't use "c", <C-c> is for exit program
|
||||
# Or the function key, value can be "F1" to "F64"
|
||||
# This file should located at $XDG_CONFIG_HOME/gtt/keymap.yaml or $HOME/.config/gtt/keymap.yaml.
|
||||
|
||||
# Translate, <C-j>
|
||||
translate: "j"
|
||||
# For key to combine with Ctrl, the value can be "C-space", "C-\\", "C-]", "C-^", "C-_" or "C-a" to "C-z".
|
||||
# ⚠️ Note, don't use "C-c", <C-c> is for exit program.
|
||||
|
||||
# For key to combine with Alt, the value can be "A-space" or "A-" + the character you want.
|
||||
|
||||
# Or you can use function key, the value can be "F1" to "F64".
|
||||
|
||||
|
||||
# The following is the default key map
|
||||
|
||||
# Translate from source to destination window, <C-j>
|
||||
translate: "C-j"
|
||||
# Swap language, <C-s>
|
||||
swap_language: "s"
|
||||
swap_language: "C-s"
|
||||
# Clear all text in source of translation window, <C-q>
|
||||
clear: "q"
|
||||
clear: "C-q"
|
||||
# Copy selected text, <C-y>
|
||||
copy_selected: "y"
|
||||
copy_selected: "C-y"
|
||||
# Copy all text in source of translation window, <C-g>
|
||||
copy_source: "g"
|
||||
copy_source: "C-g"
|
||||
# Copy all text in destination of translation window, <C-r>
|
||||
copy_destination: "r"
|
||||
copy_destination: "C-r"
|
||||
# Play text to speech on source of translation window, <C-o>
|
||||
tts_source: "o"
|
||||
tts_source: "C-o"
|
||||
# Play text to speech on destination of translation window, <C-p>
|
||||
tts_destination: "p"
|
||||
tts_destination: "C-p"
|
||||
# Stop playing text to speech, <C-x>
|
||||
stop_tts: "x"
|
||||
stop_tts: "C-x"
|
||||
# Toggle transparent, <C-t>
|
||||
toggle_transparent: "t"
|
||||
toggle_transparent: "C-t"
|
||||
# Toggle Definition/Example & Part of speech, <C-\>
|
||||
toggle_below: "\\"
|
||||
toggle_below: "C-\\"
|
||||
|
@ -1,6 +1,6 @@
|
||||
# This file should located at $XDG_CONFIG_HOME/gtt/theme.yaml or $HOME/.config/gtt/theme.yaml
|
||||
# You have to provide theme name. e.g. tokyonight
|
||||
# And colors: bg, fg, gray, red, green, yellow, blue, purple, cyan, orange
|
||||
# This file should located at $XDG_CONFIG_HOME/gtt/theme.yaml or $HOME/.config/gtt/theme.yaml.
|
||||
# You have to provide theme name. e.g. tokyonight.
|
||||
# And colors: bg, fg, gray, red, green, yellow, blue, purple, cyan, orange.
|
||||
# bg is for background color
|
||||
# fg is for foreground color
|
||||
# gray is for selected color
|
||||
|
@ -1,66 +0,0 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
type keyData struct {
|
||||
name string
|
||||
key tcell.Key
|
||||
}
|
||||
|
||||
type KeyMaps map[string]keyData
|
||||
|
||||
func NewKeyData(keyStr string) keyData {
|
||||
var (
|
||||
name string
|
||||
key tcell.Key
|
||||
)
|
||||
|
||||
if len(keyStr) > 1 && keyStr[0] == 'F' {
|
||||
// function key, can be F1 to F64
|
||||
name = keyStr
|
||||
fNum, err := strconv.Atoi(keyStr[1:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
key = tcell.KeyF1 + tcell.Key(fNum-1)
|
||||
} else {
|
||||
switch keyStr[0] {
|
||||
case ' ':
|
||||
name = "C-Space"
|
||||
key = tcell.KeyCtrlSpace
|
||||
case '\\':
|
||||
name = "C-\\"
|
||||
key = tcell.KeyCtrlBackslash
|
||||
case ']':
|
||||
name = "C-]"
|
||||
key = tcell.KeyCtrlRightSq
|
||||
case '^':
|
||||
name = "C-^"
|
||||
key = tcell.KeyCtrlCarat
|
||||
case '_':
|
||||
name = "C-_"
|
||||
key = tcell.KeyCtrlUnderscore
|
||||
default:
|
||||
// This should be a to z
|
||||
name = "C-" + keyStr
|
||||
key = tcell.KeyCtrlA + tcell.Key(keyStr[0]-'a')
|
||||
}
|
||||
}
|
||||
|
||||
return keyData{
|
||||
name: name,
|
||||
key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (k keyData) GetName() string {
|
||||
return k.name
|
||||
}
|
||||
|
||||
func (k keyData) GetKey() tcell.Key {
|
||||
return k.key
|
||||
}
|
121
key.go
Normal file
121
key.go
Normal file
@ -0,0 +1,121 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
)
|
||||
|
||||
var keyNames = map[tcell.Key]string{
|
||||
tcell.KeyEsc: "Esc",
|
||||
tcell.KeyF1: "F1",
|
||||
tcell.KeyF2: "F2",
|
||||
tcell.KeyF3: "F3",
|
||||
tcell.KeyF4: "F4",
|
||||
tcell.KeyF5: "F5",
|
||||
tcell.KeyF6: "F6",
|
||||
tcell.KeyF7: "F7",
|
||||
tcell.KeyF8: "F8",
|
||||
tcell.KeyF9: "F9",
|
||||
tcell.KeyF10: "F10",
|
||||
tcell.KeyF11: "F11",
|
||||
tcell.KeyF12: "F12",
|
||||
tcell.KeyF13: "F13",
|
||||
tcell.KeyF14: "F14",
|
||||
tcell.KeyF15: "F15",
|
||||
tcell.KeyF16: "F16",
|
||||
tcell.KeyF17: "F17",
|
||||
tcell.KeyF18: "F18",
|
||||
tcell.KeyF19: "F19",
|
||||
tcell.KeyF20: "F20",
|
||||
tcell.KeyF21: "F21",
|
||||
tcell.KeyF22: "F22",
|
||||
tcell.KeyF23: "F23",
|
||||
tcell.KeyF24: "F24",
|
||||
tcell.KeyF25: "F25",
|
||||
tcell.KeyF26: "F26",
|
||||
tcell.KeyF27: "F27",
|
||||
tcell.KeyF28: "F28",
|
||||
tcell.KeyF29: "F29",
|
||||
tcell.KeyF30: "F30",
|
||||
tcell.KeyF31: "F31",
|
||||
tcell.KeyF32: "F32",
|
||||
tcell.KeyF33: "F33",
|
||||
tcell.KeyF34: "F34",
|
||||
tcell.KeyF35: "F35",
|
||||
tcell.KeyF36: "F36",
|
||||
tcell.KeyF37: "F37",
|
||||
tcell.KeyF38: "F38",
|
||||
tcell.KeyF39: "F39",
|
||||
tcell.KeyF40: "F40",
|
||||
tcell.KeyF41: "F41",
|
||||
tcell.KeyF42: "F42",
|
||||
tcell.KeyF43: "F43",
|
||||
tcell.KeyF44: "F44",
|
||||
tcell.KeyF45: "F45",
|
||||
tcell.KeyF46: "F46",
|
||||
tcell.KeyF47: "F47",
|
||||
tcell.KeyF48: "F48",
|
||||
tcell.KeyF49: "F49",
|
||||
tcell.KeyF50: "F50",
|
||||
tcell.KeyF51: "F51",
|
||||
tcell.KeyF52: "F52",
|
||||
tcell.KeyF53: "F53",
|
||||
tcell.KeyF54: "F54",
|
||||
tcell.KeyF55: "F55",
|
||||
tcell.KeyF56: "F56",
|
||||
tcell.KeyF57: "F57",
|
||||
tcell.KeyF58: "F58",
|
||||
tcell.KeyF59: "F59",
|
||||
tcell.KeyF60: "F60",
|
||||
tcell.KeyF61: "F61",
|
||||
tcell.KeyF62: "F62",
|
||||
tcell.KeyF63: "F63",
|
||||
tcell.KeyF64: "F64",
|
||||
tcell.KeyCtrlA: "C-a",
|
||||
tcell.KeyCtrlB: "C-b",
|
||||
tcell.KeyCtrlC: "C-c",
|
||||
tcell.KeyCtrlD: "C-d",
|
||||
tcell.KeyCtrlE: "C-e",
|
||||
tcell.KeyCtrlF: "C-f",
|
||||
tcell.KeyCtrlG: "C-g",
|
||||
tcell.KeyCtrlJ: "C-j",
|
||||
tcell.KeyCtrlK: "C-k",
|
||||
tcell.KeyCtrlL: "C-l",
|
||||
tcell.KeyCtrlN: "C-n",
|
||||
tcell.KeyCtrlO: "C-o",
|
||||
tcell.KeyCtrlP: "C-p",
|
||||
tcell.KeyCtrlQ: "C-q",
|
||||
tcell.KeyCtrlR: "C-r",
|
||||
tcell.KeyCtrlS: "C-s",
|
||||
tcell.KeyCtrlT: "C-t",
|
||||
tcell.KeyCtrlU: "C-u",
|
||||
tcell.KeyCtrlV: "C-v",
|
||||
tcell.KeyCtrlW: "C-w",
|
||||
tcell.KeyCtrlX: "C-x",
|
||||
tcell.KeyCtrlY: "C-y",
|
||||
tcell.KeyCtrlZ: "C-z",
|
||||
tcell.KeyCtrlSpace: "C-space",
|
||||
tcell.KeyCtrlUnderscore: "C-_",
|
||||
tcell.KeyCtrlRightSq: "C-]",
|
||||
tcell.KeyCtrlBackslash: "C-\\",
|
||||
tcell.KeyCtrlCarat: "C-^",
|
||||
}
|
||||
|
||||
func getKeyName(event *tcell.EventKey) string {
|
||||
var keyName string
|
||||
key := event.Key()
|
||||
|
||||
if key == tcell.KeyRune {
|
||||
if event.Modifiers() == tcell.ModAlt {
|
||||
switch event.Rune() {
|
||||
case ' ':
|
||||
keyName = "A-space"
|
||||
default:
|
||||
keyName = "A-" + string(event.Rune())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keyName = keyNames[key]
|
||||
}
|
||||
|
||||
return keyName
|
||||
}
|
2
main.go
2
main.go
@ -21,7 +21,7 @@ var (
|
||||
// UI style
|
||||
uiStyle = style.NewStyle()
|
||||
// keyMaps
|
||||
keyMaps = make(ui.KeyMaps)
|
||||
keyMaps = make(map[string]string)
|
||||
// UI
|
||||
app = tview.NewApplication()
|
||||
srcInput = tview.NewTextArea()
|
||||
|
81
ui.go
81
ui.go
@ -10,6 +10,13 @@ import (
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
item tview.Primitive
|
||||
fixedSize int
|
||||
proportion int
|
||||
focus bool
|
||||
}
|
||||
|
||||
const (
|
||||
popOutWindowHeight int = 20
|
||||
langStrMaxLength int = 32
|
||||
@ -45,13 +52,6 @@ const (
|
||||
Switch pop out window.`
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
item tview.Primitive
|
||||
fixedSize int
|
||||
proportion int
|
||||
focus bool
|
||||
}
|
||||
|
||||
func updateTranslateWindow() {
|
||||
if uiStyle.HideBelow {
|
||||
translateWindow.RemoveItem(translateBelowWidget)
|
||||
@ -165,17 +165,17 @@ func updateNonConfigColor() {
|
||||
keyMapMenu.SetTextColor(uiStyle.ForegroundColor()).
|
||||
SetText(fmt.Sprintf(keyMapText,
|
||||
fmt.Sprintf("%.6x", uiStyle.HighLightColor().TrueColor().Hex()),
|
||||
keyMaps["translate"].GetName(),
|
||||
keyMaps["swap_language"].GetName(),
|
||||
keyMaps["clear"].GetName(),
|
||||
keyMaps["copy_selected"].GetName(),
|
||||
keyMaps["copy_src"].GetName(),
|
||||
keyMaps["copy_dst"].GetName(),
|
||||
keyMaps["tts_src"].GetName(),
|
||||
keyMaps["tts_dst"].GetName(),
|
||||
keyMaps["stop_tts"].GetName(),
|
||||
keyMaps["toggle_transparent"].GetName(),
|
||||
keyMaps["toggle_below"].GetName(),
|
||||
keyMaps["translate"],
|
||||
keyMaps["swap_language"],
|
||||
keyMaps["clear"],
|
||||
keyMaps["copy_selected"],
|
||||
keyMaps["copy_source"],
|
||||
keyMaps["copy_destination"],
|
||||
keyMaps["tts_source"],
|
||||
keyMaps["tts_destination"],
|
||||
keyMaps["stop_tts"],
|
||||
keyMaps["toggle_transparent"],
|
||||
keyMaps["toggle_below"],
|
||||
)).
|
||||
SetBorderColor(uiStyle.HighLightColor()).
|
||||
SetTitleColor(uiStyle.HighLightColor())
|
||||
@ -373,9 +373,14 @@ func uiInit() {
|
||||
// https://github.com/golang/go/discussions/56010
|
||||
widget := widget
|
||||
widget.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
key := event.Key()
|
||||
switch key {
|
||||
case keyMaps["copy_selected"].GetKey():
|
||||
keyName := getKeyName(event)
|
||||
|
||||
if len(keyName) == 0 {
|
||||
return event
|
||||
}
|
||||
|
||||
switch keyName {
|
||||
case keyMaps["copy_selected"]:
|
||||
// copy selected text
|
||||
text, _, _ := widget.GetSelection()
|
||||
|
||||
@ -437,10 +442,14 @@ func uiInit() {
|
||||
}
|
||||
|
||||
func mainPageHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
key := event.Key()
|
||||
keyName := getKeyName(event)
|
||||
|
||||
switch key {
|
||||
case keyMaps["toggle_transparent"].GetKey():
|
||||
if len(keyName) == 0 {
|
||||
return event
|
||||
}
|
||||
|
||||
switch keyName {
|
||||
case keyMaps["toggle_transparent"]:
|
||||
// Toggle transparent
|
||||
uiStyle.Transparent = !uiStyle.Transparent
|
||||
// The following will trigger transparentDropDown SetDoneFunc
|
||||
@ -448,7 +457,7 @@ func mainPageHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
IndexOf(strconv.FormatBool(uiStyle.Transparent),
|
||||
[]string{"true", "false"}))
|
||||
return nil
|
||||
case keyMaps["toggle_below"].GetKey():
|
||||
case keyMaps["toggle_below"]:
|
||||
// Toggle Hide below window
|
||||
uiStyle.HideBelow = !uiStyle.HideBelow
|
||||
// The following will trigger hideBelowDropDown SetDoneFunc
|
||||
@ -462,14 +471,14 @@ func mainPageHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
|
||||
func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
key := event.Key()
|
||||
keyName := getKeyName(event)
|
||||
|
||||
switch key {
|
||||
case tcell.KeyEsc:
|
||||
switch keyName {
|
||||
case "Esc":
|
||||
mainPage.ShowPage("langPopOut")
|
||||
app.SetFocus(langCycle.GetCurrentUI())
|
||||
return nil
|
||||
case keyMaps["translate"].GetKey():
|
||||
case keyMaps["translate"]:
|
||||
message := srcInput.GetText()
|
||||
// Only translate when message exist
|
||||
if len(message) > 0 {
|
||||
@ -483,10 +492,10 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case keyMaps["clear"].GetKey():
|
||||
case keyMaps["clear"]:
|
||||
srcInput.SetText("", true)
|
||||
return nil
|
||||
case keyMaps["copy_src"].GetKey():
|
||||
case keyMaps["copy_source"]:
|
||||
// copy all text in Input
|
||||
text := srcInput.GetText()
|
||||
|
||||
@ -495,7 +504,7 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
CopyToClipboard(text)
|
||||
}
|
||||
return nil
|
||||
case keyMaps["copy_dst"].GetKey():
|
||||
case keyMaps["copy_destination"]:
|
||||
// copy all text in Output
|
||||
text := dstOutput.GetText(false)
|
||||
|
||||
@ -504,7 +513,7 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
CopyToClipboard(text[:len(text)-1])
|
||||
}
|
||||
return nil
|
||||
case keyMaps["swap_language"].GetKey():
|
||||
case keyMaps["swap_language"]:
|
||||
translator.SwapLang()
|
||||
updateCurrentLang()
|
||||
srcText := srcInput.GetText()
|
||||
@ -517,7 +526,7 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
dstOutput.SetText(srcText)
|
||||
return nil
|
||||
case keyMaps["tts_src"].GetKey():
|
||||
case keyMaps["tts_source"]:
|
||||
// Play text to speech on source of translation window.
|
||||
if translator.LockAvailable() {
|
||||
message := srcInput.GetText()
|
||||
@ -535,7 +544,7 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
|
||||
}
|
||||
return nil
|
||||
case keyMaps["tts_dst"].GetKey():
|
||||
case keyMaps["tts_destination"]:
|
||||
// Play text to speech on destination of translation window.
|
||||
if translator.LockAvailable() {
|
||||
message := dstOutput.GetText(false)
|
||||
@ -552,7 +561,7 @@ func translateWindowHandler(event *tcell.EventKey) *tcell.EventKey {
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case keyMaps["stop_tts"].GetKey():
|
||||
case keyMaps["stop_tts"]:
|
||||
// Stop play sound
|
||||
translator.StopTTS()
|
||||
return nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user