-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcommands.go
154 lines (140 loc) · 4.44 KB
/
commands.go
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Licensed under the GPL-v3
// Copyright: Sebastian Tilders <[email protected]> (c) 2019
package ncurses
// TODO(sebi2020) Ensure that only one instance of Term control the Terminal
import (
// #cgo LDFLAGS: -lncursesw
// #include <binding.h>
// #include <curses.h>
"C"
"fmt"
"os"
"runtime"
)
// Command channel ensures Thread safety
var comChan chan Command = make(chan Command,4)
// Name of a ncurses command
type CommandName uint8
// Data of a ncurses command
type CommandValue interface{}
// Scope of Command
type CommandScope int
const (
GLOBAL CommandScope = iota // not a window specific command
LOCAL // a window specific command
)
//All available commands, which can be passed to the command channel
const (
MOVE CommandName = iota // Move the terminal cursor
ADD // Add string at current cursor location
INSERT // Insert string at current cursor location
DELETE // Delete string at current cursor locatio
REFRESH // Flush buffer to video memory
CLEAR // Clear the entire window
SCROLLOK // Enables scrolling
SCROLL // Scrolls current window
SETCOLOR // Sets the color for text and background
WBKGD // Sets fg and bg of entire window
ATTRSET // Sets font attributes for follwing output
START_TA // UNIMPL(sebi2020) Initiates a transaction
END_TA // UNIMPL(sebi2020) Finalizes a transaction
)
// TODO(sebi2020): Use generator for this
func (cn CommandName) String() string {
switch cn {
case MOVE:
return "MOV"
case ADD:
return "ADD"
case INSERT:
return "INS"
case DELETE:
return "DEL"
case REFRESH:
return "REFRESH"
case CLEAR:
return "CLEAR"
case SCROLLOK:
return "SCROLLOK"
case SCROLL:
return "SCROLL"
case SETCOLOR:
return "SETCOLOR"
case WBKGD:
return "WBKGD"
case ATTRSET:
return "ATTRSET"
default:
return fmt.Sprintf("Unkown (%x)",int(cn))
}
}
// Ncurse related commands
type Command struct {
// Name of the command
Name CommandName
// Window on which the command should be executed
Window *Window
// Scope of command
Scope CommandScope
// Data which should be passed along with the command
Value CommandValue
}
// Implements Stringer interface for 'type Command'.
func (c Command) String() string {
return fmt.Sprintf("Command <%s>",c.Name)
}
// Returns the command channel associated with stdscr (see ncurses documentation for information about stdscr)
func GetComChannel() chan<- Command {
return comChan
}
func (com Command) execute () {
var handle winst
if com.Scope != GLOBAL {
if com.Window == nil {
panic(fmt.Sprintf("No Context for command %s", com))
}
handle = (*C.struct__win_st)(com.Window.chandle)
}
// TODO(sebi2020): Maybe use an interface with type inference to distinguish between different commands.
switch com.Name {
case MOVE:
pos := com.Value.(Position)
C.wmove(handle,C.int(pos.Y),C.int(pos.X))
case ADD:
text := C.CString(com.Value.(string))
C.bind_waddstr(handle,text)
case INSERT:
text := C.CString(com.Value.(string))
C.winsstr(handle,text)
case REFRESH:
C.wrefresh(handle)
case CLEAR:
C.wclear(handle)
case SCROLLOK:
C.scrollok(handle,C.bool(com.Value.(bool)))
case SCROLL:
C.wscrl(handle,C.int(com.Value.(int)))
case SETCOLOR:
C.bind_color_set(C.short(com.Value.(pairId)))
case WBKGD:
C.bind_wbkgd(handle,C.short(com.Value.(pairId)))
case ATTRSET:
C.wattrset(handle,C.int(com.Value.(int)))
default:
panic(fmt.Sprintf("Command %s not implemented",com))
}
}
func recoverFromPanic() {
if r := recover(); r != nil {
Endwin()
fmt.Printf("Ncurses panic: %s",r)
os.Exit(-1)
}
}
func processCommands() {
runtime.LockOSThread()
defer recoverFromPanic()
for com := range comChan {
com.execute()
}
}