-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommand.go
More file actions
142 lines (120 loc) · 3.47 KB
/
Copy pathcommand.go
File metadata and controls
142 lines (120 loc) · 3.47 KB
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
package main
import (
"crypto/md5"
"encoding/base64"
"encoding/hex"
"fmt"
"os"
"strings"
)
type TaskCommand struct {
ID string
Label string
Cmd string
Directory string
UseInteractiveShell bool
Status string
ExitCode int
Timestamp string
Env string
}
func (c TaskCommand) String() string {
s := fmt.Sprintf("ID : %s\n", c.ID)
s += fmt.Sprintf("Last Used : %s\n", c.Timestamp)
s += fmt.Sprintf("Label : %s\n", c.Label)
s += fmt.Sprintf("Exec : %s\n", c.Cmd)
s += fmt.Sprintf("Env : %s\n", c.Env)
s += fmt.Sprintf("Directory : %s\n", c.Directory)
s += fmt.Sprintf("Status : %s\n", c.Status)
s += fmt.Sprintf("ExitCode : %d\n", c.ExitCode)
s += fmt.Sprintf("Load Shell Profile : %v\n", c.UseInteractiveShell)
return s
}
// ToBase64 util method to pack the command information into a string
// so we it can be preview in the shell from fzf more easily
func (c TaskCommand) ToBase64() string {
return base64.StdEncoding.EncodeToString([]byte(c.String()))
}
func (c TaskCommand) GetEnv() []string {
var env = make([]string, 0)
for value := range strings.SplitSeq(c.Env, " ") {
value = strings.TrimSpace(value)
env = append(env, value)
}
return env
}
func (c TaskCommand) Edit() (TaskCommand, error) {
// Create a clean structure with config section for editable fields
editData := map[string]any{
"config": map[string]any{
"label": c.Label,
"command": c.Cmd,
"env": c.Env,
"interactive_shell": c.UseInteractiveShell,
},
"_info_": map[string]any{
"_instructions": "Edit the 'config' fields and save to update your command.",
"directory": c.Directory,
"examples": map[string]any{
"label": "deploy-staging",
"command": "make build && ./deploy.sh",
"env": "ENV=staging DEBUG=true",
},
},
}
f, err := os.CreateTemp("", "edit_command_*.json")
if err != nil {
return TaskCommand{}, err
}
defer os.Remove(f.Name())
defer f.Close()
filename := f.Name()
writeJSONFile(filename, editData)
// edit the command in the editor
openEditor(filename)
var result map[string]any
err = readJSONFile(filename, &result)
if err != nil {
return TaskCommand{}, fmt.Errorf("failed to parse edited JSON: %w", err)
}
newCmd := TaskCommand{
ID: c.ID,
Directory: c.Directory,
Status: c.Status,
ExitCode: c.ExitCode,
Timestamp: c.Timestamp,
}
config, ok := result["config"].(map[string]any)
if !ok {
return TaskCommand{}, fmt.Errorf("missing or invalid 'config' section in edited JSON")
}
if val, ok := config["label"].(string); ok {
newCmd.Label = val
}
if val, ok := config["command"].(string); ok {
newCmd.Cmd = val
}
if val, ok := config["env"].(string); ok {
newCmd.Env = val
}
if val, ok := config["interactive_shell"].(bool); ok {
newCmd.UseInteractiveShell = val
}
return newCmd, nil
}
func GenerateID(c TaskCommand) string {
hash := md5.Sum(fmt.Appendf(nil, "%s%s%s", c.Directory, c.Cmd, c.Env))
return hex.EncodeToString(hash[:])
}
func NewCommand(dir, cmdStr, label, env string, interactive bool) TaskCommand {
cmdStr = strings.TrimSpace(cmdStr)
cmd := TaskCommand{
Label: label,
Cmd: cmdStr,
UseInteractiveShell: interactive,
Directory: dir,
Env: env,
}
cmd.ID = GenerateID(cmd)
return cmd
}