diff options
Diffstat (limited to 'home/fast-p')
| -rw-r--r-- | home/fast-p/README.md | 5 | ||||
| -rw-r--r-- | home/fast-p/flake.lock | 27 | ||||
| -rw-r--r-- | home/fast-p/flake.nix | 49 | ||||
| -rw-r--r-- | home/fast-p/go.mod | 11 | ||||
| -rw-r--r-- | home/fast-p/go.sum | 10 | ||||
| -rw-r--r-- | home/fast-p/main.go | 147 | ||||
| l--------- | home/fast-p/result | 1 |
7 files changed, 250 insertions, 0 deletions
diff --git a/home/fast-p/README.md b/home/fast-p/README.md new file mode 100644 index 0000000..344c387 --- /dev/null +++ b/home/fast-p/README.md @@ -0,0 +1,5 @@ +Should be run as nushell function + +def p [] { +^fd -e pdf | ^fast-p | ^fzf --read0 --reverse -e -d "\t" --preview-window "down:80%" --preview 'v=$(echo {q} | tr " " "|"); echo -e {1}"\n"{2} | grep -E "^|$v" -i --color=always;' | ^cut -z -f 1 -d "\t" | ^tr -d '\n' | ^xargs -r --null xdg-open > /dev/null err> /dev/null +} diff --git a/home/fast-p/flake.lock b/home/fast-p/flake.lock new file mode 100644 index 0000000..08c2bc9 --- /dev/null +++ b/home/fast-p/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1764677808, + "narHash": "sha256-H3lC7knbXOBrHI9hITQ7modLuX20mYJVhZORL5ioms0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1aab89277eb2d87823d5b69bae631a2496cff57a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/home/fast-p/flake.nix b/home/fast-p/flake.nix new file mode 100644 index 0000000..f12cd44 --- /dev/null +++ b/home/fast-p/flake.nix @@ -0,0 +1,49 @@ +{ + description = "A Nix flake for building the fast-p Go binary"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + }; + + outputs = + { self, nixpkgs }: + let + # Support multiple systems + supportedSystems = [ + "x86_64-linux" + "aarch64-linux" + ]; + + # Helper function to generate outputs for each system + forEachSystem = + f: + nixpkgs.lib.genAttrs supportedSystems ( + system: + f { + inherit system; + pkgs = nixpkgs.legacyPackages.${system}; + } + ); + + in + { + packages = forEachSystem ( + { system, pkgs }: + { + default = pkgs.buildGoModule { + pname = "fast-p"; + version = "0.1.0"; + src = ./.; + vendorHash = "sha256-/lKWY6NZrw8aGe1/R2jspT4EZQxAxP0ujckpwZQGn2w="; # Run `nix build` to get actual hash + }; + } + ); + + devShells = forEachSystem ( + { pkgs, ... }: + { + default = pkgs.mkShell { packages = with pkgs; [ go ]; }; + } + ); + }; +} diff --git a/home/fast-p/go.mod b/home/fast-p/go.mod new file mode 100644 index 0000000..2d2c9a3 --- /dev/null +++ b/home/fast-p/go.mod @@ -0,0 +1,11 @@ +module fast-p + +go 1.25.4 + +require ( + github.com/boltdb/bolt v1.3.1 + github.com/cespare/xxhash v1.1.0 + github.com/mitchellh/go-homedir v1.1.0 +) + +require golang.org/x/sys v0.38.0 // indirect diff --git a/home/fast-p/go.sum b/home/fast-p/go.sum new file mode 100644 index 0000000..34025f4 --- /dev/null +++ b/home/fast-p/go.sum @@ -0,0 +1,10 @@ +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= diff --git a/home/fast-p/main.go b/home/fast-p/main.go new file mode 100644 index 0000000..409c2c2 --- /dev/null +++ b/home/fast-p/main.go @@ -0,0 +1,147 @@ +package main + +import ( + "bufio" + "encoding/hex" + "flag" + "fmt" + "github.com/boltdb/bolt" + "github.com/cespare/xxhash" + "github.com/mitchellh/go-homedir" + "io" + "log" + "os" + "os/exec" + "path/filepath" +) + +func hash_file_xxhash(filePath string) (string, error) { + var returnMD5String string + file, err := os.Open(filePath) + if err != nil { + return returnMD5String, err + } + defer file.Close() + hash := xxhash.New() + if _, err := io.Copy(hash, file); err != nil { + return returnMD5String, err + } + hashInBytes := hash.Sum(nil)[:] + returnMD5String = hex.EncodeToString(hashInBytes) + return returnMD5String, nil + +} + +func main() { + flag.Usage = func() { + fmt.Printf(`Usage: fast-p [OPTIONS] + Reads a list of PDF filenames from STDIN and returns a list of null-byte + separated items of the form + filename[TAB]text + where "text" is the text extracted from the first two pages of the PDF + by pdftotext and [TAB] denotes a tab character "\t". + + Common usage of this tool is to pipe the result to FZF with a command in + your .bashrc as explained in https://github.com/bellecp/fast-p. + + +`) + flag.PrintDefaults() + } + version := flag.Bool("version", false, "Display program version") + clearCache := flag.Bool("clear-cache", false, "Delete cache file located at: \n~/.cache/fast-p-pdftotext-output/fast-p_cached_pdftotext_output.db") + flag.Parse() + + if *version != false { + fmt.Printf("v.0.2.5 \nhttps://github.com/bellecp/fast-p\n") + os.Exit(0) + } + + if *clearCache != false { + removePath, err := homedir.Expand("~/.cache/fast-p-pdftotext-output/fast-p_cached_pdftotext_output.db") + if err != nil { + log.Fatal(err) + os.Exit(1) + } + os.Remove(removePath) + os.Exit(0) + } + + // Create ~/.cache folder if does not exist + // https://stackoverflow.com/questions/37932551/mkdir-if-not-exists-using-golang + cachePath, err := homedir.Expand("~/.cache/fast-p-pdftotext-output/") + os.MkdirAll(cachePath, os.ModePerm) + + // open BoltDB cache database + scanner := bufio.NewScanner(os.Stdin) + boltDbFilepath := filepath.Join(cachePath, "fast-p_cached_pdftotext_output.db") + if err != nil { + log.Fatal(err) + } + db, err := bolt.Open(boltDbFilepath, 0600, nil) + bucketName := "fast-p_bucket_for_cached_pdftotext_output" + if err != nil { + log.Fatal(err) + } + defer db.Close() + + nullByte := "\u0000" + + db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucketIfNotExists([]byte(bucketName)) + if err != nil { + return fmt.Errorf("create bucket: %s", err) + } + return nil + }) + + missing := make(map[string]string) + alreadySeen := make(map[string]bool) + + for scanner.Scan() { + filepath := scanner.Text() + hash, err := hash_file_xxhash(filepath) + if alreadySeen[hash] != true { + alreadySeen[hash] = true + if err != nil { + log.Println("err", hash) + } + var content string + found := false + err2 := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(bucketName)) + v := b.Get([]byte(hash)) + if v != nil { + found = true + content = string(v) + } + return nil + }) + if err2 != nil { + log.Println(err2) + } + if found == true { + fmt.Println(filepath + "\t" + content + nullByte) + } else { + missing[hash] = filepath + } + } + } + for hash, filepath := range missing { + cmd := exec.Command("pdftotext", "-l", "2", filepath, "-") + out, err := cmd.CombinedOutput() + content := string(out) + if err != nil { + log.Println(err) + } + fmt.Println(filepath + "\t" + content + nullByte) + db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte(bucketName)) + err := b.Put([]byte(hash), []byte(content)) + if err != nil { + fmt.Println(err) + } + return nil + }) + } +} diff --git a/home/fast-p/result b/home/fast-p/result new file mode 120000 index 0000000..7fb87ab --- /dev/null +++ b/home/fast-p/result @@ -0,0 +1 @@ +/nix/store/d43jc4b5dgpf071kgws69x8jk6ps5rz5-fast-p-0.1.0
\ No newline at end of file |
