From: Edgar HIPP Date: Sun, 21 Jun 2015 13:33:05 +0000 (+0200) Subject: Initial commit X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;ds=sidebyside;h=f51055449eb750d71d101132fda3467b4d36ab37;p=path-extractor.git Initial commit --- f51055449eb750d71d101132fda3467b4d36ab37 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f008b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +pe +*.txt +demo.gif diff --git a/README.md b/README.md new file mode 100644 index 0000000..67fb3d1 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# PathExtractor (pe) + +![demo](raw.github.com/edi9999/i/master/demo.gif) + +PathExtractor is a command line tool that extracts a list of files/paths from stdin. + +Advantages over [fpp](https://github.com/facebook/PathPicker): + + * It does only one thing : more unixy + * You can use it with any fuzzy finder, such as [fzf](https://github.com/junegunn/fzf),[peco](https://github.com/peco/peco),[percol](https://github.com/mooz/percol),[pick](https://github.com/thoughtbot/pick),[selecta](https://github.com/garybernhardt/selecta/) + * It doesn't wait for stdin to be finished to output the paths + * It is faster + * It is much smaller (easily understandable) + * You can also use it without a fuzzy finder for programmatic usage + +For example, you could write: + + git status | pe + +to get a list of the files that were added/changed, without all the formating + +One of the most common usage is to create an alias that will automatically run : + + `pe` + a command line fuzzy finder such as fzf + an action such as opening that file in your favorite editor. + +For example, using `zsh` , I have as an alias: + + alias -g P='| pe | fzf | read filename; [ ! -z $filename ] && vim $filename' + +With `bash`: + + bind '"PP": "| pe | fzf | read filename; [ ! -z $filename ] && vim $filename"' + +So that If I run + + `git status P` + +or + + `git status PP` + +to quickly open one of the changed files in vim + +Other usage ideas: + +With zsh: + + # Copy selected path to clipboard + alias -g C='| pe | fzf | read filename; [ ! -z $filename ] && echo -n $filename | xclip -selection c' + +With bash: + + bind '"CC": "| pe | fzf | read filename; [ ! -z $filename ] && echo -n $filename | xclip -selection c"' + +# Installation + +``` +git clone # in your go path + +go test + +go build + +go install +``` diff --git a/extractor.go b/extractor.go new file mode 100644 index 0000000..69d4b95 --- /dev/null +++ b/extractor.go @@ -0,0 +1,30 @@ +package main + +import "regexp" + + +func pathExtractor(input string) [][][]byte { + surroundRegex := "[^][ \\t:'\"]" + r := regexp.MustCompile("("+surroundRegex+"*[\\./]"+surroundRegex+"*)") + temp := [][][]byte{} + temp = r.FindAllSubmatch([]byte(input),-1) + return temp +} + +func getAllMatches(input string) []string { + matches := [][][]byte{} + result := []string{} + s := string("") + matches = pathExtractor(input) + for _,match := range matches { + s = string(match[1]) + if isDate(s) || isVersion(s) || isGitRange(s) || isGitInstruction(s) || containsInvalidString(s) || len(s)<=2 { + continue + } + if isGitPath(s) { + s = replaceGitPath(s) + } + result = append(result,s) + } + return result +} diff --git a/pe.go b/pe.go new file mode 100644 index 0000000..a95a385 --- /dev/null +++ b/pe.go @@ -0,0 +1,18 @@ +package main + +import "os" +import "bufio" +import "fmt" + +func main() { + stdin := os.Stdin + if scanner := bufio.NewScanner(stdin); scanner != nil { + for scanner.Scan() { + matches := getAllMatches(scanner.Text()) + for _,match := range matches { + fmt.Println(match) + } + } + } +} + diff --git a/pe_test.go b/pe_test.go new file mode 100644 index 0000000..378e79a --- /dev/null +++ b/pe_test.go @@ -0,0 +1,65 @@ +package main + +import "testing" + +func TestGitIgnore(t *testing.T) { + output:=getAllMatches("?? alt/generateStore.php") + if output[0] != "alt/generateStore.php" { + t.Errorf("Doesnt match files", output[0]) + } + + output=getAllMatches("hello .gitignore") + if output[0] != ".gitignore" { + t.Errorf("Doesnt match hidden files", output[0]) + } + + output=getAllMatches(" mail@mail.com ") + if len(output) != 0 { + t.Errorf("Matches email adresses", output[0]) + } + + output=getAllMatches("v1.2") + if len(output) != 0 { + t.Errorf("Matches version number", output[0]) + } + + output=getAllMatches("obj.slice()") + if len(output) != 0 { + t.Errorf("Matches function call", output[0]) + } + + output=getAllMatches("~/www") + if len(output) == 0 || output[0] != "~/www" { + t.Errorf("Doesnt match home", output[0]) + } + + output=getAllMatches("origin/master") + if len(output) != 0 { + t.Errorf("Matches remote name", output[0]) + } + + output=getAllMatches("john doe (dead on 28/04/2014)") + if len(output) != 0 { + t.Errorf("Matches date", output[0]) + } + + output=getAllMatches("john doe ,dead on 28/04/2014") + if len(output) != 0 { + t.Errorf("Matches date", output[0]) + } + + output=getAllMatches(".gitignore , ~/www") + if len(output) != 2 { + t.Errorf("Doesnt match multi", output[0]) + } + + output=getAllMatches("var/") + if len(output) != 1 { + t.Errorf("Doesnt match dir", output[0]) + } + + output=getAllMatches("//") + if len(output) != 0 { + t.Errorf("Comment matches", output[0]) + } +} diff --git a/validators.go b/validators.go new file mode 100644 index 0000000..60811fc --- /dev/null +++ b/validators.go @@ -0,0 +1,46 @@ +package main + +import "strings" +import "regexp" + +func isGitRange (input string) bool { + r := regexp.MustCompile("[0-9a-f]{3,}\\.\\.[0-9a-f]{3,}") + return r.Match([]byte(input)) +} + +func isGitPath (input string) bool { + r := regexp.MustCompile("^[ab]/") + return r.Match([]byte(input)) +} + +func isDate (input string) bool { + r := regexp.MustCompile("^[0-9]+/[0-9]+/[0-9]+") + return r.Match([]byte(input)) +} + +func isGitInstruction (input string) bool { + r := regexp.MustCompile("\\.{3,}") + return r.Match([]byte(input)) +} + +func replaceGitPath (input string) string { + r := regexp.MustCompile("^[ab]/(.*)") + temp := [][]byte{} + temp = r.FindSubmatch([]byte(input)) + return string(temp[1]) +} + +func isVersion (input string) bool { + r := regexp.MustCompile("[0-9x]\\.[0-9x]{1,2}(\\.[0-9x]{1,3})?") + return r.Match([]byte(input)) +} + +func containsInvalidString (input string) bool { + invalidStrings := []string{"(",")","@","origin/","{","}","<",">","$","*"} + for _,s := range invalidStrings { + if strings.Contains(input,s) { + return true + } + } + return false +}