summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod29
-rw-r--r--go.sum73
-rw-r--r--internal/app/app.go67
-rw-r--r--internal/app/flags.go (renamed from flags.go)2
-rw-r--r--internal/app/keybindings.md24
-rw-r--r--internal/documentation/documentation.go44
-rw-r--r--internal/logging/discard.go25
-rw-r--r--internal/logging/logging.go8
-rw-r--r--main.go37
9 files changed, 248 insertions, 61 deletions
diff --git a/go.mod b/go.mod
index 5de072d..09873f0 100644
--- a/go.mod
+++ b/go.mod
@@ -6,26 +6,43 @@ require (
github.com/atotto/clipboard v0.1.4
github.com/charmbracelet/bubbles v0.20.0
github.com/charmbracelet/bubbletea v1.2.3
+ github.com/charmbracelet/glamour v0.9.1
github.com/charmbracelet/harmonica v0.2.0
- github.com/charmbracelet/lipgloss v1.0.0
- github.com/charmbracelet/x/ansi v0.4.5
+ github.com/charmbracelet/lipgloss v1.1.0
+ github.com/charmbracelet/x/ansi v0.8.0
github.com/hashicorp/go-uuid v1.0.3
github.com/lucasb-eyer/go-colorful v1.2.0
- github.com/muesli/termenv v0.15.2
+ github.com/muesli/termenv v0.16.0
+ github.com/urfave/cli-docs/v3 v3.0.0-alpha6
github.com/urfave/cli/v3 v3.0.0-beta1
)
require (
+ github.com/alecthomas/chroma/v2 v2.14.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
+ github.com/aymerick/douceur v0.2.0 // indirect
+ github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
+ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+ github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
+ github.com/gorilla/css v1.0.1 // 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/microcosm-cc/bluemonday v1.0.27 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
+ github.com/muesli/reflow v0.3.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
- golang.org/x/sync v0.9.0 // indirect
- golang.org/x/sys v0.27.0 // indirect
- golang.org/x/text v0.8.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
+ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
+ github.com/yuin/goldmark v1.7.8 // indirect
+ github.com/yuin/goldmark-emoji v1.0.5 // indirect
+ golang.org/x/net v0.33.0 // indirect
+ golang.org/x/sync v0.12.0 // indirect
+ golang.org/x/sys v0.31.0 // indirect
+ golang.org/x/term v0.30.0 // indirect
+ golang.org/x/text v0.23.0 // indirect
)
diff --git a/go.sum b/go.sum
index 5db4ae7..b835f99 100644
--- a/go.sum
+++ b/go.sum
@@ -1,55 +1,104 @@
+github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
+github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
+github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
+github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
+github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
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/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
+github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
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.2.3 h1:d9MdMsANIYZB5pE1KkRqaUV6GfsiWm+/9z4fTuGVm9I=
github.com/charmbracelet/bubbletea v1.2.3/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
+github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
+github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
+github.com/charmbracelet/glamour v0.9.1 h1:11dEfiGP8q1BEqvGoIjivuc2rBk+5qEXdPtaQ2WoiCM=
+github.com/charmbracelet/glamour v0.9.1/go.mod h1:+SHvIS8qnwhgTpVMiXwn7OfGomSqff1cHBCI8jLOetk=
github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ=
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
-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.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM=
-github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
+github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
+github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
+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/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
+github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
+github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q=
+github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
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/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
+github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
+github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
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.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
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/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
+github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
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/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.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
+github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
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 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/urfave/cli-docs/v3 v3.0.0-alpha6 h1:w/l/N0xw1rO/aHRIGXJ0lDwwYFOzilup1qGvIytP3BI=
+github.com/urfave/cli-docs/v3 v3.0.0-alpha6/go.mod h1:p7Z4lg8FSTrPB9GTaNyTrK3ygffHZcK3w0cU2VE+mzU=
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
-golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
-golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
+github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
+github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
+github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
+github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
+github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
+github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
+golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
+golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
+golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
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.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
-golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
+golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
+golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
+golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/app/app.go b/internal/app/app.go
new file mode 100644
index 0000000..b17f32a
--- /dev/null
+++ b/internal/app/app.go
@@ -0,0 +1,67 @@
+package app
+
+import (
+ "context"
+ _ "embed"
+ "fmt"
+ "io"
+ "log/slog"
+
+ "github.com/ChausseBenjamin/termpicker/internal/logging"
+ "github.com/ChausseBenjamin/termpicker/internal/switcher"
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/glamour"
+ docs "github.com/urfave/cli-docs/v3"
+ "github.com/urfave/cli/v3"
+)
+
+//go:embed keybindings.md
+var KeybindingDocs string
+
+// Set by the build system
+var version = "compiled"
+
+func AppAction(ctx context.Context, cmd *cli.Command) error {
+ logfile := logging.Setup(cmd.String("logfile"))
+ defer logfile.Close()
+
+ slog.Info("Starting Termpicker")
+
+ sw := switcher.New()
+
+ if colorStr := cmd.String("color"); colorStr != "" {
+ sw.NewNotice(sw.SetColorFromText(colorStr))
+ }
+
+ p := tea.NewProgram(sw)
+ if _, err := p.Run(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func Command() *cli.Command {
+ cmd := &cli.Command{
+ Name: "termpicker",
+ Usage: "A terminal-based color picker",
+ Action: AppAction,
+ Authors: []any{"Benjamin Chausse <benjamin@chausse.xyz>"},
+ Version: version,
+ Flags: AppFlags,
+ EnableShellCompletion: true,
+ }
+
+ cli.HelpPrinter = func(w io.Writer, _ string, _ any) {
+ docs.MarkdownDocTemplate = fmt.Sprintf("%s\n‎\n\n%s",
+ docs.MarkdownDocTemplate,
+ KeybindingDocs,
+ )
+
+ helpRaw, _ := docs.ToMarkdown(cmd)
+ helpCute, _ := glamour.Render(helpRaw, "dark")
+
+ w.Write([]byte(helpCute))
+ }
+
+ return cmd
+}
diff --git a/flags.go b/internal/app/flags.go
index a7eb37f..fae403b 100644
--- a/flags.go
+++ b/internal/app/flags.go
@@ -1,4 +1,4 @@
-package main
+package app
import "github.com/urfave/cli/v3"
diff --git a/internal/app/keybindings.md b/internal/app/keybindings.md
new file mode 100644
index 0000000..03f8201
--- /dev/null
+++ b/internal/app/keybindings.md
@@ -0,0 +1,24 @@
+# KEYBINDINGS
+
+**Normal mode**:
+
+- `h`,`l`: coarse decrease/increase the current slider by 5%
+- `H`,`L`: fine decrease/increase the current slider by 1
+- `j`,`k`: select the slider below/above
+- `<Tab>`,`<S-Tab>`: move to the next/previous tab
+- `f`,`b`: copy the color as an ANSI escape code for the foreground/background
+- `x`,`r`,`s`,`c`: copy the color as a hex/rgb/hsl/cmyk
+- `?`: expand/shrink the help menu
+- `i`,`<cmd>`: enter Insert mode
+- `q`/`<C-c>`: quit the application
+
+**Insert mode**:
+
+Manually type a color. Pressing <Esc> will cancel/leave insert mode.
+Anything in the following formats will be used as a color input when
+pressing enter:
+
+- Hex values: `#rrggbb`
+- RGB values: `rgb( r, g, b)`
+- CMYK values: `cmyk(c, m, y, k)`
+- HSL values: `hsl(h, s, l)`
diff --git a/internal/documentation/documentation.go b/internal/documentation/documentation.go
new file mode 100644
index 0000000..af4b302
--- /dev/null
+++ b/internal/documentation/documentation.go
@@ -0,0 +1,44 @@
+/*
+ * This package isn't the actual termpicker app.
+ * To avoid importing packages which aren't needed at runtime,
+ * some auto-generation functionnalities is offloaded to here so
+ * it can be done with access to the rest of the code-base but
+ * without bloating the final binary. For example,
+ * generating bash+zsh auto-completion scripts isn't needed in
+ * the final binary if those script are generated before hand.
+ * Same gose for manpages. This file is meant to be run automatically
+ * to easily package new releases. Same goes for manpages which is the
+ * only feature currently in here.
+ */
+package main
+
+import (
+ _ "embed"
+ "log/slog"
+ "os"
+ "strings"
+
+ "github.com/ChausseBenjamin/termpicker/internal/app"
+ docs "github.com/urfave/cli-docs/v3"
+)
+
+func main() {
+ a := app.Command()
+
+ docs.MarkdownDocTemplate = strings.Join(
+ []string{
+ docs.MarkdownDocTemplate,
+ app.KeybindingDocs,
+ },
+ "\n",
+ )
+
+ man, err := docs.ToManWithSection(a, 1)
+ if err != nil {
+ slog.Error("failed to generate man page",
+ slog.Any("error_message", err),
+ )
+ os.Exit(1)
+ }
+ os.Stdout.Write([]byte(man))
+}
diff --git a/internal/logging/discard.go b/internal/logging/discard.go
new file mode 100644
index 0000000..e827287
--- /dev/null
+++ b/internal/logging/discard.go
@@ -0,0 +1,25 @@
+package logging
+
+import (
+ "context"
+ "log/slog"
+)
+
+// DiscardHandler discards all log output. DiscardHandler.Enabled returns false for all Levels.
+type DiscardHandler struct{}
+
+func (d DiscardHandler) Enabled(ctx context.Context, level slog.Level) bool {
+ return false
+}
+
+func (d DiscardHandler) Handle(ctx context.Context, record slog.Record) error {
+ return nil
+}
+
+func (d DiscardHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ return d
+}
+
+func (d DiscardHandler) WithGroup(name string) slog.Handler {
+ return d
+}
diff --git a/internal/logging/logging.go b/internal/logging/logging.go
index 71f0334..054b303 100644
--- a/internal/logging/logging.go
+++ b/internal/logging/logging.go
@@ -7,12 +7,6 @@ import (
"github.com/ChausseBenjamin/termpicker/internal/util"
)
-type logSink struct{}
-
-func (l logSink) Write(p []byte) (n int, err error) {
- return len(p), nil
-}
-
func Setup(filepath string) *os.File {
if filepath != "" {
logFile, err := os.Create(filepath)
@@ -28,7 +22,7 @@ func Setup(filepath string) *os.File {
} else {
// Since app is a TUI, logging to stdout/stderr would break the UI
// So we disable it by default
- handler := slog.NewJSONHandler(logSink{}, nil)
+ handler := DiscardHandler{}
slog.SetDefault(slog.New(handler))
return nil
}
diff --git a/main.go b/main.go
index f8dacf8..4fdb35e 100644
--- a/main.go
+++ b/main.go
@@ -5,45 +5,12 @@ import (
"log/slog"
"os"
- "github.com/ChausseBenjamin/termpicker/internal/logging"
- "github.com/ChausseBenjamin/termpicker/internal/switcher"
+ "github.com/ChausseBenjamin/termpicker/internal/app"
"github.com/ChausseBenjamin/termpicker/internal/util"
- tea "github.com/charmbracelet/bubbletea"
- "github.com/urfave/cli/v3"
)
-// Set by the build system
-var version = "compiled"
-
-func AppAction(ctx context.Context, cmd *cli.Command) error {
- logfile := logging.Setup(cmd.String("logfile"))
- defer logfile.Close()
-
- slog.Info("Starting Termpicker")
-
- sw := switcher.New()
-
- if colorStr := cmd.String("color"); colorStr != "" {
- sw.NewNotice(sw.SetColorFromText(colorStr))
- }
-
- p := tea.NewProgram(sw)
- if _, err := p.Run(); err != nil {
- return err
- }
- return nil
-}
-
func main() {
- app := &cli.Command{
- Name: "Termpicker",
- Usage: "A terminal-based color picker",
- Action: AppAction,
- Authors: []any{"Benjamin Chausse <benjamin@chausse.xhz>"},
- Version: version,
- Flags: AppFlags,
- EnableShellCompletion: true,
- }
+ app := app.Command()
if err := app.Run(context.Background(), os.Args); err != nil {
slog.Error("Program crashed", util.ErrKey, err.Error())
os.Exit(1)