aboutsummaryrefslogtreecommitdiff
path: root/main.go
blob: 5a9c9ea9df7a1638ae84444198dde07985d40333 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main

// #cgo linux LDFLAGS: -lX11 -lXtst -lXi
// #include "keyboard_writer.h"
// #include "keyboard_reader.h"
import "C"

import (
	"errors"
	"fmt"
	"github.com/BurntSushi/toml"
	"github.com/sirupsen/logrus"
	"reflect"
	"strings"
	"time"
)

type tomlConfig struct {
	Bindings map[string]binding
}

type binding struct {
	Keypress string
	Text     string
}

func main() {
	// Startup Load the config
	config, err := get_config()
	if err != nil {
		logrus.Println(err)
		return
	}
	for {
		expansion := wait_for_autocomplete(config)
		logrus.Println(fmt.Sprintf("executing: %s", expansion))
		time.Sleep(100 * time.Millisecond)
		for _, v := range expansion {
			cs := C.CString(char_to_x11(string(v)))
			if stringInSlice(string(v), needsShift) {
				C.x11_key_shift(cs)
			} else {
				C.x11_key(cs)
			}
		}
	}
}

func get_config() (tomlConfig, error) {
	var config tomlConfig
	if _, err := toml.DecodeFile("incantation.toml", &config); err != nil {
		return config, errors.New("Can't load config file")
	}
	return config, nil
}

func wait_for_autocomplete(config tomlConfig) string {
	max_length := 10
	buffer := make([]string, max_length)
	for {
		key_press := x11_to_char(C.GoString(C.get_key()))
		// Cut down length
		if len(buffer) == max_length {
			buffer = buffer[1:]
		}
		buffer = append(buffer, key_press)
		logrus.Println(strings.Join(buffer, ", "))
		// Check for expansion matches, windowing through buffer
		for _, binding := range config.Bindings {
			// Build kepress string into slice for slice comparison
			keypress_slice := make([]string, 0)
			for _, v := range binding.Keypress {
				keypress_slice = append(keypress_slice, string(v))
			}
			for i := 0; i < len(buffer)-len(keypress_slice)+1; i++ {
				tmp_buf := buffer[i : i+len(keypress_slice)]
				if reflect.DeepEqual(tmp_buf, keypress_slice) {
					// Erase the keypresses
					for range binding.Keypress {
						cs := C.CString("BackSpace")
						C.x11_key(cs)
					}
					return binding.Text
				}
			}
		}
	}
}

func char_to_x11(code string) string {
	for k, v := range x11Map {
		if k == code {
			return v
		}
	}
	return code
}

func x11_to_char(code string) string {
	for k, v := range x11Map {
		if v == code {
			return k
		}
	}
	return code
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}