summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Häggqvist <[email protected]>2016-02-02 03:13:47 +0100
committerVictor Häggqvist <[email protected]>2016-02-02 03:13:47 +0100
commit91548853b7163a9744dda4c75c062fe6eb57be4d (patch)
tree431d871da19d5a25410195c9bbf0554a794e84b2
init
-rw-r--r--Godeps/Godeps.json20
-rw-r--r--Godeps/Readme5
-rw-r--r--README.md39
-rw-r--r--config.ini.default3
-rw-r--r--goboom.go196
-rwxr-xr-xgoboom_run2
-rwxr-xr-xgoboom_run_debug2
7 files changed, 267 insertions, 0 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
new file mode 100644
index 0000000..7a10d89
--- /dev/null
+++ b/Godeps/Godeps.json
@@ -0,0 +1,20 @@
+{
+ "ImportPath": "snilius.com/goboom",
+ "GoVersion": "go1.5.3",
+ "Deps": [
+ {
+ "ImportPath": "github.com/go-ini/ini",
+ "Comment": "v1.8.6",
+ "Rev": "afbd495e5aaea13597b5e14fe514ddeaa4d76fc3"
+ },
+ {
+ "ImportPath": "github.com/gocarina/gocsv",
+ "Rev": "c9648aef1bdc65989a5db138c92442e3b1370ecc"
+ },
+ {
+ "ImportPath": "github.com/ogier/pflag",
+ "Comment": "v0.0.1-7-g45c278a",
+ "Rev": "45c278ab3607870051a2ea9040bb85fcb8557481"
+ }
+ ]
+}
diff --git a/Godeps/Readme b/Godeps/Readme
new file mode 100644
index 0000000..4cdaa53
--- /dev/null
+++ b/Godeps/Readme
@@ -0,0 +1,5 @@
+This directory tree is generated automatically by godep.
+
+Please do not edit.
+
+See https://github.com/tools/godep for more information.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c937601
--- /dev/null
+++ b/README.md
@@ -0,0 +1,39 @@
+# goboom
+goboom is wrapper around the dmenu. goboom is the successor and rewrite of xboomx in Go.
+
+goboom sorts commands to launch according to their launch frequency.
+In other words - if you launch Chromium and KeePassX all the time - they will appear in the list of commands first.
+
+## Building
+goboom is build using Go 1.5 vendoring and godeps.
+
+ export GO15VENDOREXPERIMENT=1
+ godep get github.com/victorhaggqvist/goboom
+ go build goboom.go
+
+## Install
+
+```sh
+sudo cp goboom /usr/bin
+sudo cp goboom_run /usr/bin
+mkdir -p ~/.goboom
+cp config.ini.default ~/.goboom/config.ini
+```
+
+### Migration from xboomx
+goboom will look for a config file in `~/.goboom`.
+You will need to will need to convert you old config file to ini-format and name it `config.ini`, see the bundeled default ini-file for guidence.
+
+goboom uses a csv-file instead sqlite as datastore. You will need to export your xboomx db as so. At this point there is not a provided tool to do so, but you can easely export it with something like [sqlitebrowser](http://sqlitebrowser.org/).
+
+The contents of your exported database should look along the lines of this.
+
+ name,count
+ chroimum,13
+ keepassx,17
+ gimp,4
+
+
+## License
+
+GPL v3
diff --git a/config.ini.default b/config.ini.default
new file mode 100644
index 0000000..e00c592
--- /dev/null
+++ b/config.ini.default
@@ -0,0 +1,3 @@
+dmenu_params = -b -i -nb black -nf orange -sb black -p ">"
+ignore = X,su
+
diff --git a/goboom.go b/goboom.go
new file mode 100644
index 0000000..1948534
--- /dev/null
+++ b/goboom.go
@@ -0,0 +1,196 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/user"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+
+ "github.com/go-ini/ini"
+ "github.com/gocarina/gocsv"
+ flag "github.com/ogier/pflag"
+)
+
+const version = 0
+
+type Runnable struct {
+ Cmd string `csv:"name"`
+ Count int `csv:"count"`
+}
+
+type Config struct {
+ DmenuParams string
+ Ignore []string `delim:","`
+}
+
+type CmdList []*Runnable
+
+func (c CmdList) Len() int {
+ return len(c)
+}
+
+func (c CmdList) Swap(i, j int) {
+ c[i], c[j] = c[j], c[i]
+}
+
+func (c CmdList) Less(i, j int) bool {
+ return c[i].Count > c[j].Count
+}
+
+var (
+ prePhase bool
+ postPhase bool
+ launcher bool
+ dbFilePath string
+ config Config
+)
+
+func isInIgnoreList(item string) bool {
+ for _, i := range config.Ignore {
+ if i == item {
+ return true
+ }
+ }
+ return false
+}
+
+func addIfNotContains(items []string, item string) []string {
+ for _, i := range items {
+ if i == item {
+ return items
+ }
+ }
+ return append(items, item)
+}
+
+func openDB() map[string]int {
+ list := CmdList{}
+ file, _ := os.Open(dbFilePath)
+ if err := gocsv.UnmarshalFile(file, &list); err != nil {
+ panic(err)
+ }
+
+ itemSet := make(map[string]int)
+ for _, item := range list {
+ itemSet[item.Cmd] = item.Count
+ }
+ return itemSet
+}
+
+func generatePath() []string {
+ sysPath := os.Getenv("PATH")
+ paths := strings.Split(sysPath, ":")
+
+ pathItems := sort.StringSlice{}
+
+ for _, p := range paths {
+ if _, err := os.Stat(p); err == nil {
+ files, _ := ioutil.ReadDir(p)
+ for _, f := range files {
+ if !isInIgnoreList(f.Name()) {
+ pathItems = addIfNotContains(pathItems, f.Name())
+ }
+ }
+ }
+ }
+
+ sort.Sort(pathItems)
+ return pathItems
+}
+
+func rankPath(pathItems []string) CmdList {
+ itemSet := openDB()
+
+ rankedItems := CmdList{}
+ for _, item := range pathItems {
+ count, exists := itemSet[item]
+ if !exists {
+ count = 0
+ }
+ rankedItems = append(rankedItems, &Runnable{item, count})
+ }
+
+ sort.Sort(rankedItems)
+ return rankedItems
+}
+
+func loadIni() {
+ usr, _ := user.Current()
+ configPath := filepath.Join(usr.HomeDir, ".goboom")
+ iniFile := filepath.Join(configPath, "config.ini")
+ dbFilePath = filepath.Join(configPath, "rankdb.csv")
+
+ if _, err := os.Stat(configPath); err != nil {
+ err := os.Mkdir(configPath, os.ModePerm)
+ if err != nil {
+ fmt.Println("failed to create config dir")
+ }
+ }
+
+ config = Config{}
+ if err := ini.MapToWithMapper(&config, ini.TitleUnderscore, iniFile); err != nil {
+ panic(err)
+ }
+}
+
+func updateRank(runnable string) {
+ itemSet := openDB()
+
+ count, exists := itemSet[runnable]
+ if !exists {
+ itemSet[runnable] = 1
+ } else {
+ itemSet[runnable] = count + 1
+ }
+
+ writeDB(itemSet)
+}
+
+func writeDB(itemSet map[string]int) {
+ items := CmdList{}
+ for runnable, count := range itemSet {
+ items = append(items, &Runnable{runnable, count})
+ }
+
+ file, err := os.OpenFile(dbFilePath, os.O_RDWR|os.O_CREATE, os.ModePerm)
+ if err != nil {
+ panic(err)
+ }
+ if err = gocsv.MarshalFile(&items, file); err != nil {
+ panic(err)
+ }
+}
+
+func main() {
+ flag.BoolVar(&prePhase, "pre", false, "Generate dmenu in")
+ flag.BoolVar(&launcher, "launcher", false, "Output launcher command")
+ flag.BoolVar(&postPhase, "post", false, "Update ranking DB")
+ flag.Parse()
+
+ loadIni()
+
+ if prePhase {
+ pathList := generatePath()
+ sortedList := rankPath(pathList)
+ for _, item := range sortedList {
+ fmt.Println(item.Cmd)
+ }
+ } else if postPhase {
+ scanner := bufio.NewScanner(os.Stdin)
+ scanner.Scan()
+ input := scanner.Text()
+ updateRank(input)
+ fmt.Print(input)
+ } else if launcher {
+ fmt.Print("dmenu " + config.DmenuParams)
+ } else {
+ fmt.Printf("goboom v%d (%s/%s/%s)\n", version, runtime.GOOS, runtime.GOARCH, runtime.Version())
+ fmt.Println("\nTo actually use goboom execute goboom_run\n")
+ flag.Usage()
+ }
+}
diff --git a/goboom_run b/goboom_run
new file mode 100755
index 0000000..6958843
--- /dev/null
+++ b/goboom_run
@@ -0,0 +1,2 @@
+#!/bin/sh
+goboom --pre | eval $(goboom --launcher) | goboom --post | xargs -I {} sh -c 'exec {} &'
diff --git a/goboom_run_debug b/goboom_run_debug
new file mode 100755
index 0000000..b5bad4f
--- /dev/null
+++ b/goboom_run_debug
@@ -0,0 +1,2 @@
+#!/bin/sh
+./goboom --pre | eval $(./goboom --launcher) | ./goboom --post | xargs -I {} sh -c 'exec {} &'