• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

UiPath / uipathcli / 6442892572

07 Oct 2023 06:45PM UTC coverage: 67.119% (-23.3%) from 90.418%
6442892572

push

github

thschmitt
Upgrade to golang 1.21, update dependencies to latest versions

- Upgrade to golang 1.21
- Update all dependencies to latest versions

3068 of 4571 relevant lines covered (67.12%)

362.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.41
/commandline/autocomplete_handler.go
1
package commandline
2

3
import (
4
        "errors"
5
        "fmt"
6
        "os"
7
        "path/filepath"
8
        "strings"
9

10
        "github.com/urfave/cli/v2"
11
)
12

13
const directoryPermissions = 0755
14
const filePermissions = 0644
15

16
const Powershell = "powershell"
17
const Bash = "bash"
18

19
const completeHandlerEnabledCheck = "uipath_auto_complete"
20

21
const powershellCompleteHandler = `
22
$uipath_auto_complete = {
23
    param($wordToComplete, $commandAst, $cursorPosition)
24
    $padLength = $cursorPosition - $commandAst.Extent.StartOffset
25
    $textToComplete = $commandAst.ToString().PadRight($padLength, ' ').Substring(0, $padLength)
26
    $command, $params = $commandAst.ToString() -split " ", 2
27
    & $command autocomplete complete --command "$textToComplete" | foreach-object {
28
        [system.management.automation.completionresult]::new($_, $_, 'parametervalue', $_)
29
    }
30
}
31
Register-ArgumentCompleter -Native -CommandName uipath -ScriptBlock $uipath_auto_complete
32
`
33

34
const bashCompleteHandler = `
35
function _uipath_auto_complete()
36
{
37
  local executable="${COMP_WORDS[0]}"
38
  local cur="${COMP_WORDS[COMP_CWORD]}" IFS=$'\n'
39
  local candidates
40
  read -d '' -ra candidates < <($executable autocomplete complete --command "${COMP_LINE}" 2>/dev/null)
41
  read -d '' -ra COMPREPLY < <(compgen -W "${candidates[*]:-}" -- "$cur")
42
}
43
complete -f -F _uipath_auto_complete uipath
44
`
45

46
// autoCompleteHandler parses the autocomplete command and provides suggestions for the available commands.
47
// It tries to perform a prefix- as well as contains-match based on the current context.
48
// Example:
49
// uipath autocomplete complete --command "uipath o"
50
// returns:
51
// oms
52
// orchestrator
53
// documentunderstanding
54
type autoCompleteHandler struct {
55
}
56

57
func (a autoCompleteHandler) EnableCompleter(shell string, filePath string) (string, error) {
×
58
        if shell != Powershell && shell != Bash {
×
59
                return "", fmt.Errorf("Invalid shell, supported values: %s, %s", Powershell, Bash)
×
60
        }
×
61

62
        profileFilePath, err := a.profileFilePath(shell, filePath)
×
63
        if err != nil {
×
64
                return "", err
×
65
        }
×
66
        completeHandler := a.completeHandler(shell)
×
67
        return a.enableCompleter(shell, profileFilePath, completeHandlerEnabledCheck, completeHandler)
×
68
}
69

70
func (a autoCompleteHandler) profileFilePath(shell string, filePath string) (string, error) {
×
71
        if filePath != "" {
×
72
                return filePath, nil
×
73
        }
×
74
        if shell == Powershell {
×
75
                return PowershellProfilePath()
×
76
        }
×
77
        return BashrcPath()
×
78
}
79

80
func (a autoCompleteHandler) completeHandler(shell string) string {
×
81
        if shell == Powershell {
×
82
                return powershellCompleteHandler
×
83
        }
×
84
        return bashCompleteHandler
×
85
}
86

87
func (a autoCompleteHandler) enableCompleter(shell string, filePath string, enabledCheck string, completerHandler string) (string, error) {
×
88
        err := a.ensureDirectoryExists(filePath)
×
89
        if err != nil {
×
90
                return "", err
×
91
        }
×
92
        enabled, err := a.completerEnabled(filePath, enabledCheck)
×
93
        if err != nil {
×
94
                return "", err
×
95
        }
×
96
        if enabled {
×
97
                output := fmt.Sprintf("Shell: %s\nProfile: %s\n\nCommand completion is already enabled.", shell, filePath)
×
98
                return output, nil
×
99
        }
×
100
        err = a.writeCompleterHandler(filePath, completerHandler)
×
101
        if err != nil {
×
102
                return "", err
×
103
        }
×
104
        output := fmt.Sprintf("Shell: %s\nProfile: %s\n\nSuccessfully enabled command completion! Restart your shell for the changes to take effect.", shell, filePath)
×
105
        return output, nil
×
106
}
107

108
func (a autoCompleteHandler) ensureDirectoryExists(filePath string) error {
×
109
        err := os.MkdirAll(filepath.Dir(filePath), directoryPermissions)
×
110
        if err != nil {
×
111
                return fmt.Errorf("Error creating profile folder: %w", err)
×
112
        }
×
113
        return nil
×
114
}
115

116
func (a autoCompleteHandler) completerEnabled(filePath string, enabledCheck string) (bool, error) {
×
117
        content, err := os.ReadFile(filePath)
×
118
        if err != nil && errors.Is(err, os.ErrNotExist) {
×
119
                return false, nil
×
120
        }
×
121
        if err != nil {
×
122
                return false, fmt.Errorf("Error reading profile file: %w", err)
×
123
        }
×
124
        return strings.Contains(string(content), enabledCheck), nil
×
125
}
126

127
func (a autoCompleteHandler) writeCompleterHandler(filePath string, completerHandler string) error {
×
128
        file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, filePermissions)
×
129
        if err != nil {
×
130
                return fmt.Errorf("Error opening profile file: %w", err)
×
131
        }
×
132
        defer file.Close()
×
133
        if _, err := file.WriteString(completerHandler); err != nil {
×
134
                return fmt.Errorf("Error writing profile file: %w", err)
×
135
        }
×
136
        return nil
×
137
}
138

139
func (a autoCompleteHandler) Find(commandText string, commands []*cli.Command, exclude []string) []string {
1✔
140
        words := strings.Split(commandText, " ")
1✔
141
        if len(words) < 2 {
1✔
142
                return []string{}
×
143
        }
×
144

145
        command := &cli.Command{
1✔
146
                Name:        "uipath",
1✔
147
                Subcommands: commands,
1✔
148
        }
1✔
149

1✔
150
        for _, word := range words[1 : len(words)-1] {
2✔
151
                if strings.HasPrefix(word, "-") {
1✔
152
                        break
×
153
                }
154
                command = a.findCommand(word, command.Subcommands)
1✔
155
                if command == nil {
1✔
156
                        return []string{}
×
157
                }
×
158
        }
159

160
        lastWord := words[len(words)-1]
1✔
161
        if strings.HasPrefix(lastWord, "-") {
1✔
162
                return a.searchFlags(strings.TrimLeft(lastWord, "-"), command, append(exclude, words...))
×
163
        }
×
164
        return a.searchCommands(lastWord, command.Subcommands, exclude)
1✔
165
}
166

167
func (a autoCompleteHandler) findCommand(name string, commands []*cli.Command) *cli.Command {
1✔
168
        for _, command := range commands {
2✔
169
                if command.Name == name {
2✔
170
                        return command
1✔
171
                }
1✔
172
        }
173
        return nil
×
174
}
175

176
func (a autoCompleteHandler) searchCommands(word string, commands []*cli.Command, exclude []string) []string {
1✔
177
        result := []string{}
1✔
178
        for _, command := range commands {
2✔
179
                if strings.HasPrefix(command.Name, word) {
2✔
180
                        result = append(result, command.Name)
1✔
181
                }
1✔
182
        }
183
        for _, command := range commands {
2✔
184
                if strings.Contains(command.Name, word) {
2✔
185
                        result = append(result, command.Name)
1✔
186
                }
1✔
187
        }
188
        return a.removeDuplicates(a.removeExcluded(result, exclude))
1✔
189
}
190

191
func (a autoCompleteHandler) searchFlags(word string, command *cli.Command, exclude []string) []string {
×
192
        result := []string{}
×
193
        for _, flag := range command.Flags {
×
194
                flagNames := flag.Names()
×
195
                for _, flagName := range flagNames {
×
196
                        if strings.HasPrefix(flagName, word) {
×
197
                                result = append(result, "--"+flagName)
×
198
                        }
×
199
                }
200
        }
201
        for _, flag := range command.Flags {
×
202
                flagNames := flag.Names()
×
203
                for _, flagName := range flagNames {
×
204
                        if strings.Contains(flagName, word) {
×
205
                                result = append(result, "--"+flagName)
×
206
                        }
×
207
                }
208
        }
209
        return a.removeDuplicates(a.removeExcluded(result, exclude))
×
210
}
211

212
func (a autoCompleteHandler) removeDuplicates(values []string) []string {
1✔
213
        keys := make(map[string]bool)
1✔
214
        result := []string{}
1✔
215

1✔
216
        for _, entry := range values {
3✔
217
                if _, value := keys[entry]; !value {
3✔
218
                        keys[entry] = true
1✔
219
                        result = append(result, entry)
1✔
220
                }
1✔
221
        }
222
        return result
1✔
223
}
224

225
func (a autoCompleteHandler) removeExcluded(values []string, exclude []string) []string {
1✔
226
        result := []string{}
1✔
227
        for _, entry := range values {
3✔
228
                if !a.contains(exclude, entry) {
4✔
229
                        result = append(result, entry)
2✔
230
                }
2✔
231
        }
232
        return result
1✔
233
}
234

235
func (a autoCompleteHandler) contains(values []string, value string) bool {
2✔
236
        for _, v := range values {
28✔
237
                if v == value {
26✔
238
                        return true
×
239
                }
×
240
        }
241
        return false
2✔
242
}
243

244
func newAutoCompleteHandler() *autoCompleteHandler {
1✔
245
        return &autoCompleteHandler{}
1✔
246
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc