Refactor, add alias file support

master
Bryan 2023-09-20 07:55:38 -06:00
parent 82dfdf8df8
commit bbafd7788f
5 changed files with 165 additions and 54 deletions

149
cdhist.go
View File

@ -1,13 +1,16 @@
package main package main
import ( import (
// "os/exec"
"fmt" "fmt"
"log" "log"
"os" "os"
"strings" "strings"
"io" "io"
"bufio" "bufio"
"path/filepath" // "path/filepath"
"text/template"
"cdhist/dir"
) )
func histAdd(histFile string, newPath string) (error) { func histAdd(histFile string, newPath string) (error) {
@ -66,11 +69,93 @@ func histList(histFile string) error {
fmt.Scanln(&in) fmt.Scanln(&in)
if in >= 1 && in <= m { if in >= 1 && in <= m {
path := paths[m - in] path := paths[m - in]
cd(histFile, "", path) cd(histFile, aliasFile, "", path)
} }
return nil 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 { func sanitizePath(path string) string {
switch path { switch path {
case "-": case "-":
@ -89,53 +174,23 @@ func sanitizePath(path string) string {
log.Printf("Invalid path:, %s", err) log.Printf("Invalid path:, %s", err)
os.Exit(2) os.Exit(2)
} }
if s, err := os.Stat(path); os.IsNotExist(err) { if _, err := os.Stat(path); os.IsNotExist(err) {
log.Printf("%s: No such directory. %v", path, s) log.Printf("%s: No such directory.", path)
log.Printf("%v", DirAliases(aliasFile))
os.Exit(2) os.Exit(2)
} }
return path return path
} }*/
func cd(histFile, outString, path string) { // func cdableVars() bool {
path = sanitizePath(path) // v := exec.Command("bash", "-i", "-c", "echo $var")
histAdd(histFile, path) // o, _ := v.Output()
fmt.Printf("%s %s", outString, path) // os.Stderr.WriteString(string(o))
os.Exit(0) //
} // c := exec.Command("bash", "-i", "-c", "shopt cdable_vars")
// out, _ := c.Output()
func ReadLines(fileName string) ([]string, error) { // os.Stderr.WriteString(string(out))
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0660) //
if err != nil { // return strings.Contains(string(out), "on")
// 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
}

36
dir/dir.go Normal file
View File

@ -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
}

3
dir/go.mod Normal file
View File

@ -0,0 +1,3 @@
module cdhist/dir
go 1.20

4
go.mod
View File

@ -1,3 +1,7 @@
module projects/cdhist module projects/cdhist
go 1.20 go 1.20
replace cdhist/dir => ./dir
require cdhist/dir v0.0.0-00010101000000-000000000000

27
main.go
View File

@ -6,23 +6,32 @@ import (
"log" "log"
"path" "path"
"fmt" "fmt"
// "cdhist/dir"
) )
// must run the following to source the cd bash function // must run the following to source the cd bash function
// if type cdhist &>/dev/null; then . <(cdhist -i); fi // if type cdhist &>/dev/null; then . <(cdhist -i); fi
var ( var (
histFile string = ".cd_history" histFile string = ".cd_history"
outString string = "" 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 { if err != nil {
log.Printf("Error reading cd history file: %v", err) 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 len(os.Args) == 2 && os.Args[1] == "--" {
if err := histList(histFile); err != nil { if err := histList(histFile); err != nil {
@ -40,7 +49,11 @@ func main() {
switch { switch {
case *flagInit: case *flagInit:
makeBashFunc() name := "cd"
if flag.Arg(0) != "" {
name = flag.Arg(0)
}
printBashFunc(BashFuncOpts{FuncName: name, Command: os.Args[0]})
os.Exit(1) os.Exit(1)
case *flagL: case *flagL:
outString = fmt.Sprintf("%s -L", outString) outString = fmt.Sprintf("%s -L", outString)
@ -53,7 +66,7 @@ func main() {
} }
path := flag.Arg(0) path := flag.Arg(0)
cd(histFile, outString, path) cd(histFile, aliasFile, outString, path)
return return
} }