Compare commits

...

3 Commits

Author SHA1 Message Date
f932050632 Added Nix
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m7s
2025-12-25 12:43:36 -07:00
975c61cce3 ???
All checks were successful
Docker Deploy / build-and-push (push) Successful in 2m25s
2025-12-23 11:07:07 -07:00
3df6aa402a Fuck 2025-12-23 11:07:06 -07:00
7 changed files with 103 additions and 41 deletions

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

5
.gitignore vendored
View File

@@ -1,2 +1,7 @@
main main
yule yule
.ssh/
# nix
.direnv/
result

View File

@@ -4,4 +4,6 @@ services:
container_name: yule container_name: yule
ports: ports:
- "${SSH_PORT:-2222}:2222" - "${SSH_PORT:-2222}:2222"
volumes:
- ${ROOT_DIR}:/app/.ssh
restart: unless-stopped restart: unless-stopped

27
flake.lock generated Normal file
View File

@@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1766473571,
"narHash": "sha256-5G1NDO2PulBx1RoaA6U1YoUDX0qZslpPxv+n5GX6Qto=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "76701a179d3a98b07653e2b0409847499b2a07d3",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

38
flake.nix Normal file
View File

@@ -0,0 +1,38 @@
{
description = "yule dev shell";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
};
outputs = { self, nixpkgs }:
let
allSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
pkgs = import nixpkgs { inherit system; };
});
in
{
devShells = forAllSystems ({ pkgs }: {
default = pkgs.mkShell {
packages = with pkgs; [
go
gopls
gotools
go-tools
];
shellHook = ''
echo "<yule dev shell>"
echo "Go version: $(go version)"
'';
};
});
};
}

2
go.mod
View File

@@ -8,6 +8,7 @@ require (
github.com/charmbracelet/lipgloss v1.1.0 github.com/charmbracelet/lipgloss v1.1.0
github.com/charmbracelet/ssh v0.0.0-20250826160808-ebfa259c7309 github.com/charmbracelet/ssh v0.0.0-20250826160808-ebfa259c7309
github.com/charmbracelet/wish v1.4.7 github.com/charmbracelet/wish v1.4.7
github.com/muesli/termenv v0.16.0
) )
require ( require (
@@ -35,7 +36,6 @@ require (
github.com/mattn/go-runewidth v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/crypto v0.46.0 // indirect golang.org/x/crypto v0.46.0 // indirect

67
main.go
View File

@@ -19,6 +19,7 @@ import (
"github.com/charmbracelet/wish/activeterm" "github.com/charmbracelet/wish/activeterm"
"github.com/charmbracelet/wish/bubbletea" "github.com/charmbracelet/wish/bubbletea"
"github.com/charmbracelet/wish/logging" "github.com/charmbracelet/wish/logging"
"github.com/muesli/termenv"
) )
const ( const (
@@ -33,6 +34,7 @@ func init() {
func main() { func main() {
s, err := wish.NewServer( s, err := wish.NewServer(
wish.WithAddress(net.JoinHostPort(host, port)), wish.WithAddress(net.JoinHostPort(host, port)),
wish.WithHostKeyPath(".ssh/id_ed25519"),
wish.WithMiddleware( wish.WithMiddleware(
bubbletea.Middleware(teaHandler), bubbletea.Middleware(teaHandler),
activeterm.Middleware(), activeterm.Middleware(),
@@ -66,7 +68,9 @@ func main() {
func teaHandler(s ssh.Session) (tea.Model, []tea.ProgramOption) { func teaHandler(s ssh.Session) (tea.Model, []tea.ProgramOption) {
pty, _, _ := s.Pty() pty, _, _ := s.Pty()
m := newModel(pty.Window.Width, pty.Window.Height) renderer := bubbletea.MakeRenderer(s)
renderer.SetColorProfile(termenv.ANSI256)
m := newModel(pty.Window.Width, pty.Window.Height, renderer)
return m, []tea.ProgramOption{tea.WithAltScreen()} return m, []tea.ProgramOption{tea.WithAltScreen()}
} }
@@ -77,9 +81,10 @@ type model struct {
height int height int
viewport viewport.Model viewport viewport.Model
buffer []int buffer []int
renderer *lipgloss.Renderer
} }
func newModel(width, height int) model { func newModel(width, height int, renderer *lipgloss.Renderer) model {
vp := viewport.New(width, height) vp := viewport.New(width, height)
size := width * height size := width * height
return model{ return model{
@@ -87,6 +92,7 @@ func newModel(width, height int) model {
height: height, height: height,
viewport: vp, viewport: vp,
buffer: make([]int, size+width+1), buffer: make([]int, size+width+1),
renderer: renderer,
} }
} }
@@ -159,58 +165,40 @@ func (m model) View() string {
return m.renderFire() return m.renderFire()
} }
// ANSI 256-color palette for fire effect (from dark to bright) var fireColors = []string{"0", "52", "88", "124", "160", "196", "202", "208", "214", "220", "226", "227", "228", "229", "230"}
var fireStyles = []lipgloss.Style{
lipgloss.NewStyle().Foreground(lipgloss.Color("0")), // black
lipgloss.NewStyle().Foreground(lipgloss.Color("52")), // dark red
lipgloss.NewStyle().Foreground(lipgloss.Color("88")), // dark red 2
lipgloss.NewStyle().Foreground(lipgloss.Color("124")), // red
lipgloss.NewStyle().Foreground(lipgloss.Color("160")), // red 2
lipgloss.NewStyle().Foreground(lipgloss.Color("196")), // bright red
lipgloss.NewStyle().Foreground(lipgloss.Color("202")), // orange-red
lipgloss.NewStyle().Foreground(lipgloss.Color("208")), // orange
lipgloss.NewStyle().Foreground(lipgloss.Color("214")), // orange-yellow
lipgloss.NewStyle().Foreground(lipgloss.Color("220")), // yellow
lipgloss.NewStyle().Foreground(lipgloss.Color("226")), // bright yellow
lipgloss.NewStyle().Foreground(lipgloss.Color("227")), // light yellow
lipgloss.NewStyle().Foreground(lipgloss.Color("228")), // pale yellow
lipgloss.NewStyle().Foreground(lipgloss.Color("229")), // near white
lipgloss.NewStyle().Foreground(lipgloss.Color("230")), // white-yellow
}
var fireChars = []rune{' ', '.', ':', '^', '*', 'x', 's', 'S', '#', '$'} var fireChars = []rune{' ', '.', ':', '^', '*', 'x', 's', 'S', '#', '$'}
func getFireStyle(v int) lipgloss.Style { func getFireColorIndex(v int) int {
if v <= 0 { if v <= 0 {
return fireStyles[0] return 0
} else if v <= 2 { } else if v <= 2 {
return fireStyles[1] return 1
} else if v <= 4 { } else if v <= 4 {
return fireStyles[2] return 2
} else if v <= 6 { } else if v <= 6 {
return fireStyles[3] return 3
} else if v <= 8 { } else if v <= 8 {
return fireStyles[4] return 4
} else if v <= 10 { } else if v <= 10 {
return fireStyles[5] return 5
} else if v <= 13 { } else if v <= 13 {
return fireStyles[6] return 6
} else if v <= 16 { } else if v <= 16 {
return fireStyles[7] return 7
} else if v <= 20 { } else if v <= 20 {
return fireStyles[8] return 8
} else if v <= 25 { } else if v <= 25 {
return fireStyles[9] return 9
} else if v <= 30 { } else if v <= 30 {
return fireStyles[10] return 10
} else if v <= 40 { } else if v <= 40 {
return fireStyles[11] return 11
} else if v <= 50 { } else if v <= 50 {
return fireStyles[12] return 12
} else if v <= 60 { } else if v <= 60 {
return fireStyles[13] return 13
} }
return fireStyles[14] return 14
} }
func (m model) renderFire() string { func (m model) renderFire() string {
@@ -232,7 +220,8 @@ func (m model) renderFire() string {
v = m.buffer[i] v = m.buffer[i]
} }
style := getFireStyle(v) colorIdx := getFireColorIndex(v)
style := m.renderer.NewStyle().Foreground(lipgloss.Color(fireColors[colorIdx]))
chIdx := v chIdx := v
if chIdx > 9 { if chIdx > 9 {
@@ -248,7 +237,7 @@ func (m model) renderFire() string {
} }
footer := "Press 'q' to exit" footer := "Press 'q' to exit"
footerStyle := lipgloss.NewStyle(). footerStyle := m.renderer.NewStyle().
Foreground(lipgloss.Color("240")). Foreground(lipgloss.Color("240")).
Width(width). Width(width).
Align(lipgloss.Center) Align(lipgloss.Center)