diff --git a/cdhist.go b/cdhist.go index dc956bf..7a6fa16 100644 --- a/cdhist.go +++ b/cdhist.go @@ -4,42 +4,107 @@ import ( "fmt" "log" "os" + "strings" "io" "bufio" + "path/filepath" ) -func histAdd(histFile string, path string) (error) { +func histAdd(histFile string, newPath string) (error) { - data, err := ReadLines(histFile) + paths, err := ReadLines(histFile) if err != nil { if os.IsNotExist(err) != true { log.Printf("Error reading cd history file: %v", err) } } - data = append(data, path) file, err := os.OpenFile(histFile, os.O_RDWR|os.O_CREATE, 0660) if err != nil { return err } defer file.Close() - for _, line := range data { - _, err := file.Write([]byte(fmt.Sprintf("%s\n", line))) - if err != nil { - log.Printf("Error writing cd history file: %v", err) - return err + if err := file.Truncate(0); err != nil { + return err + } + if len(paths) == 0 { + path, _ := os.Getwd() + if err == nil { + paths = append(paths, path) + } + } + for _, path := range paths { + if strings.Compare(path, newPath) != 0 { + _, err := file.Write([]byte(fmt.Sprintf("%s\n", path))) + if err != nil { + log.Printf("Error writing cd history file: %v", err) + return err + } } } - return err + _, err = file.Write([]byte(fmt.Sprintf("%s\n", newPath))) + if err != nil { + log.Printf("Error writing cd history file: %v", err) + return err + } + return nil } -func histList(histFile string) { - fmt.Println("List") +func histList(histFile string) error { + paths, err := ReadLines(histFile) + if err != nil { + return err + } + m := len(paths) - 1 + for i := 0; i < m; i++ { + s := fmt.Sprintf("%d: %s\n",m - i, paths[i]) + os.Stderr.WriteString(s) + } - return + var in int + os.Stderr.WriteString("> ") + fmt.Scanln(&in) + if in >= 1 && in <= m { + path := paths[m - in] + cd(histFile, "", path) + } + return nil } -func ReadLines(fileName string) (data []string, err error) { +func sanitizePath(path string) string { + 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 { + log.Printf("No home directory: %s", err) + } + } + + path = strings.TrimSpace(path) + path, err := filepath.Abs(path) + if err != nil { + 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) + 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) @@ -48,7 +113,7 @@ func ReadLines(fileName string) (data []string, err error) { defer file.Close() reader := bufio.NewReader(file) - var paths []string + paths := make([]string,0) for { line, _, err := reader.ReadLine() if err != nil { @@ -63,14 +128,14 @@ func ReadLines(fileName string) (data []string, err error) { } // 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("cdh() { local d; d=$(cdhist-v2 \"$@\"); if [ $? -ne 0 ]; then return 0; fi; builtin cd -- \"$d\"; }") - fmt.Printf(`cdh() { + fmt.Printf(`cd() { local d - d=$(cdhist-v2 "$@") - if [ $? -ne 0 ]; then return 0 + d=$(cdhist "$@") + if [ $? -eq 0 ]; then + builtin cd $d fi - builtin cd -- "$d" }`) return } diff --git a/main.go b/main.go index df9fbf2..2608b27 100644 --- a/main.go +++ b/main.go @@ -2,42 +2,58 @@ package main import ( "os" - // "os/exec" + "flag" "log" "path" - // "syscall" "fmt" ) +// 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 = "" ) func main() { histFileDir, err := os.UserHomeDir() if err != nil { - log.Fatal(err, "Can't find home directory.") + log.Printf("Error reading cd history file: %v", err) } histFile := path.Join(histFileDir, histFile) - if len(os.Args) > 1 && os.Args[1] == "--" { - histList(histFile) - os.Exit(1) - } - - if len(os.Args) > 1 && os.Args[1] == "-i" { - makeBashFunc() + if len(os.Args) == 2 && os.Args[1] == "--" { + if err := histList(histFile); err != nil { + log.Printf("Error reading cd history file: %s", err) + } os.Exit(1) } - if len(os.Args) > 1 { - path := os.Args[1] - histAdd(histFile, path) - fmt.Printf("%s", path) - os.Exit(0) + flagInit := flag.Bool("i", false, "Creates function to be sourced by bash") + flagL := flag.Bool("L", false, "Passed to cd") + flagP := flag.Bool("P", false, "Passed to cd") + flage := flag.Bool("e", false, "Passed to cd") + flagAt := flag.Bool("@", false, "Passed to cd") + flag.Parse() + + switch { + case *flagInit: + makeBashFunc() + os.Exit(1) + case *flagL: + outString = fmt.Sprintf("%s -L", outString) + case *flagP: + outString = fmt.Sprintf("%s -P", outString) + case *flage: + outString = fmt.Sprintf("%s -e", outString) + case *flagAt: + outString = fmt.Sprintf("%s -@", outString) } + path := flag.Arg(0) + cd(histFile, outString, path) return }