From bbafd7788fc163114c02e025aaa6735aa027a6e0 Mon Sep 17 00:00:00 2001 From: Bryan Date: Wed, 20 Sep 2023 07:55:38 -0600 Subject: [PATCH] Refactor, add alias file support --- cdhist.go | 149 ++++++++++++++++++++++++++++++++++++----------------- dir/dir.go | 36 +++++++++++++ dir/go.mod | 3 ++ go.mod | 4 ++ main.go | 27 +++++++--- 5 files changed, 165 insertions(+), 54 deletions(-) create mode 100644 dir/dir.go create mode 100644 dir/go.mod diff --git a/cdhist.go b/cdhist.go index 7a6fa16..d24053b 100644 --- a/cdhist.go +++ b/cdhist.go @@ -1,13 +1,16 @@ package main import ( +// "os/exec" "fmt" "log" "os" "strings" "io" "bufio" - "path/filepath" +// "path/filepath" + "text/template" + "cdhist/dir" ) func histAdd(histFile string, newPath string) (error) { @@ -66,11 +69,93 @@ func histList(histFile string) error { fmt.Scanln(&in) if in >= 1 && in <= m { path := paths[m - in] - cd(histFile, "", path) + cd(histFile, aliasFile, "", path) } return nil } +func DirAliases(aliasFile string) map[string]string { + d, err := ReadLines(aliasFile) + if err != nil { + log.Printf("Error reading cd alias file: %s", err) + } + aliases := make(map[string]string) + for _, line := range d { + l := strings.Split(line, "=") + if len(l) == 2 { + aliases[strings.TrimSpace(l[0])] = strings.TrimSpace(l[1]) + } + } + return aliases +} + +func cd(histFile, aliasFile, outString, path string) { + cleanPath, err := dir.Sanitize(path) + if ! dir.Exist(cleanPath) { + a := DirAliases(aliasFile) + p, prs := a[path] + if prs { + cleanPath, err = dir.Sanitize(p) + } + } + if err != nil { + log.Printf("%s: %s", path, err) + os.Exit(2) + } + histAdd(histFile, cleanPath) + fmt.Printf("%s %s", outString, cleanPath) + os.Exit(0) +} + +func ReadLines(fileName string) ([]string, error) { + file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0660) + if err != nil { + // log.Print(err) + return nil, err + } + defer file.Close() + + reader := bufio.NewReader(file) + lines := make([]string,0) + for { + line, _, err := reader.ReadLine() + if err != nil { + if err == io.EOF { + err = nil + } + break + } + lines = append(lines, string(line)) + } + return lines, err +} + + + +// makeBashFunc prints the wrapper function to be sourced by bash +// Copied from https://github.com/bulletmark/cdhist/blob/master/cdhist/cdhist.py +func printBashFunc(opts BashFuncOpts) { + f := `{{.FuncName}}() { + local d + d=$({{.Command}} "$@") + if [ $? -eq 0 ]; then + builtin cd $d + fi + }` + t, err := template.New("t").Parse(f) + if err != nil { + log.Printf("Error parsing template, %s", err) + os.Exit(2) + } + err = t.Execute(os.Stderr, opts) + if err != nil { + log.Printf("Error executing template, %s", err) + os.Exit(2) + } + return +} + +/* func sanitizePath(path string) string { switch path { case "-": @@ -89,53 +174,23 @@ func sanitizePath(path string) string { log.Printf("Invalid path:, %s", err) os.Exit(2) } - if s, err := os.Stat(path); os.IsNotExist(err) { - log.Printf("%s: No such directory. %v", path, s) + if _, err := os.Stat(path); os.IsNotExist(err) { + log.Printf("%s: No such directory.", path) + log.Printf("%v", DirAliases(aliasFile)) os.Exit(2) } return path -} +}*/ -func cd(histFile, outString, path string) { - path = sanitizePath(path) - histAdd(histFile, path) - fmt.Printf("%s %s", outString, path) - os.Exit(0) -} - -func ReadLines(fileName string) ([]string, error) { - file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0660) - if err != nil { - // log.Print(err) - return nil, err - } - defer file.Close() - - reader := bufio.NewReader(file) - paths := make([]string,0) - for { - line, _, err := reader.ReadLine() - if err != nil { - if err == io.EOF { - err = nil - } - break - } - paths = append(paths, string(line)) - } - return paths, err -} - -// makeBashFunc prints the wrapper function to be sourced by bash -// Copied from https://github.com/bulletmark/cdhist/blob/master/cdhist/cdhist.py -func makeBashFunc() { - fmt.Printf(`cd() { - local d - d=$(cdhist "$@") - if [ $? -eq 0 ]; then - builtin cd $d - fi - }`) - return -} +// func cdableVars() bool { +// v := exec.Command("bash", "-i", "-c", "echo $var") +// o, _ := v.Output() +// os.Stderr.WriteString(string(o)) +// +// c := exec.Command("bash", "-i", "-c", "shopt cdable_vars") +// out, _ := c.Output() +// os.Stderr.WriteString(string(out)) +// +// return strings.Contains(string(out), "on") +// } diff --git a/dir/dir.go b/dir/dir.go new file mode 100644 index 0000000..edd06ae --- /dev/null +++ b/dir/dir.go @@ -0,0 +1,36 @@ +package dir + +import ( + "os" +// "errors" + "path/filepath" + "strings" +) + +func Exist(path string) bool { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false + } + return true +} + +func Sanitize(path string) (string, error) { + switch path { + case "-": + path = os.Getenv("OLDPWD") + case "": + var err error // need to do this because the next line won't work using := + path, err = os.UserHomeDir() + if err != nil { + return "", err + } + } + + path = strings.TrimSpace(path) + path, err := filepath.Abs(path) + if err != nil { + return "", err + } + return path, nil +} + diff --git a/dir/go.mod b/dir/go.mod new file mode 100644 index 0000000..cd3a044 --- /dev/null +++ b/dir/go.mod @@ -0,0 +1,3 @@ +module cdhist/dir + +go 1.20 diff --git a/go.mod b/go.mod index ae48c2b..92e03c8 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,7 @@ module projects/cdhist go 1.20 + +replace cdhist/dir => ./dir + +require cdhist/dir v0.0.0-00010101000000-000000000000 diff --git a/main.go b/main.go index 2608b27..e5555a8 100644 --- a/main.go +++ b/main.go @@ -6,23 +6,32 @@ import ( "log" "path" "fmt" +// "cdhist/dir" ) // must run the following to source the cd bash function // if type cdhist &>/dev/null; then . <(cdhist -i); fi var ( - histFile string = ".cd_history" - outString string = "" + histFile string = ".cd_history" + aliasFile string = ".cd_aliases" + outString string = "" ) -func main() { +type BashFuncOpts struct { + Command string + FuncName string +} - histFileDir, err := os.UserHomeDir() +func main() { +// cdableVars() + + dir, err := os.UserHomeDir() if err != nil { log.Printf("Error reading cd history file: %v", err) } - histFile := path.Join(histFileDir, histFile) + histFile = path.Join(dir, histFile) + aliasFile = path.Join(dir, aliasFile) if len(os.Args) == 2 && os.Args[1] == "--" { if err := histList(histFile); err != nil { @@ -40,7 +49,11 @@ func main() { switch { case *flagInit: - makeBashFunc() + name := "cd" + if flag.Arg(0) != "" { + name = flag.Arg(0) + } + printBashFunc(BashFuncOpts{FuncName: name, Command: os.Args[0]}) os.Exit(1) case *flagL: outString = fmt.Sprintf("%s -L", outString) @@ -53,7 +66,7 @@ func main() { } path := flag.Arg(0) - cd(histFile, outString, path) + cd(histFile, aliasFile, outString, path) return }