142 lines
2.7 KiB
Go
142 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"io"
|
|
"bufio"
|
|
"path/filepath"
|
|
)
|
|
|
|
func histAdd(histFile string, newPath string) (error) {
|
|
|
|
paths, err := ReadLines(histFile)
|
|
if err != nil {
|
|
if os.IsNotExist(err) != true {
|
|
log.Printf("Error reading cd history file: %v", err)
|
|
}
|
|
}
|
|
file, err := os.OpenFile(histFile, os.O_RDWR|os.O_CREATE, 0660)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|
|
_, 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) 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)
|
|
}
|
|
|
|
var in int
|
|
os.Stderr.WriteString("> ")
|
|
fmt.Scanln(&in)
|
|
if in >= 1 && in <= m {
|
|
path := paths[m - in]
|
|
cd(histFile, "", path)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
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)
|
|
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
|
|
}
|