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

feat/std tui #51

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2202ca9
WIP: std TUI
blaggacao Apr 13, 2022
3ada194
WIP: std TUI
blaggacao Apr 15, 2022
37c9992
WIP: fix filter
blaggacao Apr 15, 2022
644f359
fix linting issues
manveru Apr 15, 2022
1b9e6f2
support j/k for movement
manveru Apr 15, 2022
381cbf8
example of showing help
manveru Apr 15, 2022
ea47b4c
WIP: fix proportions
blaggacao Apr 16, 2022
659ef72
WIP: add markdown help
blaggacao Apr 17, 2022
0e9392c
few renamings
blaggacao Apr 17, 2022
3742e82
readme with tabs
blaggacao Apr 17, 2022
4315e78
add loading spinner & test uninitialized state
blaggacao Apr 18, 2022
98f42c6
prepare for loading the flake metadata
blaggacao Apr 18, 2022
2b8a56b
add left/right for switching focus
blaggacao Apr 18, 2022
306ec0a
organize files
blaggacao Apr 18, 2022
971884d
add nice debugging info when loading of std meta json fails
blaggacao Apr 18, 2022
8432498
add first actual std meta parsing
blaggacao Apr 18, 2022
67cb39a
faint styling when action is missing
blaggacao Apr 18, 2022
9ba15e0
parse first actions
blaggacao Apr 18, 2022
5557949
WIP
blaggacao Apr 19, 2022
eef0f5b
add some clade actions
blaggacao Apr 19, 2022
abec29d
add proper error message display & example data
blaggacao Apr 19, 2022
659eb8b
make the data clade shine
blaggacao Apr 19, 2022
216f8c3
add action inspection
blaggacao Apr 19, 2022
84310bd
WIP
blaggacao Apr 19, 2022
9502139
bump bubbletea (with tea.Cmd)
blaggacao Apr 20, 2022
6bdd96a
use derivation to slightly speed up (and prep for nix-eval-cache)
blaggacao Apr 20, 2022
bc2458f
avoid necessity to declare dependencies
blaggacao Apr 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cells/std/cli/.gitignore
@@ -0,0 +1 @@
vendor
80 changes: 80 additions & 0 deletions cells/std/cli/actions.go
@@ -0,0 +1,80 @@
package main

import (
"fmt"

"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)

var (
ActionStyle = lipgloss.NewStyle().
Width(30).Height(32).
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("63"))
)

type ActionModel struct {
List list.Model
}

func (m *ActionModel) Init() tea.Cmd { return nil }

func (m *ActionModel) Update(msg tea.Msg) (*ActionModel, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
}
m.List, cmd = m.List.Update(msg)
return m, cmd
case tea.WindowSizeMsg:
}
return m, cmd
}
func (m *ActionModel) View() string {
return ActionStyle.Render(m.List.View())
}

func NewAction(i item) *ActionModel {
var (
appKeys = NewAppKeyMap()
numItems = cap(i.actions)
)
// Make list of actions
items := make([]list.Item, numItems)
for j := 0; j < numItems; j++ {
items[j] = i.actions[j]
}
actionList := list.New(items, list.NewDefaultDelegate(), 0, 32)
actionList.Title = fmt.Sprintf("Actions for %s", i.clade)
actionList.KeyMap = DefaultListKeyMap()
actionList.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
appKeys.toggleFocus,
}
}
actionList.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
appKeys.toggleFocus,
}
}
actionList.SetShowPagination(false)
actionList.SetShowHelp(false)
actionList.SetShowStatusBar(false)
actionList.SetFilteringEnabled(false)

return &ActionModel{actionList}
}

type action struct {
name string `json:"__action_name"`
command []string `json:"__action_command"`
description string `json:"__action_description"`
}

func (a action) Title() string { return a.name }
func (a action) Description() string { return a.description }
func (a action) FilterValue() string { return a.Title() }
117 changes: 17 additions & 100 deletions cells/std/cli/default.nix
Expand Up @@ -7,107 +7,24 @@
nixpkgs = inputs.nixpkgs;
in {
default = let
inherit (nixpkgs.chickenPackages) chickenEggs;
shell = nixpkgs.eggDerivation {
name = "shell-0.4";
src = nixpkgs.fetchegg {
name = "shell";
version = "0.4";
sha256 = "sha256-TVZBzvlVegDLNU3Nz3w92E7imXGw6HYOq+vm2amM+/w=";
};
buildInputs = [];
};
lazy-seq = nixpkgs.eggDerivation {
name = "lazy-seq-2";
src = nixpkgs.fetchegg {
name = "lazy-seq";
version = "2";
sha256 = "sha256-emjinMqdMpeaU9O7qN4v/xiJGfZyHC9YTMQlkk/aoB0=";
};
buildInputs = with chickenEggs; [srfi-1];
};
trie = nixpkgs.eggDerivation {
name = "trie-2";
src = nixpkgs.fetchegg {
name = "trie";
version = "2";
sha256 = "sha256-kdsywnZqJVFO+2vCba5BbpLW4azODO70LhgqQWzn65I=";
};
buildInputs = with chickenEggs; [srfi-1];
};
srfi-69 = nixpkgs.eggDerivation {
name = "srfi-69-0.4.3";
src = nixpkgs.fetchegg {
name = "srfi-69";
version = "0.4.3";
sha256 = "sha256-ejqj0EghSr7Ac4/fD5AHiRgbrmpJd9bVrTcPZknx9oY=";
# sha256 = nixpkgs.lib.fakeSha256;
};
};
comparse = nixpkgs.eggDerivation {
name = "comparse-3";
src = nixpkgs.fetchegg {
name = "comparse";
version = "3";
sha256 = "sha256-gpGLRF1cTvkEjEhV95jwaPpGI6tXoP2WqwSCZILShnU=";
};
buildInputs = with chickenEggs; [lazy-seq trie matchable srfi-13 srfi-69];
};
medea = nixpkgs.eggDerivation {
name = "medea-4";
src = nixpkgs.fetchegg {
name = "medea";
version = "4";
sha256 = "sha256-29AZOHuyacFeNS1dmH9qOxDB0IeyM8Lz0z1JQitdKOc=";
};
buildInputs = [comparse];
};
iset = nixpkgs.eggDerivation {
name = "iset";
src = nixpkgs.fetchegg {
name = "iset";
version = "2.2";
sha256 = "sha256-P49qdCSmd/5OFVe2DcgkhW3QA/Jyr+Wwtd1wdkBj03k=";
};
};
regex = nixpkgs.eggDerivation {
name = "regex";
src = nixpkgs.fetchegg {
name = "regex";
version = "2.0";
sha256 = "sha256-kkgEI2EA/XFTlyxdF9zG/EdoRzJr+474e9iXlFvO+GE=";
};
};
utf8 = nixpkgs.eggDerivation {
name = "utf8";
src = nixpkgs.fetchegg {
name = "utf8";
version = "3.6.3";
sha256 = "sha256-PJ53wuNStzziNhrG9Uu14Dc3mcPuncgodZM/Zxdtgbw=";
};
buildInputs = with chickenEggs; [iset srfi-69 regex];
};
fmt = nixpkgs.eggDerivation {
name = "fmt";
src = nixpkgs.fetchegg {
name = "fmt";
version = "0.8.11";
sha256 = "sha256-nmDj5Xmo29V+nLnxsIz5/bD72LtyyYWLNU4/CmFaGVg=";
};
buildInputs = with chickenEggs; [srfi-1 srfi-13 srfi-69 utf8];
};
commit = inputs.self.shortRev or "dirty";
date = inputs.self.lastModifiedDate or inputs.self.lastModified or "19700101";
version = "0.1.0+${builtins.substring 0 8 date}.${commit}";
in
nixpkgs.stdenv.mkDerivation {
name = "std";
meta.description = "nix shortcut for projects that conform to Standard";
nixpkgs.buildGoModule rec {
inherit version;
pname = "std";
meta.description = "A tui for projects that conform to Standard";

src = ./.;
dontInstall = true;
nativeBuildInputs = [nixpkgs.chicken];
buildInputs = with nixpkgs.chickenPackages.chickenEggs; [matchable srfi-13 shell medea fmt];
propagatedBuildInputs = [nixpkgs.git];
buildPhase = ''
mkdir -p $out/bin
csc -o $out/bin/std -static "$src/main.scm"
'';

vendorSha256 = null;

ldflags = [
"-s"
"-w"
"-X main.buildVersion=${version}"
"-X main.buildCommit=${commit}"
];
};
}
9 changes: 9 additions & 0 deletions cells/std/cli/go.mod
@@ -0,0 +1,9 @@
module github.com/divnix/std/cells/std/cli

go 1.16

require (
github.com/charmbracelet/bubbles v0.10.3
github.com/charmbracelet/bubbletea v0.20.0
github.com/charmbracelet/lipgloss v0.5.0
)
48 changes: 48 additions & 0 deletions cells/std/cli/go.sum
@@ -0,0 +1,48 @@
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/charmbracelet/bubbles v0.10.3 h1:fKarbRaObLn/DCsZO4Y3vKCwRUzynQD9L+gGev1E/ho=
github.com/charmbracelet/bubbles v0.10.3/go.mod h1:jOA+DUF1rjZm7gZHcNyIVW+YrBPALKfpGVdJu8UiJsA=
github.com/charmbracelet/bubbletea v0.19.3/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA=
github.com/charmbracelet/bubbletea v0.20.0 h1:/b8LEPgCbNr7WWZ2LuE/BV1/r4t5PyYJtDb+J3vpwxc=
github.com/charmbracelet/bubbletea v0.20.0/go.mod h1:zpkze1Rioo4rJELjRyGlm9T2YNou1Fm4LIJQSa5QMEM=
github.com/charmbracelet/harmonica v0.1.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM=
github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8=
github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw=
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 h1:QANkGiGr39l1EESqrE0gZw0/AJNYzIvoGLhIoVYtluI=
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed h1:Ei4bQjjpYUsS4efOUz+5Nz++IVkHk87n2zBA0NxBWc0=
golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
90 changes: 90 additions & 0 deletions cells/std/cli/keys.go
@@ -0,0 +1,90 @@
package main

import (
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list"
)

type AppKeyMap struct {
toggleFocus key.Binding
forceQuit key.Binding
}

func NewAppKeyMap() *AppKeyMap {
return &AppKeyMap{
// Swiching focus.
toggleFocus: key.NewBinding(
key.WithKeys("tab"),
key.WithHelp("⇥", "toggle focus"),
),

// Quitting.
forceQuit: key.NewBinding(key.WithKeys("ctrl+c")),
}
}

// DefaultListKeyMap returns a default set of keybindings.
func DefaultListKeyMap() list.KeyMap {
return list.KeyMap{
// Browsing.
CursorUp: key.NewBinding(
key.WithKeys("up"),
key.WithHelp("↑", "up"),
),
CursorDown: key.NewBinding(
key.WithKeys("down"),
key.WithHelp("↓", "down"),
),
PrevPage: key.NewBinding(
key.WithKeys("pgup"),
key.WithHelp("pgup", "prev page"),
),
NextPage: key.NewBinding(
key.WithKeys("pgdown"),
key.WithHelp("pgdn", "next page"),
),
GoToStart: key.NewBinding(
key.WithKeys("home"),
key.WithHelp("home", "go to start"),
),
GoToEnd: key.NewBinding(
key.WithKeys("end"),
key.WithHelp("end", "go to end"),
),
Filter: key.NewBinding(
key.WithKeys("/"),
key.WithHelp("/", "filter"),
),
ClearFilter: key.NewBinding(
key.WithKeys("esc"),
key.WithHelp("esc", "clear filter"),
),

// Filtering.
CancelWhileFiltering: key.NewBinding(
key.WithKeys("esc"),
key.WithHelp("esc", "cancel"),
),
AcceptWhileFiltering: key.NewBinding(
key.WithKeys("enter", "tab", "up", "down"),
key.WithHelp("enter", "apply filter"),
),

// Toggle help.
ShowFullHelp: key.NewBinding(
key.WithKeys("?"),
key.WithHelp("?", "more"),
),
CloseFullHelp: key.NewBinding(
key.WithKeys("?"),
key.WithHelp("?", "close help"),
),

// Quitting.
Quit: key.NewBinding(
key.WithKeys("q"),
key.WithHelp("q", "quit"),
),
ForceQuit: key.NewBinding(key.WithKeys("ctrl+c")),
}
}