1. Serge Zaitsev
  2. 2

Commits

Serge A. Zaitsev  committed 5eed8d3

initial commit

  • Participants
  • Branches default

Comments (0)

Files changed (4)

File 2.go

View file
  • Ignore whitespace
+package main
+
+import (
+	"os"
+)
+
+func main() {
+	if len(os.Args) < 2 {
+		os.Exit(1)
+	}
+
+	command := os.Args[1]
+	args := os.Args[2:]
+	paths := LoadPaths()
+
+	switch command {
+	case "add":
+		modified := false
+		for _, path := range args {
+			if paths.add(path) {
+				modified = true
+			}
+		}
+		if modified {
+			paths.save()
+		}
+	case "go":
+		os.Stdout.WriteString(paths.find(args))
+	}
+}

File bashrc

View file
  • Ignore whitespace
+# Absolute path to the `2` binary
+TWO=/home/serge/src/serge/2/2
+
+# hook to add every visited directory to the list
+cd() {
+	builtin cd $@
+	$TWO add .
+}
+
+# alias function for "2 go"
+_2go() {
+	local path
+	[ $# -eq 0 ] && cd && return
+
+	if [ $# -eq 1 -a -d $1 ]; then
+		$TWO add $1
+		cd $1
+		return
+	fi
+	path=$($TWO go $@)
+	[ -z "$path" ] && echo "No matches for '$@'" || builtin cd $path
+}
+alias 2='_2go'
+

File paths.go

View file
  • Ignore whitespace
+package main
+
+import (
+	"bufio"
+	"io"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+const PATHS_FILENAME = ".2paths"
+
+// a storage for all known (visited at least once) directories
+type Paths struct {
+	Dirs []string
+}
+
+// load paths list
+func LoadPaths() (p *Paths) {
+	home := os.Getenv("HOME")
+
+	f, err := os.Open(filepath.Join(home, PATHS_FILENAME))
+	if err != nil {
+		return nil
+	}
+	defer f.Close()
+
+	p = new(Paths)
+	br := bufio.NewReader(f)
+
+	for err == nil {
+		line, _, err := br.ReadLine()
+		if err != nil {
+			break
+		}
+		p.Dirs = append(p.Dirs, string(line))
+	}
+	return
+}
+
+// find the most suitable path to go to
+func (p *Paths) find(hints []string) string {
+	var bestPath string
+	bestWeight := 0
+	if len(hints) == 0 {
+		return ""
+	}
+	for _, path := range p.Dirs {
+		w := 0
+		hintIndex := len(hints) - 1
+		for i := len(path) - 1; i >= 0; i-- {
+			if strings.HasPrefix(path[i:], hints[hintIndex]) {
+				w = w + i + len(hints[hintIndex])
+				if hintIndex == 0 {
+					break
+				}
+				hintIndex = hintIndex - 1
+				i = i - len(hints[hintIndex])
+			}
+		}
+		if w == 0 || hintIndex != 0 {
+			continue
+		}
+		if len(bestPath) == 0 {
+			bestPath = path
+			bestWeight = w
+			continue
+		}
+
+		a := w / len(path)
+		b := bestWeight / len(bestPath)
+		if a > b || (a == b && len(path) <= len(bestPath)) {
+			bestPath = path
+			bestWeight = w
+		}
+	}
+	return bestPath
+}
+
+// add new path to the list
+func (p *Paths) add(path string) bool {
+	if _, err := os.Stat(path); err != nil {
+		return false
+	}
+
+	path, err := filepath.Abs(path)
+	if err != nil {
+		return false
+	}
+	for _, oldPath := range p.Dirs {
+		if oldPath == path {
+			return false
+		}
+	}
+	p.Dirs = append(p.Dirs, path)
+	return true
+}
+
+// save paths list to the file
+func (p *Paths) save() error {
+	home := os.Getenv("HOME")
+
+	f, err := os.Create(filepath.Join(home, PATHS_FILENAME))
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	for _, path := range p.Dirs {
+		if _, err := io.WriteString(f, path+"\n"); err != nil {
+			return err
+		}
+	}
+	return nil
+}

File zshrc

View file
  • Ignore whitespace
+# Absolute path to the `2` binary
+TWO=/home/serge/src/serge/2/2
+
+chpwd() {
+	$TWO add .
+}
+
+_2go() {
+	local path
+	[ $# -eq 0 ] && cd && return
+
+	if [ $# -eq 1 -a -d $1 ]; then
+		$TWO add $1
+		cd $1
+		return
+	fi
+	path=$($TWO go $@)
+	[ -z "$path" ] && echo "No matches for '$@'" || builtin cd $path
+}
+
+_2shell() {
+	echo "interactive shell"
+}
+
+alias 2='_2go'
+