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

UiPath / uipathcli / 11216909938

07 Oct 2024 01:45PM UTC coverage: 90.416% (-0.03%) from 90.447%
11216909938

push

github

web-flow
Merge pull request #123 from UiPath/feature/command-builder

Create command abstraction and split up command builder

460 of 475 new or added lines in 8 files covered. (96.84%)

1 existing line in 1 file now uncovered.

4264 of 4716 relevant lines covered (90.42%)

1.02 hits per line

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

80.43
/commandline/autocomplete_handler.go
1
package commandline
2

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

11
const AutocompletePowershell = "powershell"
12
const AutocompleteBash = "bash"
13

14
const directoryPermissions = 0755
15
const filePermissions = 0644
16

17
const completeHandlerEnabledCheck = "uipath_auto_complete"
18

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

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

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

55
func (a autoCompleteHandler) EnableCompleter(shell string, filePath string) (string, error) {
1✔
56
        if shell != AutocompletePowershell && shell != AutocompleteBash {
2✔
57
                return "", fmt.Errorf("Invalid shell, supported values: %s, %s", AutocompletePowershell, AutocompleteBash)
1✔
58
        }
1✔
59

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

68
func (a autoCompleteHandler) profileFilePath(shell string, filePath string) (string, error) {
1✔
69
        if filePath != "" {
2✔
70
                return filePath, nil
1✔
71
        }
1✔
NEW
72
        if shell == AutocompletePowershell {
×
73
                return PowershellProfilePath()
×
74
        }
×
75
        return BashrcPath()
×
76
}
77

78
func (a autoCompleteHandler) completeHandler(shell string) string {
1✔
79
        if shell == AutocompletePowershell {
2✔
80
                return powershellCompleteHandler
1✔
81
        }
1✔
82
        return bashCompleteHandler
1✔
83
}
84

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

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

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

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

137
func (a autoCompleteHandler) Find(commandText string, command *CommandDefinition, exclude []string) []string {
1✔
138
        words := strings.Split(commandText, " ")
1✔
139
        if len(words) < 2 {
1✔
140
                return []string{}
×
141
        }
×
142

143
        for _, word := range words[1 : len(words)-1] {
2✔
144
                if strings.HasPrefix(word, "-") {
2✔
145
                        break
1✔
146
                }
147
                command = a.findCommand(word, command.Subcommands)
1✔
148
                if command == nil {
1✔
149
                        return []string{}
×
150
                }
×
151
        }
152

153
        lastWord := words[len(words)-1]
1✔
154
        if strings.HasPrefix(lastWord, "-") {
2✔
155
                return a.searchFlags(strings.TrimLeft(lastWord, "-"), command, append(exclude, words...))
1✔
156
        }
1✔
157
        return a.searchCommands(lastWord, command.Subcommands, exclude)
1✔
158
}
159

160
func (a autoCompleteHandler) findCommand(name string, commands []*CommandDefinition) *CommandDefinition {
1✔
161
        for _, command := range commands {
2✔
162
                if command.Name == name {
2✔
163
                        return command
1✔
164
                }
1✔
165
        }
166
        return nil
×
167
}
168

169
func (a autoCompleteHandler) searchCommands(word string, commands []*CommandDefinition, exclude []string) []string {
1✔
170
        result := []string{}
1✔
171
        for _, command := range commands {
2✔
172
                if strings.HasPrefix(command.Name, word) {
2✔
173
                        result = append(result, command.Name)
1✔
174
                }
1✔
175
        }
176
        for _, command := range commands {
2✔
177
                if strings.Contains(command.Name, word) {
2✔
178
                        result = append(result, command.Name)
1✔
179
                }
1✔
180
        }
181
        return a.removeDuplicates(a.removeExcluded(result, exclude))
1✔
182
}
183

184
func (a autoCompleteHandler) searchFlags(word string, command *CommandDefinition, exclude []string) []string {
1✔
185
        result := []string{}
1✔
186
        for _, flag := range command.Flags {
2✔
187
                if strings.HasPrefix(flag.Name, word) {
2✔
188
                        result = append(result, "--"+flag.Name)
1✔
189
                }
1✔
190
        }
191
        for _, flag := range command.Flags {
2✔
192
                if strings.Contains(flag.Name, word) {
2✔
193
                        result = append(result, "--"+flag.Name)
1✔
194
                }
1✔
195
        }
196
        return a.removeDuplicates(a.removeExcluded(result, exclude))
1✔
197
}
198

199
func (a autoCompleteHandler) removeDuplicates(values []string) []string {
1✔
200
        keys := make(map[string]bool)
1✔
201
        result := []string{}
1✔
202

1✔
203
        for _, entry := range values {
2✔
204
                if _, value := keys[entry]; !value {
2✔
205
                        keys[entry] = true
1✔
206
                        result = append(result, entry)
1✔
207
                }
1✔
208
        }
209
        return result
1✔
210
}
211

212
func (a autoCompleteHandler) removeExcluded(values []string, exclude []string) []string {
1✔
213
        result := []string{}
1✔
214
        for _, entry := range values {
2✔
215
                if !a.contains(exclude, entry) {
2✔
216
                        result = append(result, entry)
1✔
217
                }
1✔
218
        }
219
        return result
1✔
220
}
221

222
func (a autoCompleteHandler) contains(values []string, value string) bool {
1✔
223
        for _, v := range values {
2✔
224
                if v == value {
2✔
225
                        return true
1✔
226
                }
1✔
227
        }
228
        return false
1✔
229
}
230

231
func newAutoCompleteHandler() *autoCompleteHandler {
1✔
232
        return &autoCompleteHandler{}
1✔
233
}
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

© 2025 Coveralls, Inc