summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorGrail Finder <wohilas@gmail.com>2026-03-14 11:06:18 +0300
committerGrail Finder <wohilas@gmail.com>2026-03-14 11:06:18 +0300
commit92acfb7ed4cda8e93909eadb54863012eac45128 (patch)
tree937d2104bfbc32d0683d0d3b90533d6828e32120 /tools
parent2901208c800742cb7b5980e7e203655bf7dee4b4 (diff)
Feat: run sed
Diffstat (limited to 'tools')
-rw-r--r--tools/chain.go12
-rw-r--r--tools/fs.go74
2 files changed, 86 insertions, 0 deletions
diff --git a/tools/chain.go b/tools/chain.go
index fb7767e..73ab6cd 100644
--- a/tools/chain.go
+++ b/tools/chain.go
@@ -266,6 +266,18 @@ func execBuiltin(name string, args []string, stdin string) string {
}
fsRootDir = abs
return fmt.Sprintf("Changed directory to: %s", fsRootDir)
+ case "go":
+ // Allow all go subcommands
+ if len(args) == 0 {
+ return "[error] usage: go <subcommand> [options]"
+ }
+ cmd := exec.Command("go", args...)
+ cmd.Dir = fsRootDir
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return fmt.Sprintf("[error] go %s: %v\n%s", args[0], err, string(output))
+ }
+ return string(output)
}
return ""
}
diff --git a/tools/fs.go b/tools/fs.go
index 50b8da2..9fc09bb 100644
--- a/tools/fs.go
+++ b/tools/fs.go
@@ -614,6 +614,80 @@ func FsCd(args []string, stdin string) string {
return fmt.Sprintf("Changed directory to: %s", fsRootDir)
}
+func FsSed(args []string, stdin string) string {
+ if len(args) == 0 {
+ return "[error] usage: sed 's/old/new/[g]' [file]"
+ }
+
+ inPlace := false
+ var filePath string
+ var pattern string
+
+ for _, a := range args {
+ if a == "-i" || a == "--in-place" {
+ inPlace = true
+ } else if strings.HasPrefix(a, "s") && len(a) > 1 {
+ // This looks like a sed pattern
+ pattern = a
+ } else if filePath == "" && !strings.HasPrefix(a, "-") {
+ filePath = a
+ }
+ }
+
+ if pattern == "" {
+ return "[error] usage: sed 's/old/new/[g]' [file]"
+ }
+
+ // Parse pattern: s/old/new/flags
+ parts := strings.Split(pattern[1:], "/")
+ if len(parts) < 2 {
+ return "[error] invalid sed pattern. Use: s/old/new/[g]"
+ }
+
+ oldStr := parts[0]
+ newStr := parts[1]
+ global := len(parts) >= 3 && strings.Contains(parts[2], "g")
+
+ var content string
+ if filePath != "" && stdin == "" {
+ // Read from file
+ abs, err := resolvePath(filePath)
+ if err != nil {
+ return fmt.Sprintf("[error] sed: %v", err)
+ }
+ data, err := os.ReadFile(abs)
+ if err != nil {
+ return fmt.Sprintf("[error] sed: %v", err)
+ }
+ content = string(data)
+ } else if stdin != "" {
+ // Use stdin
+ content = stdin
+ } else {
+ return "[error] sed: no input (use file path or pipe from stdin)"
+ }
+
+ // Apply sed replacement
+ if global {
+ content = strings.ReplaceAll(content, oldStr, newStr)
+ } else {
+ content = strings.Replace(content, oldStr, newStr, 1)
+ }
+
+ if inPlace && filePath != "" {
+ abs, err := resolvePath(filePath)
+ if err != nil {
+ return fmt.Sprintf("[error] sed: %v", err)
+ }
+ if err := os.WriteFile(abs, []byte(content), 0644); err != nil {
+ return fmt.Sprintf("[error] sed: %v", err)
+ }
+ return fmt.Sprintf("Modified %s", filePath)
+ }
+
+ return content
+}
+
func FsMemory(args []string, stdin string) string {
if len(args) == 0 {
return "[error] usage: memory store <topic> <data> | memory get <topic> | memory list | memory forget <topic>"