1
1
package main
2
2
3
3
import (
4
+ "EXP/pkg/shellout"
4
5
"context"
6
+ "encoding/json"
5
7
"fmt"
6
- "github.com/codeskyblue/go-sh"
7
8
"github.com/spf13/cobra"
8
- "github.com/spf13/pflag"
9
9
"os"
10
10
"strings"
11
11
"sync"
12
+ "time"
12
13
)
13
14
14
- type CobraCallbackE func ( cmd * cobra. Command , args [] string ) error
15
+ var bgctx = context . Background ()
15
16
16
17
var (
17
18
cmd = & cobra.Command {
18
- Use : "goprompt" ,
19
- PersistentPreRunE : bindEnvironmentFlags ("GOPROMPT" ),
19
+ Use : "goprompt" ,
20
20
}
21
- cmdQuery = & cobra.Command {
22
- Use : "query" ,
23
- RunE : cmdQueryExec ,
24
- }
25
-
26
- cmdQueryStatus = cmd .PersistentFlags ().Int (
21
+ flgCmdStatus = cmd .PersistentFlags ().Int (
27
22
"cmd-status" , 0 ,
28
23
"cmd status of previous command" ,
29
24
)
30
- cmdQueryPreexecTS = cmd .PersistentFlags ().String (
31
- "preexec-ts" , "0" ,
25
+ flgPreexecTS = cmd .PersistentFlags ().Int (
26
+ "preexec-ts" , 0 ,
32
27
"pre-execution timestamp to gauge how log execution took" ,
33
28
)
34
29
)
35
30
36
31
func init () {
37
- cmd .AddCommand (cmdQuery )
38
-
32
+ cmd .RunE = cmdExec
39
33
}
40
34
41
- func bindEnvironmentFlags (prefix string ) CobraCallbackE {
42
- return func (cmd * cobra.Command , args []string ) (outErr error ) {
43
- cmd .Flags ().VisitAll (func (f * pflag.Flag ) {
44
- if ! f .Changed {
45
- envKey := prefix + "_" + strings .ReplaceAll (f .Name , "-" , "_" )
46
- if value , ok := os .LookupEnv (strings .ToUpper (envKey )); ok {
47
- if err := cmd .Flags ().Set (f .Name , value ); err != nil {
48
- outErr = err
49
- return
50
- }
51
- }
52
- }
53
- })
54
- return nil
55
- }
56
- }
35
+ // PROMPT PARTS:
36
+ // (exit-status: if > 0)
37
+ // (parent-process)
38
+ // (hostname: if remote connection)
39
+ // (current-dir-path)
40
+ // (vsc-information)
41
+ // (timestamp)
57
42
58
- func cmdQueryExec (cmd * cobra.Command , args []string ) error {
59
- if * cmdQueryStatus != 0 {
60
- printPart ("st" , fmt .Sprintf ("%#v" , * cmdQueryStatus ))
43
+ func cmdExec (cmd * cobra.Command , args []string ) error {
44
+ if * flgCmdStatus != 0 {
45
+ printPart ("st" , fmt .Sprintf ("%#v" , * flgCmdStatus ))
61
46
}
62
47
63
- wg := new (sync.WaitGroup )
48
+ wg := new (WaitGroupDispatcher )
49
+ defer wg .Wait ()
64
50
65
- wg .Add (1 )
66
- go func () {
67
- defer wg .Done ()
51
+ wg .Dispatch (func () {
52
+ homeDir := os .Getenv ("HOME" )
68
53
69
54
if wd , err := os .Getwd (); err == nil {
70
- printPart ("wd" , trimPathLast (wd , 2 ))
55
+ wdh := strings .Replace (wd , homeDir , "~" , 1 )
56
+
57
+ printPart ("wd_full" , wdh )
58
+ printPart ("wd" , trimPath (wdh ))
71
59
}
72
- }()
73
60
74
- wg .Add (1 )
75
- go func () {
76
- defer wg .Done ()
61
+ nowTS := time .Now ()
62
+ printPart ("ts" , nowTS .Format ("15:04:05 01/02/06" ))
77
63
78
- if branch , err := sh .Command ("git" , "branch" , "--show-current" ).Output (); err == nil {
79
- printPart ("git_br" , trim (string (branch )))
64
+ if * flgPreexecTS != 0 {
65
+ cmdTS := time .Unix (int64 (* flgPreexecTS ), 0 )
66
+
67
+ diff := nowTS .Sub (cmdTS )
68
+ printPart ("ds" , diff .Round (time .Second ))
69
+ }
70
+ })
71
+
72
+ //wg.Dispatch(func() {
73
+ // out, err := stringExec("git", "config", "--list")
74
+ // printPart("debug_o", js(out))
75
+ // if err != nil {
76
+ // printPart("debug_e", js(err.Error()))
77
+ // }
78
+ //})
79
+
80
+ wg .Dispatch (func () {
81
+ cwg := new (WaitGroupDispatcher )
82
+ defer cwg .Wait ()
83
+
84
+ if _ , err := stringExec ("git" , "rev-parse" , "--show-toplevel" ); err == nil {
85
+ printPart ("vcs" , "git" )
86
+ } else {
87
+ return
80
88
}
81
- }()
82
89
83
- wg .Add (1 )
84
- go func () {
85
- defer wg .Done ()
90
+ cwg .Dispatch (func () {
91
+ if branch , err := stringExec ("git" , "branch" , "--show-current" ); err == nil {
92
+ printPart ("vcs_br" , trim (string (branch )))
93
+ }
94
+ })
86
95
87
- if status , err := sh .Command ("git" , "status" , "--porcelain" ).Output (); err == nil {
88
- if len (status ) > 0 {
89
- printPart ("git_st" , "dirty" )
90
- } else {
91
- printPart ("git_st" , "clean" )
96
+ cwg .Dispatch (func () {
97
+ if status , err := stringExec ("git" , "status" , "--porcelain" ); err == nil {
98
+ if len (status ) > 0 {
99
+ printPart ("vcs_dirty" , 1 )
100
+ printPart ("vcs_dirty_st" , js (status ))
101
+ } else {
102
+ printPart ("vsc_dirty" , 0 )
103
+ }
92
104
}
105
+ })
106
+ })
107
+
108
+ wg .Dispatch (func () {
109
+ cwg := new (WaitGroupDispatcher )
110
+ defer cwg .Wait ()
111
+
112
+ var stgPatchTop string
113
+ var err error
114
+
115
+ if stgPatchTop , err = stringExec ("stg" , "top" ); err == nil {
116
+ printPart ("stg" , "1" )
117
+ printPart ("stg_top" , stgPatchTop )
118
+ } else {
119
+ return
93
120
}
94
- }()
95
121
96
- wg . Wait ()
97
- return nil
98
- }
122
+ cwg . Dispatch ( func () {
123
+ gitSHA , _ := stringExec ( "stg" , "id" )
124
+ stgSHA , _ := stringExec ( "stg" , "id" , stgPatchTop )
99
125
100
- func trimPathLast (s string , n int ) string {
101
- return s
102
- }
126
+ if gitSHA != stgSHA {
127
+ printPart ("stg_dirty" , 1 )
128
+ } else {
129
+ printPart ("stg_dirty" , 0 )
130
+ }
131
+ })
103
132
104
- func intMax (a , b int ) int {
105
- if a > b {
106
- return a
107
- } else {
108
- return b
109
- }
110
- }
133
+ cwg .Dispatch (func () {
134
+ if stgPatchLen , err := stringExec ("stg" , "series" , "-c" ); err == nil {
135
+ printPart ("stg_qlen" , stgPatchLen )
136
+ }
137
+ })
111
138
112
- func trim (s string ) string {
113
- return strings .Trim (s , "\n \t " )
139
+ cwg .Dispatch (func () {
140
+ if stgPatchPos , err := stringExec ("stg" , "series" , "-cA" ); err == nil {
141
+ printPart ("stg_qpos" , stgPatchPos )
142
+ }
143
+ })
144
+ })
145
+
146
+ return nil
114
147
}
115
148
116
149
func printPart (name string , value interface {}) {
@@ -120,17 +153,79 @@ func printPart(name string, value interface{}) {
120
153
fmt .Printf ("%s\t %v\n " , name , value )
121
154
}
122
155
123
- // PROMPT PARTS:
124
- // (exit-status: if > 0)
125
- // (parent-process)
126
- // (hostname: if remote connection)
127
- // (current-dir-path)
128
- // (vsc-information)
129
- // (timestamp)
156
+ //------------------------------------------------------------------------------
130
157
131
158
func main () {
132
159
err := cmd .ExecuteContext (context .Background ())
133
160
if err != nil {
134
161
panic (err )
135
162
}
136
163
}
164
+
165
+ //------------------------------------------------------------------------------
166
+
167
+ type WaitGroupDispatcher struct {
168
+ wg sync.WaitGroup
169
+ }
170
+
171
+ func (d * WaitGroupDispatcher ) Dispatch (fn func ()) {
172
+ d .wg .Add (1 )
173
+ go func () {
174
+ defer d .wg .Done ()
175
+ fn ()
176
+ }()
177
+ }
178
+
179
+ func (d * WaitGroupDispatcher ) Wait () {
180
+ d .wg .Wait ()
181
+ }
182
+
183
+ func stringExec (path string , args ... string ) (string , error ) {
184
+ out , err := shellout .New (bgctx ,
185
+ shellout .Args (path , args ... ),
186
+ shellout .EnvSet (map [string ]string {
187
+ "GIT_OPTIONAL_LOCKS" : "0" ,
188
+ }),
189
+ ).RunString ()
190
+ return trim (out ), err
191
+ }
192
+
193
+ func js (v interface {}) string {
194
+ b , _ := json .Marshal (v )
195
+ return string (b )
196
+ }
197
+
198
+ func trimPath (s string ) string {
199
+ var out []string
200
+
201
+ parts := strings .Split (s , "/" )
202
+ for i , part := range parts {
203
+ if i == len (parts )- 1 {
204
+ out = append (out , part )
205
+ } else {
206
+ out = append (out , part [0 :intMin (len (part ), 1 )])
207
+ }
208
+ }
209
+
210
+ return strings .Join (out , "/" )
211
+ }
212
+
213
+ func intMax (a , b int ) int {
214
+ if a > b {
215
+ return a
216
+ } else {
217
+ return b
218
+ }
219
+ }
220
+
221
+ func intMin (a , b int ) int {
222
+ if a < b {
223
+ return a
224
+ } else {
225
+ return b
226
+ }
227
+ }
228
+
229
+ func trim (s string ) string {
230
+ return strings .Trim (s , "\n \t " )
231
+ }
0 commit comments