Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b309799
feat: Use system-wide Escape key for exiting
cilginc Oct 15, 2025
6d3251d
chore: updated github project structure
cilginc Oct 15, 2025
6f4c655
fix: go module
cilginc Oct 15, 2025
d81576c
refactor: refactored wayland package
cilginc Oct 15, 2025
c53985b
refactor: added models package
cilginc Oct 15, 2025
ae49475
refactor: added stroke package
cilginc Oct 15, 2025
38c9661
refactor: added shaders package
cilginc Oct 15, 2025
731daa5
feat: better shader implementation
cilginc Oct 15, 2025
b2b216c
refactor: added config package
cilginc Oct 15, 2025
24a8a91
refactor: added execute package
cilginc Oct 15, 2025
1731bab
refactor: added default dpackage
cilginc Oct 15, 2025
bcdc939
refactor: added gesture package
cilginc Oct 15, 2025
d758750
chore: updated gitignore
cilginc Oct 15, 2025
2c7426f
refactor: all the project
cilginc Oct 15, 2025
d58a38c
chore: handled unhandled error
cilginc Oct 15, 2025
291b496
chore: updated deprecated functions
cilginc Oct 15, 2025
4e8aa39
feat: embedded the shader files
cilginc Oct 15, 2025
f47aba9
chore: deleted fornow package
cilginc Oct 17, 2025
fb052ff
!feat: added root cli parameter
cilginc Oct 16, 2025
d435b08
!feat: added run cli parameter
cilginc Oct 16, 2025
ec7ac09
!feat: added learn cli parameter
cilginc Oct 16, 2025
2543e6c
!feat: added list cli parameter
cilginc Oct 16, 2025
7c23e39
!feat: added remove cli parameter
cilginc Oct 16, 2025
8f86e69
!feat: added completion cli parameter
cilginc Oct 16, 2025
0640e3a
Merge branch 'main' into params
ThatOtherAndrew Oct 20, 2025
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
47 changes: 47 additions & 0 deletions cmd/completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

var completionCmd = &cobra.Command{
Use: "completion [bash|zsh|fish]",
Short: "Get completions for your favorite shell",
RunE: GetCompletion,
ValidArgs: []string{"bash", "zsh", "fish"},
DisableFlagsInUseLine: true,
}

func init() {
rootCmd.AddCommand(completionCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// completionCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// completionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func GetCompletion(cmd *cobra.Command, args []string) error {
if len(args) <= 0 {
return cmd.Help()
}

switch args[0] {
case "bash":
return rootCmd.GenBashCompletionV2(os.Stdout, true)
case "zsh":
return rootCmd.GenZshCompletion(os.Stdout)
case "fish":
return rootCmd.GenFishCompletion(os.Stdout, true)
default:
return fmt.Errorf("unsupported shell: %s", args[0])
}
}
211 changes: 2 additions & 209 deletions cmd/hexecute/main.go
Original file line number Diff line number Diff line change
@@ -1,214 +1,7 @@
package main

import (
"encoding/json"
"flag"
"log"
"os"
"runtime"
"time"

"github.com/ThatOtherAndrew/Hexecute/internal/config"
"github.com/ThatOtherAndrew/Hexecute/internal/draw"
"github.com/ThatOtherAndrew/Hexecute/internal/execute"
gestures "github.com/ThatOtherAndrew/Hexecute/internal/gesture"
"github.com/ThatOtherAndrew/Hexecute/internal/models"
"github.com/ThatOtherAndrew/Hexecute/internal/opengl"
"github.com/ThatOtherAndrew/Hexecute/internal/spawn"
"github.com/ThatOtherAndrew/Hexecute/internal/stroke"
"github.com/ThatOtherAndrew/Hexecute/internal/update"
"github.com/ThatOtherAndrew/Hexecute/pkg/wayland"
"github.com/go-gl/gl/v4.1-core/gl"
)

func init() {
runtime.LockOSThread()
}

type App struct {
*models.App
}
import "github.com/ThatOtherAndrew/Hexecute/cmd"

func main() {
learnCommand := flag.String("learn", "", "Learn a new gesture for the specified command")
listGestures := flag.Bool("list", false, "List all registered gestures")
removeGesture := flag.String("remove", "", "Remove a gesture by command name")
flag.Parse()

if flag.NArg() > 0 {
log.Fatalf("Unknown arguments: %v", flag.Args())
}

if *listGestures {
gestures, err := gestures.LoadGestures()
if err != nil {
log.Fatal("Failed to load gestures:", err)
}
if len(gestures) == 0 {
println("No gestures registered")
} else {
println("Registered gestures:")
for _, g := range gestures {
println(" ", g.Command)
}
}
return
}

if *removeGesture != "" {
gestures, err := gestures.LoadGestures()
if err != nil {
log.Fatal("Failed to load gestures:", err)
}

found := false
for i, g := range gestures {
if g.Command == *removeGesture {
gestures = append(gestures[:i], gestures[i+1:]...)
found = true
break
}
}

if !found {
log.Fatalf("Gesture not found: %s", *removeGesture)
}

configFile, err := config.GetPath()
if err != nil {
log.Fatal("Failed to get config path:", err)
}

data, err := json.Marshal(gestures)
if err != nil {
log.Fatal("Failed to marshal gestures:", err)
}

if err := os.WriteFile(configFile, data, 0644); err != nil {
log.Fatal("Failed to save gestures:", err)
}

println("Removed gesture:", *removeGesture)
return
}

window, err := wayland.NewWaylandWindow()
if err != nil {
log.Fatal("Failed to create Wayland window:", err)
}
defer window.Destroy()

app := &models.App{StartTime: time.Now()}

if *learnCommand != "" {
app.LearnMode = true
app.LearnCommand = *learnCommand
log.Printf("Learn mode: Draw the gesture 3 times for command '%s'", *learnCommand)
} else {
gestures, err := gestures.LoadGestures()
if err != nil {
log.Fatal("Failed to load gestures:", err)
}
app.SavedGestures = gestures
log.Printf("Loaded %d gesture(s)", len(gestures))
}

opengl := opengl.New(app)
if err := opengl.InitGL(); err != nil {
log.Fatal("Failed to initialize OpenGL:", err)
}

gl.ClearColor(0, 0, 0, 0)

for range 5 {
window.PollEvents()
gl.Clear(gl.COLOR_BUFFER_BIT)
window.SwapBuffers()
}

x, y := window.GetCursorPos()
app.LastCursorX = float32(x)
app.LastCursorY = float32(y)

lastTime := time.Now()
var wasPressed bool

for !window.ShouldClose() {
now := time.Now()
dt := float32(now.Sub(lastTime).Seconds())
lastTime = now

window.PollEvents()
update := update.New(app)
update.UpdateCursor(window)

if key, state, hasKey := window.GetLastKey(); hasKey {
if state == 1 && key == 0xff1b {
if !app.IsExiting {
app.IsExiting = true
app.ExitStartTime = time.Now()
window.DisableInput()
x, y := window.GetCursorPos()
spawn := spawn.New(app)
spawn.SpawnExitWisps(float32(x), float32(y))
}
}
window.ClearLastKey()
}

if app.IsExiting {
if time.Since(app.ExitStartTime).Seconds() > 0.8 {
break
}
}
isPressed := window.GetMouseButton()
if isPressed && !wasPressed {
app.IsDrawing = true
} else if !isPressed && wasPressed {
app.IsDrawing = false

if app.LearnMode && len(app.Points) > 0 {
processed := stroke.ProcessStroke(app.Points)
app.LearnGestures = append(app.LearnGestures, processed)
app.LearnCount++
log.Printf("Captured gesture %d/3", app.LearnCount)

app.Points = nil

if app.LearnCount >= 3 {
if err := gestures.SaveGesture(app.LearnCommand, app.LearnGestures); err != nil {
log.Fatal("Failed to save gesture:", err)
}
log.Printf("Gesture saved for command: %s", app.LearnCommand)

app.IsExiting = true
app.ExitStartTime = time.Now()
window.DisableInput()
x, y := window.GetCursorPos()
spawn := spawn.New(app)
spawn.SpawnExitWisps(float32(x), float32(y))
}
} else if !app.LearnMode && len(app.Points) > 0 {
x, y := window.GetCursorPos()
exec := execute.New(app)
exec.RecognizeAndExecute(window, float32(x), float32(y))
app.Points = nil
}
}
wasPressed = isPressed

if app.IsDrawing {
x, y := window.GetCursorPos()
gesture := gestures.New(app)
gesture.AddPoint(float32(x), float32(y))

spawn := spawn.New(app)
spawn.SpawnCursorSparkles(float32(x), float32(y))
}

update.UpdateParticles(dt)
drawer := draw.New(app)
drawer.Draw(window)
window.SwapBuffers()
}
cmd.Execute()
}
Loading