From c87f3fffc6de2e7ded95145f95b3e444f6ee3143 Mon Sep 17 00:00:00 2001 From: Ayyan <119342035+ayn2op@users.noreply.github.com> Date: Fri, 29 Mar 2024 16:15:08 +0530 Subject: [PATCH] Remove vi interface (#376) --- README.md | 37 ++-- cmd/guilds_tree.go | 34 ++-- cmd/main_flex.go | 80 +++------ cmd/message_input.go | 179 ++++++++++---------- cmd/messages_text.go | 346 ++++++++++++++++++++------------------ internal/config/config.go | 4 +- internal/config/keys.go | 95 +++++------ 7 files changed, 362 insertions(+), 413 deletions(-) diff --git a/README.md b/README.md index 5c2801a..8bf2483 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ go build . The configuration file allows you to configure and customize the behavior, keybindings, and theme of the application. -- Unix: `$XDG_CONFIG_HOME/discordo/config.yml` or `$HOME/.config/discordo/config.yml` -- Darwin: `$HOME/Library/Application Support/discordo/config.yml` -- Windows: `%AppData%/discordo/config.yml` +- Unix: `$XDG_CONFIG_HOME/discordo/config.toml` or `$HOME/.config/discordo/config.toml` +- Darwin: `$HOME/Library/Application Support/discordo/config.toml` +- Windows: `%AppData%/discordo/config.toml` ```toml mouse = true @@ -62,24 +62,19 @@ timestamps_before_author = false messages_limit = 50 editor = "default" -[keys.normal] -insert_mode = "Rune[i]" +[keys] focus_guilds_tree = "Ctrl+G" focus_messages_text = "Ctrl+T" toggle_guild_tree = "Ctrl+B" +select_previous = "Rune[k]" +select_next = "Rune[j]" +select_first = "Rune[g]" +select_last = "Rune[G]" -[keys.normal.guilds_tree] +[keys.guilds_tree] select_current = "Enter" -select_previous = "Rune[k]" -select_next = "Rune[j]" -select_first = "Rune[g]" -select_last = "Rune[G]" -[keys.normal.messages_text] -select_previous = "Rune[k]" -select_next = "Rune[j]" -select_first = "Rune[g]" -select_last = "Rune[G]" +[keys.messages_text] select_reply = "Rune[s]" reply = "Rune[r]" reply_mention = "Rune[R]" @@ -87,12 +82,10 @@ delete = "Rune[d]" yank = "Rune[y]" open = "Rune[o]" -[keys.insert] -normal_mode = "Esc" - -[keys.insert.message_input] +[keys.message_input] send = "Enter" editor = "Ctrl+E" +cancel = "Esc" [theme] border = true @@ -104,16 +97,12 @@ background_color = "default" [theme.guilds_tree] auto_expand_folders = true graphics = true - + [theme.messages_text] author_color = "aqua" reply_indicator = "╭ " ``` -## Documentation - -[Here.](./docs) - ## Disclaimer Automated user accounts or "self-bots" are against Discord's Terms of Service. I am not responsible for any loss caused by using "self-bots" or Discordo. diff --git a/cmd/guilds_tree.go b/cmd/guilds_tree.go index 26fc946..544ff11 100644 --- a/cmd/guilds_tree.go +++ b/cmd/guilds_tree.go @@ -108,22 +108,23 @@ func (gt *GuildsTree) channelToString(c discord.Channel) string { return s } -func (gt *GuildsTree) createChannelNode(n *tview.TreeNode, c discord.Channel) { +func (gt *GuildsTree) createChannelNode(n *tview.TreeNode, c discord.Channel) *tview.TreeNode { if c.Type != discord.DirectMessage && c.Type != discord.GroupDM { ps, err := discordState.Permissions(c.ID, discordState.Ready().User.ID) if err != nil { log.Println(err) - return + return nil } if !ps.Has(discord.PermissionViewChannel) { - return + return nil } } cn := tview.NewTreeNode(gt.channelToString(c)) cn.SetReference(c.ID) n.AddChild(cn) + return cn } func (gt *GuildsTree) createChannelNodes(n *tview.TreeNode, cs []discord.Channel) { @@ -219,23 +220,18 @@ func (gt *GuildsTree) onSelected(n *tview.TreeNode) { } func (gt *GuildsTree) onInputCapture(event *tcell.EventKey) *tcell.EventKey { - switch mainFlex.mode { - case ModeNormal: - switch event.Name() { - case cfg.Keys.Normal.GuildsTree.SelectCurrent: - return tcell.NewEventKey(tcell.KeyEnter, 0, tcell.ModNone) - case cfg.Keys.Normal.GuildsTree.SelectPrevious: - return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone) - case cfg.Keys.Normal.GuildsTree.SelectNext: - return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone) - case cfg.Keys.Normal.GuildsTree.SelectFirst: - return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone) - case cfg.Keys.Normal.GuildsTree.SelectLast: - return tcell.NewEventKey(tcell.KeyEnd, 0, tcell.ModNone) - } + switch event.Name() { + case cfg.Keys.SelectPrevious: + return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone) + case cfg.Keys.SelectNext: + return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone) + case cfg.Keys.SelectFirst: + return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone) + case cfg.Keys.SelectLast: + return tcell.NewEventKey(tcell.KeyEnd, 0, tcell.ModNone) - // do not propagate event to the children in normal mode. - return nil + case cfg.Keys.GuildsTree.SelectCurrent: + return tcell.NewEventKey(tcell.KeyEnter, 0, tcell.ModNone) } return event diff --git a/cmd/main_flex.go b/cmd/main_flex.go index 4af4b66..ce6b6fc 100644 --- a/cmd/main_flex.go +++ b/cmd/main_flex.go @@ -5,17 +5,9 @@ import ( "github.com/rivo/tview" ) -type Mode uint - -const ( - ModeNormal Mode = iota - ModeInsert -) - type MainFlex struct { *tview.Flex - mode Mode guildsTree *GuildsTree messagesText *MessagesText messageInput *MessageInput @@ -25,23 +17,11 @@ func newMainFlex() *MainFlex { mf := &MainFlex{ Flex: tview.NewFlex(), - mode: ModeNormal, guildsTree: newGuildsTree(), messagesText: newMessagesText(), messageInput: newMessageInput(), } - app.SetBeforeDrawFunc(func(screen tcell.Screen) bool { - switch mf.mode { - case ModeNormal: - mf.messageInput.SetBorderAttributes(tcell.AttrNone) - case ModeInsert: - mf.messageInput.SetBorderAttributes(tcell.AttrDim) - } - - return false - }) - mf.init() mf.SetInputCapture(mf.onInputCapture) return mf @@ -60,49 +40,29 @@ func (mf *MainFlex) init() { } func (mf *MainFlex) onInputCapture(event *tcell.EventKey) *tcell.EventKey { - switch mf.mode { - case ModeNormal: - switch event.Name() { - case cfg.Keys.Normal.InsertMode: - mf.mode = ModeInsert - app.SetFocus(mf.messageInput) - return nil - - case cfg.Keys.Normal.FocusGuildsTree: - app.SetFocus(mf.guildsTree) - return nil - case cfg.Keys.Normal.FocusMessagesText: - app.SetFocus(mf.messagesText) - return nil - case cfg.Keys.Normal.ToggleGuildsTree: - // The guilds tree is visible if the numbers of items is two. - if mf.GetItemCount() == 2 { - mf.RemoveItem(mf.guildsTree) - if mf.guildsTree.HasFocus() { - app.SetFocus(mf) - } - } else { - mf.init() - app.SetFocus(mf.guildsTree) + switch event.Name() { + case cfg.Keys.FocusGuildsTree: + app.SetFocus(mf.guildsTree) + return nil + case cfg.Keys.FocusMessagesText: + app.SetFocus(mf.messagesText) + return nil + case cfg.Keys.FocusMessageInput: + app.SetFocus(mf.messageInput) + return nil + case cfg.Keys.ToggleGuildsTree: + // The guilds tree is visible if the numbers of items is two. + if mf.GetItemCount() == 2 { + mf.RemoveItem(mf.guildsTree) + if mf.guildsTree.HasFocus() { + app.SetFocus(mf) } - - return nil + } else { + mf.init() + app.SetFocus(mf.guildsTree) } - // do not propagate event to the children if the message input is focused in normal mode. - if mf.messageInput.HasFocus() { - return nil - } - case ModeInsert: - switch event.Name() { - case cfg.Keys.Insert.NormalMode: - mf.mode = ModeNormal - return nil - } - - if !mf.messageInput.HasFocus() { - return nil - } + return nil } return event diff --git a/cmd/message_input.go b/cmd/message_input.go index a8e5ae5..9b27966 100644 --- a/cmd/message_input.go +++ b/cmd/message_input.go @@ -49,97 +49,106 @@ func newMessageInput() *MessageInput { } func (mi *MessageInput) reset() { + mi.replyMessageIdx = -1 mi.SetTitle("") mi.SetText("", true) } func (mi *MessageInput) onInputCapture(event *tcell.EventKey) *tcell.EventKey { - switch mainFlex.mode { - case ModeInsert: - switch event.Name() { - case cfg.Keys.Insert.MessageInput.Send: - if !mainFlex.guildsTree.selectedChannelID.IsValid() { - return nil - } - - text := strings.TrimSpace(mi.GetText()) - if text == "" { - return nil - } - - if mi.replyMessageIdx != -1 { - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - data := api.SendMessageData{ - Content: text, - Reference: &discord.MessageReference{MessageID: ms[mi.replyMessageIdx].ID}, - AllowedMentions: &api.AllowedMentions{RepliedUser: option.False}, - } - - if strings.HasPrefix(mi.GetTitle(), "[@]") { - data.AllowedMentions.RepliedUser = option.True - } - - go func() { - if _, err := discordState.SendMessageComplex(mainFlex.guildsTree.selectedChannelID, data); err != nil { - log.Println("failed to send message:", err) - } - }() - } else { - go func() { - if _, err := discordState.SendMessage(mainFlex.guildsTree.selectedChannelID, text); err != nil { - log.Println("failed to send message:", err) - } - }() - } - - mi.replyMessageIdx = -1 - mainFlex.messagesText.Highlight() - mi.reset() - return nil - case cfg.Keys.Insert.MessageInput.Editor: - e := cfg.Editor - if e == "default" { - e = os.Getenv("EDITOR") - } - - f, err := os.CreateTemp("", constants.TmpFilePattern) - if err != nil { - log.Println(err) - return nil - } - _, _ = f.WriteString(mi.GetText()) - f.Close() - - defer os.Remove(f.Name()) - - cmd := exec.Command(e, f.Name()) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - app.Suspend(func() { - err := cmd.Run() - if err != nil { - log.Println(err) - return - } - }) - - msg, err := os.ReadFile(f.Name()) - if err != nil { - log.Println(err) - return nil - } - - mi.SetText(strings.TrimSpace(string(msg)), true) - return nil - } + switch event.Name() { + case cfg.Keys.MessageInput.Send: + mi.send() + return nil + case cfg.Keys.MessageInput.Editor: + mi.editor() + return nil + case cfg.Keys.MessageInput.Cancel: + mi.reset() + return nil } return event } + +func (mi *MessageInput) send() { + if !mainFlex.guildsTree.selectedChannelID.IsValid() { + return + } + + text := strings.TrimSpace(mi.GetText()) + if text == "" { + return + } + + if mi.replyMessageIdx != -1 { + ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) + if err != nil { + log.Println(err) + return + } + + data := api.SendMessageData{ + Content: text, + Reference: &discord.MessageReference{MessageID: ms[mi.replyMessageIdx].ID}, + AllowedMentions: &api.AllowedMentions{RepliedUser: option.False}, + } + + if strings.HasPrefix(mi.GetTitle(), "[@]") { + data.AllowedMentions.RepliedUser = option.True + } + + go func() { + if _, err := discordState.SendMessageComplex(mainFlex.guildsTree.selectedChannelID, data); err != nil { + log.Println("failed to send message:", err) + } + }() + } else { + go func() { + if _, err := discordState.SendMessage(mainFlex.guildsTree.selectedChannelID, text); err != nil { + log.Println("failed to send message:", err) + } + }() + } + + mi.replyMessageIdx = -1 + mainFlex.messagesText.Highlight() + mi.reset() +} + +func (mi *MessageInput) editor() { + e := cfg.Editor + if e == "default" { + e = os.Getenv("EDITOR") + } + + f, err := os.CreateTemp("", constants.TmpFilePattern) + if err != nil { + log.Println(err) + return + } + _, _ = f.WriteString(mi.GetText()) + f.Close() + + defer os.Remove(f.Name()) + + cmd := exec.Command(e, f.Name()) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + app.Suspend(func() { + err := cmd.Run() + if err != nil { + log.Println(err) + return + } + }) + + msg, err := os.ReadFile(f.Name()) + if err != nil { + log.Println(err) + return + } + + mi.SetText(strings.TrimSpace(string(msg)), true) +} diff --git a/cmd/messages_text.go b/cmd/messages_text.go index a764ab5..cd6b19f 100644 --- a/cmd/messages_text.go +++ b/cmd/messages_text.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "io" "log" @@ -149,179 +150,192 @@ func (mt *MessagesText) createFooter(w io.Writer, m discord.Message) { } } +func (mt *MessagesText) getSelectedMessage() (*discord.Message, error) { + if mt.selectedMessage == -1 { + return nil, errors.New("no message is currently selected") + } + + ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) + if err != nil { + return nil, err + } + + return &ms[mt.selectedMessage], nil +} + func (mt *MessagesText) onInputCapture(event *tcell.EventKey) *tcell.EventKey { - switch mainFlex.mode { - case ModeNormal: - switch event.Name() { - case cfg.Keys.Normal.MessagesText.Yank: - if mt.selectedMessage == -1 { - return nil - } - - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - err = clipboard.WriteAll(ms[mt.selectedMessage].Content) - if err != nil { - log.Println("failed to write to clipboard:", err) - return nil - } - - return nil - - case cfg.Keys.Normal.MessagesText.SelectFirst, cfg.Keys.Normal.MessagesText.SelectLast, cfg.Keys.Normal.MessagesText.SelectPrevious, cfg.Keys.Normal.MessagesText.SelectNext, cfg.Keys.Normal.MessagesText.SelectReply: - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - switch event.Name() { - case cfg.Keys.Normal.MessagesText.SelectPrevious: - // If no message is currently selected, select the latest message. - if len(mt.GetHighlights()) == 0 { - mt.selectedMessage = 0 - } else { - if mt.selectedMessage < len(ms)-1 { - mt.selectedMessage++ - } else { - return nil - } - } - case cfg.Keys.Normal.MessagesText.SelectNext: - // If no message is currently selected, select the latest message. - if len(mt.GetHighlights()) == 0 { - mt.selectedMessage = 0 - } else { - if mt.selectedMessage > 0 { - mt.selectedMessage-- - } else { - return nil - } - } - case cfg.Keys.Normal.MessagesText.SelectFirst: - mt.selectedMessage = len(ms) - 1 - case cfg.Keys.Normal.MessagesText.SelectLast: - mt.selectedMessage = 0 - case cfg.Keys.Normal.MessagesText.SelectReply: - if mt.selectedMessage == -1 { - return nil - } - - if ref := ms[mt.selectedMessage].ReferencedMessage; ref != nil { - for i, m := range ms { - if ref.ID == m.ID { - mt.selectedMessage = i - } - } - } - } - - mt.Highlight(ms[mt.selectedMessage].ID.String()) - mt.ScrollToHighlight() - return nil - case cfg.Keys.Normal.MessagesText.Open: - if mt.selectedMessage == -1 { - return nil - } - - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - attachments := ms[mt.selectedMessage].Attachments - if len(attachments) == 0 { - return nil - } - - for _, a := range attachments { - go func() { - if err := open.Start(a.URL); err != nil { - log.Println(err) - } - }() - } - - return nil - case cfg.Keys.Normal.MessagesText.Reply, cfg.Keys.Normal.MessagesText.ReplyMention: - if mt.selectedMessage == -1 { - return nil - } - - var title string - if event.Name() == cfg.Keys.Normal.MessagesText.ReplyMention { - title += "[@] Replying to " - } else { - title += "Replying to " - } - - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - title += ms[mt.selectedMessage].Author.Tag() - mainFlex.messageInput.SetTitle(title) - mainFlex.messageInput.replyMessageIdx = mt.selectedMessage - - app.SetFocus(mainFlex.messageInput) - return nil - case cfg.Keys.Normal.MessagesText.Delete: - if mt.selectedMessage == -1 { - return nil - } - - ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - m := ms[mt.selectedMessage] - clientID := discordState.Ready().User.ID - - ps, err := discordState.Permissions(mainFlex.guildsTree.selectedChannelID, discordState.Ready().User.ID) - if err != nil { - return nil - } - - if m.Author.ID != clientID && !ps.Has(discord.PermissionManageMessages) { - return nil - } - - if err := discordState.DeleteMessage(mainFlex.guildsTree.selectedChannelID, m.ID, ""); err != nil { - log.Println(err) - } - - if err := discordState.MessageRemove(mainFlex.guildsTree.selectedChannelID, m.ID); err != nil { - log.Println(err) - } - - ms, err = discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) - if err != nil { - log.Println(err) - return nil - } - - mt.Clear() - - for i := len(ms) - 1; i >= 0; i-- { - mainFlex.messagesText.createMessage(ms[i]) - } - + switch event.Name() { + case cfg.Keys.SelectPrevious, cfg.Keys.SelectNext, cfg.Keys.SelectFirst, cfg.Keys.SelectLast, cfg.Keys.MessagesText.SelectReply: + ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) + if err != nil { + log.Println(err) return nil } - // do not propagate event to the children in normal mode. + switch event.Name() { + case cfg.Keys.SelectPrevious: + // If no message is currently selected, select the latest message. + if len(mt.GetHighlights()) == 0 { + mt.selectedMessage = 0 + } else { + if mt.selectedMessage < len(ms)-1 { + mt.selectedMessage++ + } else { + return nil + } + } + case cfg.Keys.SelectNext: + // If no message is currently selected, select the latest message. + if len(mt.GetHighlights()) == 0 { + mt.selectedMessage = 0 + } else { + if mt.selectedMessage > 0 { + mt.selectedMessage-- + } else { + return nil + } + } + case cfg.Keys.SelectFirst: + mt.selectedMessage = len(ms) - 1 + case cfg.Keys.SelectLast: + mt.selectedMessage = 0 + case cfg.Keys.MessagesText.SelectReply: + if mt.selectedMessage == -1 { + return nil + } + + if ref := ms[mt.selectedMessage].ReferencedMessage; ref != nil { + for i, m := range ms { + if ref.ID == m.ID { + mt.selectedMessage = i + } + } + } + } + + mt.Highlight(ms[mt.selectedMessage].ID.String()) + mt.ScrollToHighlight() return nil + case cfg.Keys.MessagesText.Yank: + mt.yank() + return nil + case cfg.Keys.MessagesText.Open: + mt.open() + return nil + case cfg.Keys.MessagesText.Reply: + mt.reply(false) + return nil + case cfg.Keys.MessagesText.ReplyMention: + mt.reply(true) + return nil + case cfg.Keys.MessagesText.Delete: + mt.delete() + return nil } return event } + +func (mt *MessagesText) yank() { + msg, err := mt.getSelectedMessage() + if err != nil { + log.Println(err) + return + } + + err = clipboard.WriteAll(msg.Content) + if err != nil { + log.Println("failed to write to clipboard:", err) + return + } +} + +func (mt *MessagesText) open() { + msg, err := mt.getSelectedMessage() + if err != nil { + log.Println(err) + return + } + + attachments := msg.Attachments + if len(attachments) == 0 { + return + } + + for _, a := range attachments { + go func() { + if err := open.Start(a.URL); err != nil { + log.Println(err) + } + }() + } + +} + +func (mt *MessagesText) reply(mention bool) { + var title string + if mention { + title += "[@] Replying to " + } else { + title += "Replying to " + } + + msg, err := mt.getSelectedMessage() + if err != nil { + log.Println(err) + return + } + + title += msg.Author.Tag() + mainFlex.messageInput.SetTitle(title) + mainFlex.messageInput.replyMessageIdx = mt.selectedMessage + app.SetFocus(mainFlex.messageInput) +} + +func (mt *MessagesText) delete() { + + msg, err := mt.getSelectedMessage() + if err != nil { + log.Println(err) + return + } + + clientID := discordState.Ready().User.ID + if msg.GuildID.IsValid() { + ps, err := discordState.Permissions(mainFlex.guildsTree.selectedChannelID, discordState.Ready().User.ID) + if err != nil { + return + } + + if msg.Author.ID != clientID && !ps.Has(discord.PermissionManageMessages) { + return + } + } else { + if msg.Author.ID != clientID { + return + } + } + + if err := discordState.DeleteMessage(mainFlex.guildsTree.selectedChannelID, msg.ID, ""); err != nil { + log.Println(err) + return + } + + if err := discordState.MessageRemove(mainFlex.guildsTree.selectedChannelID, msg.ID); err != nil { + log.Println(err) + } + + ms, err := discordState.Cabinet.Messages(mainFlex.guildsTree.selectedChannelID) + if err != nil { + log.Println(err) + return + } + + mt.Clear() + + for i := len(ms) - 1; i >= 0; i-- { + mainFlex.messagesText.createMessage(ms[i]) + } + +} diff --git a/internal/config/config.go b/internal/config/config.go index 195ea56..5def224 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -22,7 +22,7 @@ type Config struct { Theme Theme `toml:"theme"` } -func defaultConfig() Config { +func DefaultConfig() Config { return Config{ Mouse: true, @@ -44,7 +44,7 @@ func Load() (*Config, error) { return nil, err } - cfg := defaultConfig() + cfg := DefaultConfig() path = filepath.Join(path, constants.Name, "config.toml") f, err := os.Open(path) if os.IsNotExist(err) { diff --git a/internal/config/keys.go b/internal/config/keys.go index a881810..3669288 100644 --- a/internal/config/keys.go +++ b/internal/config/keys.go @@ -2,35 +2,27 @@ package config type ( Keys struct { - Normal NormalModeKeys `toml:"normal"` - Insert InsertModeKeys `toml:"insert"` - } - - NormalModeKeys struct { - InsertMode string `toml:"insert_mode"` FocusGuildsTree string `toml:"focus_guilds_tree"` FocusMessagesText string `toml:"focus_messages_text"` + FocusMessageInput string `toml:"focus_message_input"` ToggleGuildsTree string `toml:"toggle_guild_tree"` - GuildsTree GuildsTreeNormalModeKeys `toml:"guilds_tree"` - MessagesText MessagesTextNormalModeKeys `toml:"messages_text"` - } - - GuildsTreeNormalModeKeys struct { - SelectCurrent string `toml:"select_current"` SelectPrevious string `toml:"select_previous"` SelectNext string `toml:"select_next"` SelectFirst string `toml:"select_first"` SelectLast string `toml:"select_last"` + + GuildsTree GuildsTreeKeys `toml:"guilds_tree"` + MessagesText MessagesTextKeys `toml:"messages_text"` + MessageInput MessageInputKeys `toml:"message_input"` } - MessagesTextNormalModeKeys struct { - SelectPrevious string `toml:"select_previous"` - SelectNext string `toml:"select_next"` - SelectFirst string `toml:"select_first"` - SelectLast string `toml:"select_last"` - SelectReply string `toml:"select_reply"` + GuildsTreeKeys struct { + SelectCurrent string `toml:"select_current"` + } + MessagesTextKeys struct { + SelectReply string `toml:"select_reply"` Reply string `toml:"reply"` ReplyMention string `toml:"reply_mention"` @@ -39,55 +31,44 @@ type ( Open string `toml:"open"` } - InsertModeKeys struct { - NormalMode string `toml:"normal_mode"` - - MessageInput MessageInputInsertModeKeys `toml:"message_input"` - } - - MessageInputInsertModeKeys struct { + MessageInputKeys struct { Send string `toml:"send"` Editor string `toml:"editor"` + Cancel string `toml:"cancel"` } ) func defaultKeys() Keys { return Keys{ - Normal: NormalModeKeys{ - InsertMode: "Rune[i]", + FocusGuildsTree: "Ctrl+G", + FocusMessagesText: "Ctrl+T", + FocusMessageInput: "Ctrl+P", + ToggleGuildsTree: "Ctrl+B", - FocusGuildsTree: "Ctrl+G", - FocusMessagesText: "Ctrl+T", - ToggleGuildsTree: "Ctrl+B", + SelectPrevious: "Rune[k]", + SelectNext: "Rune[j]", + SelectFirst: "Rune[g]", + SelectLast: "Rune[G]", - GuildsTree: GuildsTreeNormalModeKeys{ - SelectCurrent: "Enter", - SelectPrevious: "Rune[k]", - SelectNext: "Rune[j]", - SelectFirst: "Rune[g]", - SelectLast: "Rune[G]", - }, - MessagesText: MessagesTextNormalModeKeys{ - SelectPrevious: "Rune[k]", - SelectNext: "Rune[j]", - SelectFirst: "Rune[g]", - SelectLast: "Rune[G]", - SelectReply: "Rune[s]", - - Reply: "Rune[r]", - ReplyMention: "Rune[R]", - - Delete: "Rune[d]", - Yank: "Rune[y]", - Open: "Rune[o]", - }, + GuildsTree: GuildsTreeKeys{ + SelectCurrent: "Enter", }, - Insert: InsertModeKeys{ - NormalMode: "Esc", - MessageInput: MessageInputInsertModeKeys{ - Send: "Enter", - Editor: "Ctrl+E", - }, + + MessagesText: MessagesTextKeys{ + SelectReply: "Rune[s]", + + Reply: "Rune[r]", + ReplyMention: "Rune[R]", + + Delete: "Rune[d]", + Yank: "Rune[y]", + Open: "Rune[o]", + }, + + MessageInput: MessageInputKeys{ + Send: "Enter", + Editor: "Ctrl+E", + Cancel: "Esc", }, } }