Skip to content
This repository was archived by the owner on Nov 28, 2024. It is now read-only.

Commit 60e2142

Browse files
committed
v1.0
0 parents  commit 60e2142

File tree

19 files changed

+2455
-0
lines changed

19 files changed

+2455
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
tmpfile
2+
yoshinon

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Moe-hacker
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
GOLANG = go
2+
LDFLAGS = "-s -w"
3+
all:
4+
sed -i "s/Commit_id \= \"\"/Commit_id \= \"`git log --oneline|head -1|cut -d " " -f 1`\"/" main.go
5+
$(GOLANG) mod download
6+
$(GOLANG) build -ldflags $(LDFLAGS) -o yoshinon main.go

README.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<p align="center">
2+
<img src="https://github.com/Moe-hacker/yoshinon/raw/main/logo.png", width="75%"/>
3+
</p>
4+
5+
## About:
6+
Yoshinon ~~(よしのん)~~ is a whiptail-like dialog box written with Bubble Tea (Go).
7+
The command-line usage is very similar to dialog/whiptail.
8+
## Usage:
9+
As we all know, premature optimization is the root of all evil, so this will be done after I get all the modules working.
10+
## TODO:
11+
- [X] msgbox
12+
- [X] yesno
13+
- [X] inputbox
14+
- [X] passwordbox
15+
- [X] menu
16+
- [X] checklist
17+
- [X] radiolist
18+
- [X] gauge
19+
- [ ] help page
20+
- [ ] man page
21+
22+
## Thanks:
23+
[Bubble Tea](https://github.com/charmbracelet/bubbletea)
24+
```
25+
● ● ●●● ●●● ● ● ●●● ● ● ●●● ● ●
26+
● ● ● ● ● ● ● ● ●● ● ● ● ●● ●
27+
● ● ● ●●● ●●●●● ● ● ● ● ● ● ● ● ●
28+
● ● ● ● ● ● ● ● ●● ● ● ● ●●
29+
● ●●● ●●● ● ● ●●● ● ● ●●● ● ●
30+
```
31+
<p align="center">「鸟になって云をつかんで、</p>
32+
<p align="center">风になって遥远くへ</p>
33+
<p align="center">希望を抱いて飞んだ」</p>

checklist/checklist.go

+259
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
// SPDX-License-Identifier: MIT
2+
/*
3+
*
4+
* This file is part of yoshinon, with ABSOLUTELY NO WARRANTY.
5+
*
6+
* MIT License
7+
*
8+
* Copyright (c) 2023 Moe-hacker
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* The above copyright notice and this permission notice shall be included in all
18+
* copies or substantial portions of the Software.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26+
* SOFTWARE.
27+
*
28+
*
29+
*
30+
*/
31+
32+
package checklist
33+
34+
import (
35+
"fmt"
36+
tea "github.com/charmbracelet/bubbletea"
37+
"golang.org/x/sys/unix"
38+
"os"
39+
"syscall"
40+
. "yoshinon/ui"
41+
. "yoshinon/help"
42+
)
43+
44+
var (
45+
tags []string
46+
items []string
47+
status []int
48+
width int
49+
height int
50+
listheight int
51+
listwidth int
52+
message string
53+
border string
54+
bgcolor = "\033[1;48;2;100;149;237m"
55+
cursorcolor = "\033[1;48;2;152;245;225m"
56+
boxcolor = "\033[1;48;2;254;228;208m\033[1;38;2;0;0;0m"
57+
)
58+
59+
type Checklist_config struct {
60+
Tags []string
61+
Items []string
62+
Status []int
63+
Width int
64+
Height int
65+
Listheight int
66+
Message string
67+
Bgcolor string
68+
Cursorcolor string
69+
Boxcolor string
70+
Border string
71+
}
72+
type model struct {
73+
// Current chosen choice.
74+
cursor int
75+
// Curson position on the screen.
76+
position int
77+
// For yesno buttons.
78+
yesno int
79+
}
80+
81+
func (m model) Init() tea.Cmd {
82+
// See ui.go
83+
Draw_borders(bgcolor, boxcolor, border, height, width)
84+
// Correct the value of listheight.
85+
if listheight > len(items) {
86+
listheight = len(items)
87+
}
88+
// Set value of listwidth.
89+
for i := 0; i < len(items); i++ {
90+
if len(items[i])+len(tags[i])+2 > listwidth {
91+
listwidth = len(items[i]) + len(tags[i]) + 2
92+
}
93+
}
94+
return nil
95+
}
96+
97+
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
98+
switch msg := msg.(type) {
99+
case tea.KeyMsg:
100+
switch msg.String() {
101+
case "enter":
102+
return m, tea.Quit
103+
case "tab":
104+
if m.yesno < 3 {
105+
m.yesno++
106+
} else {
107+
m.yesno = 1
108+
}
109+
case "down", "j":
110+
if m.yesno == 1 {
111+
if m.cursor < len(items)-1 {
112+
m.cursor++
113+
}
114+
if m.position < listheight-1 {
115+
m.position++
116+
}
117+
} else {
118+
if m.yesno < 3 {
119+
m.yesno++
120+
} else {
121+
m.yesno = 1
122+
}
123+
}
124+
case "up", "k":
125+
if m.yesno == 1 {
126+
if m.cursor > 0 {
127+
m.cursor--
128+
}
129+
if m.position > 0 {
130+
m.position--
131+
}
132+
} else {
133+
if m.yesno > 1 {
134+
m.yesno--
135+
} else {
136+
m.yesno = 1
137+
}
138+
}
139+
case " ":
140+
if status[m.cursor] == 1 {
141+
status[m.cursor] = 0
142+
} else {
143+
status[m.cursor] = 1
144+
}
145+
}
146+
}
147+
return m, nil
148+
}
149+
150+
func (m model) View() string {
151+
fmt.Fprint(os.Stderr, "\033[1H"+bgcolor)
152+
ws, err := unix.IoctlGetWinsize(syscall.Stderr, unix.TIOCGWINSZ)
153+
if err != nil {
154+
panic(err)
155+
}
156+
wsrow := int(ws.Row)
157+
wscol := int(ws.Col)
158+
control := ""
159+
row := (wsrow-height)/2 + 3
160+
col := ((wscol / 2) - len(message)/2) + 2
161+
control = "\033[" + fmt.Sprint(row) + "H" + "\033[" + fmt.Sprint(col) + "G"
162+
// See ui.go
163+
Show_message(message, boxcolor, width, height)
164+
row = ((wsrow / 2) - (listheight / 2)) + 2
165+
col = ((wscol / 2) - (listwidth / 2)) + 2
166+
for i := m.cursor - m.position; i < m.cursor+(listheight-m.position); i++ {
167+
control = "\033[" + fmt.Sprint(row) + "H" + "\033[" + fmt.Sprint(col) + "G"
168+
if m.cursor == i && m.yesno == 1 {
169+
if status[i] == 1 {
170+
fmt.Fprintf(os.Stderr, control+cursorcolor+"[x]"+tags[i]+" "+items[i]+"\033[0m"+boxcolor)
171+
} else {
172+
fmt.Fprintf(os.Stderr, control+cursorcolor+"[ ]"+tags[i]+" "+items[i]+"\033[0m"+boxcolor)
173+
}
174+
} else {
175+
if status[i] == 1 {
176+
fmt.Fprintf(os.Stderr, control+boxcolor+"[x]"+tags[i]+" "+items[i])
177+
} else {
178+
fmt.Fprintf(os.Stderr, control+boxcolor+"[ ]"+tags[i]+" "+items[i])
179+
}
180+
}
181+
for j := 0; j <= listwidth-len(tags[i])-len(items[i])-2; j++ {
182+
fmt.Fprintf(os.Stderr, " ")
183+
}
184+
fmt.Fprintf(os.Stderr, "\033[0m"+bgcolor)
185+
fmt.Fprintf(os.Stderr, "\n")
186+
row++
187+
}
188+
row = (wsrow-height)/2 + height
189+
col = (wscol-width)/2 + 3
190+
control = "\033[" + fmt.Sprint(row) + "H" + "\033[" + fmt.Sprint(col) + "G"
191+
space := ""
192+
for i := 0; i < ((width/2)-7)*2; i++ {
193+
space += " "
194+
}
195+
if m.yesno == 2 {
196+
fmt.Fprintf(os.Stderr, cursorcolor+control+"<OK>\033[0m"+boxcolor+space+"<CANCEL>"+"\n")
197+
} else if m.yesno == 3 {
198+
fmt.Fprintf(os.Stderr, "\033[0m"+control+boxcolor+"<OK>"+space+cursorcolor+"<CANCEL>"+"\n")
199+
} else {
200+
fmt.Fprintf(os.Stderr, control+boxcolor+"<OK>"+space+"<CANCEL>\n")
201+
}
202+
return boxcolor
203+
}
204+
205+
func Checklist(m Checklist_config) string {
206+
height = m.Height
207+
width = m.Width
208+
listheight = m.Listheight
209+
tags = make([]string, len(m.Tags))
210+
for i := 0; i < len(m.Tags); i++ {
211+
tags[i] = m.Tags[i]
212+
}
213+
items = make([]string, len(m.Items))
214+
for i := 0; i < len(m.Items); i++ {
215+
items[i] = m.Items[i]
216+
}
217+
status = make([]int, len(m.Status))
218+
for i := 0; i < len(m.Items); i++ {
219+
status[i] = m.Status[i]
220+
}
221+
message = m.Message
222+
if m.Bgcolor != "" {
223+
bgcolor = m.Bgcolor
224+
}
225+
if m.Boxcolor != "" {
226+
boxcolor = m.Boxcolor
227+
}
228+
if m.Cursorcolor != "" {
229+
cursorcolor = m.Cursorcolor
230+
}
231+
if m.Border == "" {
232+
m.Border = "rounded"
233+
}
234+
border = m.Border
235+
// Check window size.
236+
ws, err := unix.IoctlGetWinsize(syscall.Stderr, unix.TIOCGWINSZ)
237+
if err != nil {
238+
panic(err)
239+
}
240+
wsrow := int(ws.Row)
241+
wscol := int(ws.Col)
242+
if wsrow < height+4 || wscol < width+4 {
243+
Error("window size is too small")
244+
os.Exit(1)
245+
}
246+
p := tea.NewProgram(model{yesno: 1}, tea.WithOutput(os.Stderr), tea.WithAltScreen())
247+
r, _ := p.Run()
248+
fmt.Fprint(os.Stderr, "\033[?25h\033c")
249+
if r.(model).yesno == 3 {
250+
os.Exit(1)
251+
}
252+
ret := ""
253+
for i := 0; i < len(tags); i++ {
254+
if status[i] == 1 {
255+
ret += "\"" + tags[i] + "\"" + " "
256+
}
257+
}
258+
return ret
259+
}

0 commit comments

Comments
 (0)