Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support modifying default keybindings prototype #356

Merged
merged 7 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 46 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
<img src="https://user-images.githubusercontent.com/6196971/198704107-6775a0ba-669d-418b-9ae9-59228aaa84d1.gif" />

## ✨ Features
* 🌅 fully configurable - define sections using github filters
* 🔍 search for both prs and issues
* 📝 customize columns with `hidden`, `width` and `grow` props
* ⚡️ act on prs and issues with checkout, comment, open, merge, diff, etc...
* ⌨️ set custom actions with new keybindings
* 💅 use custom themes
* 🔭 view details about a pr/issue with a detailed sidebar
* 🪟 write multiple configuration files to easily switch between completely different dashboards
* ♻️ set an interval for auto refreshing the dashboard

- 🌅 fully configurable - define sections using github filters
- 🔍 search for both prs and issues
- 📝 customize columns with `hidden`, `width` and `grow` props
- ⚡️ act on prs and issues with checkout, comment, open, merge, diff, etc...
- ⌨️ set custom actions with new keybindings
- 💅 use custom themes
- 🔭 view details about a pr/issue with a detailed sidebar
- 🪟 write multiple configuration files to easily switch between completely different dashboards
- ♻️ set an interval for auto refreshing the dashboard

## 📦 Installation

Expand Down Expand Up @@ -70,19 +71,23 @@
<details>
<summary>How do I get these exact colors and font?</summary>

> I'm using [Alacritty](https://github.com/alacritty/alacritty) with the [tokyonight theme](https://github.com/folke/tokyonight.nvim) and the [Fira Code](https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FiraCode) Nerd Font.
> For my full setup check out [my dotfiles](https://github.com/dlvhdr/dotfiles/blob/main/.config/alacritty/alacritty.yml).
> I'm using [Alacritty](https://github.com/alacritty/alacritty) with the [tokyonight theme](https://github.com/folke/tokyonight.nvim) and the [Fira Code](https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/FiraCode) Nerd Font.
> For my full setup check out [my dotfiles](https://github.com/dlvhdr/dotfiles/blob/main/.config/alacritty/alacritty.yml).
</details>
## ⚡️ Usage
Run
```sh
gh dash
```
Then press <kbd>?</kbd> for help.
Run `gh dash --help` for more info:
```
Usage:
gh dash [flags]
Expand All @@ -96,6 +101,7 @@ Flags:
## ⚙️ Configuring
A section is defined by a:
- title - shown in the TUI
- filters - how the repo's PRs should be filtered - these are plain [github filters](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests)

Expand Down Expand Up @@ -158,9 +164,31 @@ It can be useful if you want to have a 🧳 work and 👩‍💻 personal dashbo
### ⌨️ Keybindings
Define your own custom keybindings to run bash commands using [Go Templates](https://pkg.go.dev/text/template).
This is available for both PRs and Issues.
You can:
1. Override the builtin commands keybindings
2. Define your own custom keybindings to run bash commands using [Go Templates](https://pkg.go.dev/text/template).
#### Overriding builtin commands keybindings
To override the "checkout" keybinding you can include this in your `config.yml` file:
```yaml
keybindings:
prs:
- key: O
builtin: checkout
```
The list of available builtin commands are:
1. `universal`: up, down, firstLine, lastLine, togglePreview, openGithub, refresh, refreshAll, pageDown, pageUp, nextSection, prevSection, search, copyurl, copyNumber, help, quit
2. `prs`: assign, unassign, comment, diff, checkout, close, ready, reopen, merge, watchChecks, viewIssues
3. `Issues`: assign, unassign, comment, close, reopen, viewPrs
#### Defining custom keybindings
This is available for both PRs and Issues.
For PRs, the available arguments are:
| Argument | Description |
Expand All @@ -179,9 +207,9 @@ For Issues, the available arguments are:
| `RepoPath` | The path to the Repo, using the `config.yml` `repoPaths` key to get the mapping |
| `IssueNumber` | The Issue number |
#### Examples
**Examples**
To review a PR with either Neovim or VSCode include the following in your `config.yml` file:
1. To review a PR with either Neovim or VSCode include the following in your `config.yml` file:
```yaml
repoPaths:
Expand All @@ -202,7 +230,7 @@ keybindings:
gh pr checkout {{.PrNumber}}
```
To pin an issue include the following in your `config.yml` file:
2. To pin an issue include the following in your `config.yml` file:
```yaml
keybindings:
Expand All @@ -222,7 +250,7 @@ An `:owner/:repo` template can be specified as a generic fallback.
```yaml
repoPaths:
:owner/:repo: ~/src/github.com/:owner/:repo # template if you always clone github repos in a consistent location
dlvhdr/*: ~/code/repos/dlvhdr/* # will match dlvhdr/repo-name to ~/code/repos/dlvhdr/repo-name
dlvhdr/*: ~/code/repos/dlvhdr/* # will match dlvhdr/repo-name to ~/code/repos/dlvhdr/repo-name
dlvhdr/gh-dash: ~/code/gh-dash # will not match wildcard and map to specified path
```
Expand Down Expand Up @@ -259,6 +287,7 @@ theme:
You can customize each section's layout as well as the global layout.

For example, to hide the `author` column for **all** PR sections, include the following in your `config.yml`.

```
defaults:
layout:
Expand All @@ -271,7 +300,6 @@ defaults:
- For `issues` the column names are: `updatedAt, state, repo, title, creator, assignees, comments, reactions`.
- The available properties to control are: `grow` (false, true), `width` (number of cells), and `hidden` (false, true).


## Author

Dolev Hadar [email protected]
24 changes: 20 additions & 4 deletions config/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"
"strings"

"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/lipgloss"
"github.com/go-playground/validator/v10"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -104,11 +105,25 @@ type Defaults struct {
type Keybinding struct {
Key string `yaml:"key"`
Command string `yaml:"command"`
Builtin string `yaml:"builtin"`
}

func (kb Keybinding) NewBinding(previous *key.Binding) key.Binding {
helpDesc := ""
if previous != nil {
helpDesc = previous.Help().Desc
}

return key.NewBinding(
key.WithKeys(kb.Key),
key.WithHelp(kb.Key, helpDesc),
)
}

type Keybindings struct {
Issues []Keybinding `yaml:"issues"`
Prs []Keybinding `yaml:"prs"`
Universal []Keybinding `yaml:"universal"`
Issues []Keybinding `yaml:"issues"`
Prs []Keybinding `yaml:"prs"`
}

type Pager struct {
Expand Down Expand Up @@ -258,8 +273,9 @@ func (parser ConfigParser) getDefaultConfig() Config {
},
},
Keybindings: Keybindings{
Issues: []Keybinding{},
Prs: []Keybinding{},
Universal: []Keybinding{},
Issues: []Keybinding{},
Prs: []Keybinding{},
},
RepoPaths: map[string]string{},
Theme: &ThemeConfig{
Expand Down
43 changes: 42 additions & 1 deletion ui/keys/issueKeys.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package keys

import "github.com/charmbracelet/bubbles/key"
import (
"fmt"

"github.com/charmbracelet/bubbles/key"
log "github.com/charmbracelet/log"

"github.com/dlvhdr/gh-dash/v4/config"
)

type IssueKeyMap struct {
Assign key.Binding
Expand Down Expand Up @@ -48,3 +55,37 @@ func IssueFullHelp() []key.Binding {
IssueKeys.ViewPRs,
}
}

func rebindIssueKeys(keys []config.Keybinding) error {
for _, issueKey := range keys {
if issueKey.Builtin == "" {
continue
}

log.Debug("Rebinding issue key", "builtin", issueKey.Builtin, "key", issueKey.Key)

var key *key.Binding

switch issueKey.Builtin {
case "assign":
key = &IssueKeys.Assign
case "unassign":
key = &IssueKeys.Unassign
case "comment":
key = &IssueKeys.Comment
case "close":
key = &IssueKeys.Close
case "reopen":
key = &IssueKeys.Reopen
case "viewPrs":
key = &IssueKeys.ViewPRs
default:
return fmt.Errorf("unknown built-in issue key: '%s'", issueKey.Builtin)
}

key.SetKeys(issueKey.Key)
key.SetHelp(issueKey.Key, key.Help().Desc)
}

return nil
}
77 changes: 76 additions & 1 deletion ui/keys/keys.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package keys

import (
"fmt"

"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
log "github.com/charmbracelet/log"

"github.com/dlvhdr/gh-dash/v4/config"
)
Expand Down Expand Up @@ -82,7 +85,7 @@ func (k KeyMap) QuitAndHelpKeys() []key.Binding {
return []key.Binding{k.Help, k.Quit}
}

var Keys = KeyMap{
var Keys = &KeyMap{
Up: key.NewBinding(
key.WithKeys("up", "k"),
key.WithHelp("↑/k", "move up"),
Expand Down Expand Up @@ -152,3 +155,75 @@ var Keys = KeyMap{
key.WithHelp("q", "quit"),
),
}

// Rebind will update our saved keybindings from configuration values.
func Rebind(universal, issueKeys, prKeys []config.Keybinding) error {
dlvhdr marked this conversation as resolved.
Show resolved Hide resolved
err := rebindUniversal(universal)
if err != nil {
return err
}

err = rebindPRKeys(prKeys)
if err != nil {
return err
}

return rebindIssueKeys(issueKeys)
}

func rebindUniversal(universal []config.Keybinding) error {
log.Debug("Rebinding universal keys", "keys", universal)
for _, kb := range universal {
if kb.Builtin == "" {
continue
}

log.Debug("Rebinding universal key", "builtin", kb.Builtin, "key", kb.Key)

var key *key.Binding

switch kb.Builtin {
case "up":
dlvhdr marked this conversation as resolved.
Show resolved Hide resolved
key = &Keys.Up
case "down":
key = &Keys.Down
case "firstLine":
key = &Keys.FirstLine
case "lastLine":
key = &Keys.LastLine
case "togglePreview":
key = &Keys.TogglePreview
case "openGithub":
key = &Keys.OpenGithub
case "refresh":
key = &Keys.Refresh
case "refreshAll":
key = &Keys.RefreshAll
case "pageDown":
key = &Keys.PageDown
case "pageUp":
key = &Keys.PageUp
case "nextSection":
key = &Keys.NextSection
case "prevSection":
key = &Keys.PrevSection
case "search":
key = &Keys.Search
case "copyurl":
key = &Keys.CopyUrl
case "copyNumber":
key = &Keys.CopyNumber
case "help":
key = &Keys.Help
case "quit":
key = &Keys.Quit
default:
return fmt.Errorf("unknown built-in universal key: '%s'", kb.Builtin)
}

key.SetKeys(kb.Key)
key.SetHelp(kb.Key, key.Help().Desc)
}

return nil
}
49 changes: 49 additions & 0 deletions ui/keys/prKeys.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package keys

import (
"fmt"

"github.com/charmbracelet/bubbles/key"
log "github.com/charmbracelet/log"

"github.com/dlvhdr/gh-dash/v4/config"
)

type PRKeyMap struct {
Expand Down Expand Up @@ -80,3 +85,47 @@ func PRFullHelp() []key.Binding {
PRKeys.ViewIssues,
}
}

func rebindPRKeys(keys []config.Keybinding) error {
dlvhdr marked this conversation as resolved.
Show resolved Hide resolved
for _, prKey := range keys {
if prKey.Builtin == "" {
continue
}

log.Debug("Rebinding PR key", "builtin", prKey.Builtin, "key", prKey.Key)

var key *key.Binding

switch prKey.Builtin {
case "assign":
key = &PRKeys.Assign
case "unassign":
key = &PRKeys.Unassign
case "comment":
key = &PRKeys.Comment
case "diff":
key = &PRKeys.Diff
case "checkout":
key = &PRKeys.Checkout
case "close":
key = &PRKeys.Close
case "ready":
key = &PRKeys.Ready
case "reopen":
key = &PRKeys.Reopen
case "merge":
key = &PRKeys.Merge
case "watchChecks":
key = &PRKeys.WatchChecks
case "viewIssues":
key = &PRKeys.ViewIssues
default:
return fmt.Errorf("unknown built-in pr key: '%s'", prKey.Builtin)
}

key.SetKeys(prKey.Key)
key.SetHelp(prKey.Key, key.Help().Desc)
}

return nil
}
Loading
Loading