Loading dclish/completer.go +61 −18 Original line number Diff line number Diff line Loading @@ -41,6 +41,39 @@ func NewCompleter(ct CommandTable) Completer { } } // resolveCmd resolves a possibly-abbreviated command key to its full name. // Returns "" if not found or ambiguous. func (c Completer) resolveCmd(key string) string { upper := strings.ToUpper(key) var match string for _, cmd := range c.commands { if cmd == upper { return upper } if strings.HasPrefix(cmd, upper) { if match != "" { return "" // ambiguous } match = cmd } } return match } // commandWords extracts just the command word(s) from a string, // stopping before any flag (token starting with /). func commandWords(s string) string { parts := strings.Fields(s) result := []string{} for _, p := range parts { if strings.HasPrefix(p, "/") { break } result = append(result, strings.ToUpper(p)) } return strings.Join(result, " ") } // Do return a list of possible completions. func (c Completer) Do(line []rune, pos int) ([][]rune, int) { // Nothing typed in. Loading @@ -58,12 +91,14 @@ func (c Completer) Do(line []rune, pos int) ([][]rune, int) { // Check if the user is typing a flag (input contains a /). if idx := strings.LastIndex(input, "/"); idx >= 0 { // Extract the command part before the flag. cmdPart := strings.TrimSpace(input[:idx]) // Extract the command part before the flag, stripping any earlier // flags so "dir /folders /desc" resolves to "DIRECTORY" not // "DIRECTORY /FOLDERS". cmdPart := commandWords(input[:idx]) flagPart := strings.ToUpper(input[idx:]) // Find matching command for flag lookup. cmdKey := strings.ToUpper(cmdPart) // Resolve abbreviated command then look up its flag table. if cmdKey := c.resolveCmd(cmdPart); cmdKey != "" { if ft, ok := c.flags[cmdKey]; ok { matches := ft.Completions(flagPart) newline := [][]rune{} Loading @@ -78,16 +113,24 @@ func (c Completer) Do(line []rune, pos int) ([][]rune, int) { return newline, pos } } } // Check if the user is typing an argument after a complete command. // Check if the user is typing an argument after a command. if spaceIdx := strings.LastIndex(input, " "); spaceIdx >= 0 { cmdPart := strings.TrimSpace(input[:spaceIdx]) argPart := input[spaceIdx+1:] cmdKey := strings.ToUpper(cmdPart) argUpper := strings.ToUpper(argPart) if completer, ok := c.argCompleters[cmdKey]; ok { choices := completer() // Try direct lookup, then resolve abbreviation. cmdKey := strings.ToUpper(cmdPart) completerFn, ok := c.argCompleters[cmdKey] if !ok { if resolved := c.resolveCmd(cmdKey); resolved != "" { completerFn, ok = c.argCompleters[resolved] } } if ok { choices := completerFn() newline := [][]rune{} for _, choice := range choices { if strings.HasPrefix(strings.ToUpper(choice), argUpper) { Loading security/sandbox_linux.go +2 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ func InitSandbox() error { landlock.RODirs(roDirs...), // Allow outbound HTTPS for SSH FETCH from forges. landlock.ConnectTCP(443), landlock.ConnectTCP(53), landlock.ROFiles("/etc/resolv.conf", "/etc/hosts"), ) if err != nil { return fmt.Errorf("failed to apply landlock sandbox: %w", err) Loading security/sandbox_openbsd.go +3 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ func InitSandbox() error { {"/dev/tty", "rw"}, // Terminfo databases for tcell/readline. {"/usr/share/terminfo", "r"}, // Needed for ssh fetch. {"/etc/resolv.conf", "r"}, {"/etc/hosts", "r"}, } for _, u := range unveils { Loading Loading
dclish/completer.go +61 −18 Original line number Diff line number Diff line Loading @@ -41,6 +41,39 @@ func NewCompleter(ct CommandTable) Completer { } } // resolveCmd resolves a possibly-abbreviated command key to its full name. // Returns "" if not found or ambiguous. func (c Completer) resolveCmd(key string) string { upper := strings.ToUpper(key) var match string for _, cmd := range c.commands { if cmd == upper { return upper } if strings.HasPrefix(cmd, upper) { if match != "" { return "" // ambiguous } match = cmd } } return match } // commandWords extracts just the command word(s) from a string, // stopping before any flag (token starting with /). func commandWords(s string) string { parts := strings.Fields(s) result := []string{} for _, p := range parts { if strings.HasPrefix(p, "/") { break } result = append(result, strings.ToUpper(p)) } return strings.Join(result, " ") } // Do return a list of possible completions. func (c Completer) Do(line []rune, pos int) ([][]rune, int) { // Nothing typed in. Loading @@ -58,12 +91,14 @@ func (c Completer) Do(line []rune, pos int) ([][]rune, int) { // Check if the user is typing a flag (input contains a /). if idx := strings.LastIndex(input, "/"); idx >= 0 { // Extract the command part before the flag. cmdPart := strings.TrimSpace(input[:idx]) // Extract the command part before the flag, stripping any earlier // flags so "dir /folders /desc" resolves to "DIRECTORY" not // "DIRECTORY /FOLDERS". cmdPart := commandWords(input[:idx]) flagPart := strings.ToUpper(input[idx:]) // Find matching command for flag lookup. cmdKey := strings.ToUpper(cmdPart) // Resolve abbreviated command then look up its flag table. if cmdKey := c.resolveCmd(cmdPart); cmdKey != "" { if ft, ok := c.flags[cmdKey]; ok { matches := ft.Completions(flagPart) newline := [][]rune{} Loading @@ -78,16 +113,24 @@ func (c Completer) Do(line []rune, pos int) ([][]rune, int) { return newline, pos } } } // Check if the user is typing an argument after a complete command. // Check if the user is typing an argument after a command. if spaceIdx := strings.LastIndex(input, " "); spaceIdx >= 0 { cmdPart := strings.TrimSpace(input[:spaceIdx]) argPart := input[spaceIdx+1:] cmdKey := strings.ToUpper(cmdPart) argUpper := strings.ToUpper(argPart) if completer, ok := c.argCompleters[cmdKey]; ok { choices := completer() // Try direct lookup, then resolve abbreviation. cmdKey := strings.ToUpper(cmdPart) completerFn, ok := c.argCompleters[cmdKey] if !ok { if resolved := c.resolveCmd(cmdKey); resolved != "" { completerFn, ok = c.argCompleters[resolved] } } if ok { choices := completerFn() newline := [][]rune{} for _, choice := range choices { if strings.HasPrefix(strings.ToUpper(choice), argUpper) { Loading
security/sandbox_linux.go +2 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ func InitSandbox() error { landlock.RODirs(roDirs...), // Allow outbound HTTPS for SSH FETCH from forges. landlock.ConnectTCP(443), landlock.ConnectTCP(53), landlock.ROFiles("/etc/resolv.conf", "/etc/hosts"), ) if err != nil { return fmt.Errorf("failed to apply landlock sandbox: %w", err) Loading
security/sandbox_openbsd.go +3 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,9 @@ func InitSandbox() error { {"/dev/tty", "rw"}, // Terminfo databases for tcell/readline. {"/usr/share/terminfo", "r"}, // Needed for ssh fetch. {"/etc/resolv.conf", "r"}, {"/etc/hosts", "r"}, } for _, u := range unveils { Loading