initial commit
This commit is contained in:
commit
5a2ca8f361
7 changed files with 418 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bin/
|
21
Makefile
Normal file
21
Makefile
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
BIN = bin
|
||||||
|
BINS += $(BIN)/cherry
|
||||||
|
|
||||||
|
SRC = $(shell find . -iname "*.go")
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: $(BINS)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) $(BINS)
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: all
|
||||||
|
cp bin/cherry /usr/local/bin/cherry
|
||||||
|
|
||||||
|
$(BIN):
|
||||||
|
mkdir -p $(BIN)
|
||||||
|
|
||||||
|
$(BIN)/cherry: $(BIN) $(SRC)
|
||||||
|
go build -o $@ .
|
25
cmd/root.go
Normal file
25
cmd/root.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.cherry.town/town/cherry/launcher"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "cherry",
|
||||||
|
Short: "command-line utilities for cherry.town",
|
||||||
|
Long: "command-line utilities for cherry.town. if no sub-command\n" +
|
||||||
|
"is specified, the cherry.town program directory will be run.",
|
||||||
|
RunE: launcher.Run,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
32
go.mod
Normal file
32
go.mod
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
module git.cherry.town/town/cherry
|
||||||
|
|
||||||
|
go 1.22.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0
|
||||||
|
github.com/spf13/cobra v1.8.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
golang.org/x/sync v0.11.0 // indirect
|
||||||
|
golang.org/x/sys v0.30.0 // indirect
|
||||||
|
golang.org/x/text v0.3.8 // indirect
|
||||||
|
)
|
55
go.sum
Normal file
55
go.sum
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||||
|
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3 h1:WpU6fCY0J2vDWM3zfS3vIDi/ULq3SYphZhkAGGvmEUY=
|
||||||
|
github.com/charmbracelet/bubbletea v1.3.3/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
|
||||||
|
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||||
|
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||||
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
|
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
275
launcher/main.go
Normal file
275
launcher/main.go
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
// warning this code is messy and terrible
|
||||||
|
// TODO read list data from file
|
||||||
|
package launcher
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/bubbles/key"
|
||||||
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
var appStyle = lipgloss.NewStyle().Margin(1, 2)
|
||||||
|
|
||||||
|
var titleStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("0")).
|
||||||
|
Background(lipgloss.Color("5")).
|
||||||
|
Padding(0, 1)
|
||||||
|
|
||||||
|
var categoryTitleStyle = lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color("0")).
|
||||||
|
Background(lipgloss.Color("4")).
|
||||||
|
Padding(0, 1)
|
||||||
|
|
||||||
|
type Category struct {
|
||||||
|
title string
|
||||||
|
desc string
|
||||||
|
programs []list.Item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Category) Title() string { return c.title }
|
||||||
|
func (c Category) Description() string { return c.desc }
|
||||||
|
func (c Category) FilterValue() string { return c.title }
|
||||||
|
|
||||||
|
type Program struct {
|
||||||
|
title string
|
||||||
|
desc string
|
||||||
|
exec string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Program) Title() string { return p.title }
|
||||||
|
func (p Program) Description() string { return p.desc }
|
||||||
|
func (p Program) FilterValue() string { return p.title }
|
||||||
|
|
||||||
|
type model struct {
|
||||||
|
categoriesList list.Model
|
||||||
|
categoriesKeys *categoriesKeyMap
|
||||||
|
programsList list.Model
|
||||||
|
programsKeys *programsKeyMap
|
||||||
|
selectedCategory bool
|
||||||
|
shouldExec string
|
||||||
|
}
|
||||||
|
|
||||||
|
type categoriesKeyMap struct {
|
||||||
|
selectKey key.Binding
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCategoriesKeyMap() *categoriesKeyMap {
|
||||||
|
return &categoriesKeyMap{
|
||||||
|
selectKey: key.NewBinding(
|
||||||
|
key.WithKeys("enter"),
|
||||||
|
key.WithHelp("enter", "select"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type programsKeyMap struct {
|
||||||
|
exec key.Binding
|
||||||
|
back key.Binding
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProgramsKeyMap() *programsKeyMap {
|
||||||
|
return &programsKeyMap{
|
||||||
|
exec: key.NewBinding(
|
||||||
|
key.WithKeys("enter"),
|
||||||
|
key.WithHelp("enter", "exec"),
|
||||||
|
),
|
||||||
|
back: key.NewBinding(
|
||||||
|
key.WithKeys("b"),
|
||||||
|
key.WithHelp("b", "back"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var cmds []tea.Cmd
|
||||||
|
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.KeyMsg:
|
||||||
|
if msg.String() == "ctrl+c" {
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
if !m.selectedCategory {
|
||||||
|
switch {
|
||||||
|
case key.Matches(msg, m.categoriesKeys.selectKey):
|
||||||
|
var cat = m.categoriesList.SelectedItem().(Category)
|
||||||
|
m.programsList.SetItems(cat.programs)
|
||||||
|
m.programsList.Title = cat.title
|
||||||
|
m.selectedCategory = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch {
|
||||||
|
case key.Matches(msg, m.programsKeys.back):
|
||||||
|
m.selectedCategory = false
|
||||||
|
case key.Matches(msg, m.programsKeys.exec):
|
||||||
|
var prog = m.programsList.SelectedItem().(Program)
|
||||||
|
m.shouldExec = prog.exec
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
h, v := appStyle.GetFrameSize()
|
||||||
|
m.categoriesList.SetSize(msg.Width-h, msg.Height-v)
|
||||||
|
m.programsList.SetSize(msg.Width-h, msg.Height-v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd tea.Cmd
|
||||||
|
if m.selectedCategory {
|
||||||
|
m.programsList, cmd = m.programsList.Update(msg)
|
||||||
|
} else {
|
||||||
|
m.categoriesList, cmd = m.categoriesList.Update(msg)
|
||||||
|
}
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) View() string {
|
||||||
|
if m.selectedCategory {
|
||||||
|
return appStyle.Render(m.programsList.View())
|
||||||
|
} else {
|
||||||
|
return appStyle.Render(m.categoriesList.View())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(cmd *cobra.Command, args []string) error {
|
||||||
|
categories := []list.Item{
|
||||||
|
Category{
|
||||||
|
title: "editors",
|
||||||
|
desc: "for all your programming needs",
|
||||||
|
programs: []list.Item{
|
||||||
|
Program{
|
||||||
|
title: "helix (hx)",
|
||||||
|
desc: "next-generation modal editor",
|
||||||
|
exec: "hx",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "nano",
|
||||||
|
desc: "the easy option",
|
||||||
|
exec: "nano",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "neovim (nvim)",
|
||||||
|
desc: "like vim, but neo",
|
||||||
|
exec: "nvim",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "vim",
|
||||||
|
desc: "the one and only",
|
||||||
|
exec: "vim",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Category{
|
||||||
|
title: "games",
|
||||||
|
desc: "terminal fun",
|
||||||
|
programs: []list.Item{
|
||||||
|
Program{
|
||||||
|
title: "botany",
|
||||||
|
desc: "grow a plant in your terminal",
|
||||||
|
exec: "botany",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "nsnake",
|
||||||
|
desc: "ncurses snake game",
|
||||||
|
exec: "nsnake",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Category{
|
||||||
|
title: "social",
|
||||||
|
desc: "email, irc, etc.",
|
||||||
|
programs: []list.Item{
|
||||||
|
Program{
|
||||||
|
title: "irssi",
|
||||||
|
desc: "minimal irc client",
|
||||||
|
exec: "irssi",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "mutt",
|
||||||
|
desc: "tui email client",
|
||||||
|
exec: "mutt",
|
||||||
|
},
|
||||||
|
Program{
|
||||||
|
title: "weechat",
|
||||||
|
desc: "extendable, easy-to-use irc client",
|
||||||
|
exec: "weechat",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryDelegate := list.NewDefaultDelegate()
|
||||||
|
categoryKeys := newCategoriesKeyMap()
|
||||||
|
programDelegate := list.NewDefaultDelegate()
|
||||||
|
programKeys := newProgramsKeyMap()
|
||||||
|
|
||||||
|
categoryDelegate.Styles.SelectedTitle = categoryDelegate.Styles.SelectedTitle.
|
||||||
|
Foreground(lipgloss.Color("4")).BorderLeftForeground(lipgloss.Color("4"))
|
||||||
|
categoryDelegate.Styles.SelectedDesc = categoryDelegate.Styles.SelectedTitle
|
||||||
|
|
||||||
|
programDelegate.Styles.SelectedTitle = programDelegate.Styles.SelectedTitle.
|
||||||
|
Foreground(lipgloss.Color("1")).BorderLeftForeground(lipgloss.Color("1"))
|
||||||
|
programDelegate.Styles.SelectedDesc = programDelegate.Styles.SelectedTitle
|
||||||
|
|
||||||
|
m := model{
|
||||||
|
categoriesList: list.New(categories, categoryDelegate, 0, 0),
|
||||||
|
categoriesKeys: categoryKeys,
|
||||||
|
programsList: list.New([]list.Item{}, programDelegate, 0, 0),
|
||||||
|
programsKeys: programKeys,
|
||||||
|
selectedCategory: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.categoriesList.Title = "the cherry.town program directory"
|
||||||
|
m.categoriesList.Styles.Title = titleStyle
|
||||||
|
m.categoriesList.AdditionalShortHelpKeys = func() []key.Binding {
|
||||||
|
return []key.Binding{
|
||||||
|
categoryKeys.selectKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.categoriesList.AdditionalFullHelpKeys = func() []key.Binding {
|
||||||
|
return []key.Binding{
|
||||||
|
categoryKeys.selectKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.programsList.Styles.Title = categoryTitleStyle
|
||||||
|
m.programsList.AdditionalShortHelpKeys = func() []key.Binding {
|
||||||
|
return []key.Binding{
|
||||||
|
programKeys.exec,
|
||||||
|
programKeys.back,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.programsList.AdditionalFullHelpKeys = func() []key.Binding {
|
||||||
|
return []key.Binding{
|
||||||
|
programKeys.exec,
|
||||||
|
programKeys.back,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p := tea.NewProgram(m)
|
||||||
|
mf, err := p.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mf, ok := mf.(model); ok && mf.shouldExec != "" {
|
||||||
|
execCmd := exec.Command(mf.shouldExec)
|
||||||
|
execCmd.Stdin = os.Stdin
|
||||||
|
execCmd.Stdout = os.Stdout
|
||||||
|
execCmd.Stderr = os.Stderr
|
||||||
|
return execCmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
9
main.go
Normal file
9
main.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.cherry.town/town/cherry/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue