├── .gitignore ├── LICENSE ├── README.md ├── assets ├── demo.cast └── demo.gif ├── go.mod ├── go.sum ├── pathos └── pathos.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | # Misc 18 | pathos.sh 19 | debug.log 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2022 Chip Castle Dot Com, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the “Software”), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pathos - CLI for editing a PATH env variable 2 | 3 | ## Ruby Version 4 | 5 | [chip/pathos.rb](https://github.com/chip/pathos.rb) 6 | 7 | ## Go Version 8 | 9 | This is the Go version. 10 | 11 | ## Background 12 | 13 | If you're like me, you might have a number of `export PATH` statements 14 | littering your shell resource file (e.g., `.zshrc`, `.bashrc`, etc). Over time, 15 | many directory entries get added and revised. Those that remain eventually 16 | become unnecessary, are mistakenly duplicated, or represent directories that no 17 | longer exist on the system. This is my attempt at cleaning up `PATH` 18 | environment variable. Hopefully, others will find this to be useful. 19 | 20 | ## Demo 21 | 22 | ![pathos DEMO](assets/demo.gif "pathos DEMO") 23 | 24 | ### Built with the following: 25 | 26 | * [Go](https://go.dev/) 27 | * [Bubble Tea](https://github.com/charmbracelet/bubbletea) 28 | * [Bubbles](https://github.com/charmbracelet/bubbles) 29 | * [Lip Gloss](https://github.com/charmbracelet/lipgloss) 30 | 31 | ## Installation 32 | go install github.com/chip/pathos@latest 33 | 34 | ## IMPORTANT 35 | 36 | Be sure to save your changes with `S` *(uppercase letter S)* before quitting 37 | `pathos`, as **changes will not be saved automatically**. 38 | 39 | Each time you save your changes to the directory list, `pathos` will build a 40 | revised `export $PATH` statement that is written to `$HOME/pathos.sh`. 41 | 42 | To use the new PATH, `~/pathos.sh` **MUST BE SOURCED** to take effect within your 43 | shell. 44 | 45 | source $HOME/pathos.sh 46 | 47 | ## Navigation 48 | 49 | Like any typical [Bubble Tea](https://github.com/charmbracelet/bubbletea) app, 50 | you have the following keys that are available for navigation: 51 | 52 | Key | Description 53 | ---|--- 54 | k | Move up the list of directories 55 | j | Move down the list of directories 56 | l | Move to the next page 57 | h | Move to the previous page 58 | g/home | Move to the top of the list 59 | G/end | Move to the end of the list 60 | q | Quit pathos **(does NOT save changes)** 61 | ? | Toggle between regular and full help 62 | 63 | ## Commands 64 | 65 | Key | Description 66 | ---|--- 67 | N | Add a new directory to the list at the current cursor position 68 | D | Delete a directory at the current cursor position 69 | S | Save all changes made to the list of directories 70 | 71 | ## Color Highlighting 72 | 73 | Color | Description 74 | ---|--- 75 |   Yellow   | Shows current cursor position 76 |   Red   | Indicates directories that **do not exist** 77 |   Aqua   | Indicates duplicate directories 78 | -------------------------------------------------------------------------------- /assets/demo.cast: -------------------------------------------------------------------------------- 1 | {"version": 2, "width": 130, "height": 37, "timestamp": 1658958487, "env": {"SHELL": "/bin/zsh", "TERM": "screen"}} 2 | [0.231236, "o", "\u001b]0;~\u0007"] 3 | [0.238591, "o", "\r\n"] 4 | [0.239073, "o", "\u001b[0m\u001b[23m\u001b[24m\u001b[J\u001b[34m~\u001b[39m\r\n\r\u001b[35m❯\u001b[39m \u001b[K\u001b[?2004h"] 5 | [0.855894, "o", "p"] 6 | [1.255468, "o", "\bpa"] 7 | [1.52025, "o", "t"] 8 | [1.708333, "o", "h"] 9 | [1.914453, "o", "o"] 10 | [2.177444, "o", "s"] 11 | [3.898204, "o", "\u001b[?2004l\r\r\n"] 12 | [3.898502, "o", "\u001b]0;chip: pathos\u0007"] 13 | [3.913634, "o", "\u001b[?25l"] 14 | [3.914511, "o", "\u001b[?1049h\u001b[0;0H"] 15 | [3.931985, "o", " PATHOS - CLI Manager of the PATH env variable \r\r\n \r\r\n \u001b[38;2;119;119;119m53 items\u001b[0m \r\r\n \r\r\n \u001b[93m> /Users/chip/.luarocks/bin\u001b[0m \r\r\n /Users/chip/perl5/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n /usr/local/opt/openssl@1.1/bin \r\r\n /usr/local/opt/openssl/bin \r\r\n /Users/chip/.rbenv/shims \r\r\n \u001b[96m/Users/chip/bin\u001b[0m \r\r\n ./bin \r\r\n \u001b[91m/usr/X11/bin"] 16 | [3.932511, "o", "\u001b[0m \r\r\n /usr/local/bin \r\r\n /usr/local/sbin \r\r\n \u001b[91m/usr/local/git/bin\u001b[0m \r\r\n /bin \r\r\n /usr/bin \r\r\n /sbin \r\r\n /usr/sbin \r\r\n \u001b[96m/Users/chip/bin\u001b[0m \r\r\n /usr/local/opt/ruby/bin \r\r\n \u001b[91m/Users/chip/.gem/ruby/2.6.0/cache\u001b[0m \r\r\n \u001b[91m/opt/local/bin\u001b[0m \r\r\n \u001b[91m/opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin "] 17 | [3.932742, "o", " \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n \r\r\n \u001b[38;2;151;151;151m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m \r\r\n \r\r\n \u001b[38;2;97;97;97m↑/k\u001b[0m \u001b[38;2;73;73;73mup\u001b[0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97m↓/j\u001b[0m \u001b[38;2;73;73;73mdown\u001b[0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97mN\u001b[0m \u001b[38;2;73;73;73mnew\u001b[0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97mD\u001b[0m \u001b[38;2;73;73;73mdelete\u001b[0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97mS\u001b[0m \u001b[38;2;73;73;73msave paths\u001b[0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97mq\u001b[0m \u001b[38;2;73;73;73mquit\u001b["] 18 | [3.93318, "o", "0m\u001b[38;2;60;60;60m • \u001b[0m\u001b[38;2;97;97;97m?\u001b[0m \u001b[38;2;73;73;73mmore\u001b[0m\u001b[35;0H"] 19 | [5.282009, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B /Users/chip/.luarocks/bin \r\r\n \u001b[93m> /Users/chip/perl5/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 20 | [5.481361, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B /Users/chip/perl5/bin \r\r\n \u001b[93m> /Users/chip/.npm-packages/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 21 | [5.684106, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /Users/chip/.npm-packages/bin \r\r\n \u001b[93m> /usr/local/opt/python@3.8/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 22 | [5.850707, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/opt/python@3.8/bin \r\r\n \u001b[93m> /usr/local/opt/openssl@1.1/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 23 | [6.031715, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/opt/openssl@1.1/bin \r\r\n \u001b[93m> /usr/local/opt/openssl/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 24 | [6.218064, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/opt/openssl/bin \r\r\n \u001b[93m> /Users/chip/.rbenv/shims\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 25 | [6.382554, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /Users/chip/.rbenv/shims \r\r\n \u001b[93m> /Users/chip/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 26 | [7.098561, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m52 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[93m> ./bin\u001b[0m \r\r\n \u001b[91m/usr/X11/bin\u001b[0m \r\r\n /usr/local/bin \r\r\n /usr/local/sbin \r\r\n \u001b[91m/usr/local/git/bin\u001b[0m \r\r\n /bin \r\r\n /usr/bin \r\r\n /sbin "] 27 | [7.098824, "o", " \r\r\n /usr/sbin \r\r\n /Users/chip/bin \r\r\n /usr/local/opt/ruby/bin \r\r\n \u001b[91m/Users/chip/.gem/ruby/2.6.0/cache\u001b[0m \r\r\n \u001b[91m/opt/local/bin\u001b[0m \r\r\n \u001b[91m/opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 28 | [7.732753, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B ./bin \r\r\n \u001b[91m> /usr/X11/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 29 | [8.681979, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m51 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /usr/local/bin\u001b[0m \r\r\n /usr/local/sbin \r\r\n \u001b[91m/usr/local/git/bin\u001b[0m \r\r\n /bin \r\r\n /usr/bin \r\r\n /sbin \r\r\n /usr/sbin \r\r\n /Users/chip/bin "] 30 | [8.682233, "o", " \r\r\n /usr/local/opt/ruby/bin \r\r\n \u001b[91m/Users/chip/.gem/ruby/2.6.0/cache\u001b[0m \r\r\n \u001b[91m/opt/local/bin\u001b[0m \r\r\n \u001b[91m/opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 31 | [9.0475, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/bin \r\r\n \u001b[93m> /usr/local/sbin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 32 | [9.218234, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/sbin \r\r\n \u001b[91m> /usr/local/git/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 33 | [9.684537, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m50 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /bin\u001b[0m \r\r\n /usr/bin \r\r\n /sbin \r\r\n /usr/sbin \r\r\n /Users/chip/bin \r\r\n /usr/local/opt/ruby/bin \r\r\n \u001b[91m/Users/chip/.gem/ruby/2.6.0/cache\u001b[0m \r\r\n \u001b[91m/opt/local/bin\u001b[0m "] 34 | [9.68479, "o", " \r\r\n \u001b[91m/opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n \u001b[91m/usr/local/opt/qt@5.5/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 35 | [11.148407, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /bin \r\r\n \u001b[93m> /usr/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 36 | [11.348015, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/bin \r\r\n \u001b[93m> /sbin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 37 | [11.48167, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /sbin \r\r\n \u001b[93m> /usr/sbin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 38 | [11.665341, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/sbin \r\r\n \u001b[93m> /Users/chip/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 39 | [11.833678, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /Users/chip/bin \r\r\n \u001b[93m> /usr/local/opt/ruby/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 40 | [12.000552, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B /usr/local/opt/ruby/bin \r\r\n \u001b[91m> /Users/chip/.gem/ruby/2.6.0/cache\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 41 | [12.501855, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m49 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[91m> /opt/local/bin\u001b[0m \r\r\n \u001b[91m/opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin "] 42 | [12.502152, "o", " \r\r\n /usr/local/opt/python@3.8/bin \r\r\n \u001b[91m/usr/local/opt/qt@5.5/bin\u001b[0m \r\r\n /usr/local/opt/openssl/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 43 | [12.965198, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m48 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[91m> /opt/local/sbin\u001b[0m \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin "] 44 | [12.96548, "o", " \r\r\n \u001b[91m/usr/local/opt/qt@5.5/bin\u001b[0m \r\r\n /usr/local/opt/openssl/bin \r\r\n \u001b[91m/usr/local/heroku/bin\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 45 | [13.130925, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B \u001b[38;2;119;119;119m47 items\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /Users/chip/code/go/bin\u001b[0m \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n \u001b[91m/usr/local/opt/qt@5.5/bin\u001b[0m "] 46 | [13.131149, "o", " \r\r\n /usr/local/opt/openssl/bin \r\r\n \u001b[91m/usr/local/heroku/bin\u001b[0m \r\r\n /Users/chip/perl5/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 47 | [16.432181, "o", "\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n \r\r\n \u001b[38;2;119;119;119m47 items\u001b[0m \r\r\n \r\r\n /Users/chip/.luarocks/bin \r\r\n /Users/chip/perl5/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n /usr/local/opt/openssl@1.1/bin \r\r\n /usr/local/opt/openssl/bin \r\r\n /Users/chip/.rbenv/shims \r\r\n ./bin "] 48 | [16.432475, "o", " \r\r\n /usr/local/bin \r\r\n /usr/local/sbin \r\r\n /bin \r\r\n /usr/bin \r\r\n /sbin \r\r\n /usr/sbin \r\r\n /Users/chip/bin \r\r\n /usr/local/opt/ruby/bin \r\r\n \u001b[93m> /Users/chip/code/go/bin\u001b[0m \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n \r\r\n \u001b[38;2;151;151;151m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m "] 49 | [16.432781, "o", " \r\r\n \r\r\n \u001b[38;2;97;97;97m↑/k\u001b[0m \u001b[38;2;97;97;97m \u001b[0m\u001b[38;2;73;73;73mup\u001b[0m \u001b[38;2;60;60;60m \u001b[0m\u001b[38;2;97;97;97mN\u001b[0m\u001b[38;2;97;97;97m \u001b[0m\u001b[38;2;73;73;73mnew\u001b[0m \u001b[38;2;60;60;60m \u001b[0m\u001b[38;2;97;97;97mq\u001b[0m\u001b[38;2;97;97;97m \u001b[0m\u001b[38;2;73;73;73mquit\u001b[0m \u001b[38;2;60;60;60m \u001b[0m\r\r\n \u001b[38;2;97;97;97m↓/j\u001b[0m \u001b[38;2;73;73;73mdown\u001b[0m \u001b[38;2;97;97;97mD\u001b[0m \u001b[38;2;73;73;73mdelete\u001b[0m \u001b[38;2;97;97;97m?\u001b[0m \u001b[38;2;73;73;73mclose help\u001b[0m \r\r\n \u001b[38;2;97;97;97m→/l/pgdn\u001b[0m \u001b[38;2;73;73;73mnext page\u001b[0m \u001b[38;2;97;97;97mS\u001b[0m \u001b[38;2;73;73;73msave paths\u001b[0m \r\r\n \u001b[38;2;97;97;97m←/h/pgup\u001b[0m \u001b[38;2;73;73;73mprev page\u001b[0m \r\r\n \u001b[38;2;97;97;97mg/home\u001b[0m \u001b[38;2;73;73;73mgo to start\u001b[0m \r\r\n \u001b[38;2;97;97;97mG/end\u001b[0m \u001b[38;2;73;73;73mgo to end\u001b[0m "] 50 | [16.433057, "o", " \u001b[35;0H"] 51 | [19.498231, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B /Users/chip/code/go \r\r\n /usr/local/opt/fzf/bin \r\r\n \u001b[93m> /Users/chip/n/bin\u001b[0m \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n "] 52 | [19.498408, "o", " \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n \r\r\n\u001b[1B \u001b[38;2;60;60;60m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m\u001b[38;2;151;151;151m•\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 53 | [20.46679, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /usr/local/opt/fzf/bin\u001b[0m \r\r\n /Users/chip/n/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 54 | [20.849149, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /Users/chip/code/go\u001b[0m \r\r\n /usr/local/opt/fzf/bin \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 55 | [21.265324, "o", "\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[1A\u001b[1A\u001b[1A\u001b[130D\u001b[2K PATHOS - CLI Manager of the PATH env variable \r\r\n\u001b[1B\u001b[1B\u001b[1B \u001b[93m> /Users/chip/.luarocks/bin\u001b[0m \r\r\n /Users/chip/perl5/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n /usr/local/opt/python@3.8/bin \r\r\n /usr/local/opt/openssl@1.1/bin \r\r\n /usr/local/opt/openssl/bin \r\r\n /Users/chip/.rbenv/shims \r\r\n ./bin \r\r\n /usr/local/bin \r\r\n /usr/local/sbin \r\r\n /bin \r\r\n /usr/bin "] 56 | [21.265602, "o", " \r\r\n /sbin \r\r\n /usr/sbin \r\r\n /Users/chip/bin \r\r\n /usr/local/opt/ruby/bin \r\r\n /Users/chip/code/go/bin \r\r\n /Users/chip/Library/Android/sdk/platform-tools \r\r\n /Users/chip/Library/Android/sdk/tools \r\r\n /usr/local/opt/fzf/bin \r\r\n /Users/chip/n/bin \r\r\n /Users/chip/.npm-packages/bin \r\r\n\u001b[1B \u001b[38;2;151;151;151m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m\u001b[38;2;60;60;60m•\u001b[0m \r\r\n\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[1B\u001b[35;0H"] 57 | [24.04758, "o", "\u001b[2K\u001b[?1049l\u001b[?1002l\u001b[?1003l\u001b[?25h"] 58 | [24.049996, "o", "\u001b]0;~\u0007"] 59 | [24.052086, "o", "\r\n"] 60 | [24.052329, "o", "\u001b[0m\u001b[23m\u001b[24m\u001b[J\u001b[34m~\u001b[39m \u001b[33m20s\u001b[39m\r\n\r\u001b[35m❯\u001b[39m \u001b[K\u001b[?2004h"] 61 | [25.260657, "o", "b"] 62 | [25.391203, "o", "\bba"] 63 | [25.646255, "o", "t"] 64 | [26.068318, "o", " "] 65 | [27.368184, "o", "~"] 66 | [28.640352, "o", "/"] 67 | [29.600013, "o", "p"] 68 | [29.79521, "o", "a"] 69 | [29.95117, "o", "t"] 70 | [30.014937, "o", "h"] 71 | [30.148022, "o", "o"] 72 | [30.272317, "o", "s"] 73 | [30.604964, "o", "."] 74 | [30.940537, "o", "s"] 75 | [31.066592, "o", "h"] 76 | [31.432928, "o", "\u001b[?2004l\r\r\n"] 77 | [31.433221, "o", "\u001b]0;chip: bat ~/pathos.sh\u0007"] 78 | [31.505658, "o", "\u001b[?1h\u001b=\r"] 79 | [31.505881, "o", "\u001b[38;5;238m───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n \u001b[38;5;238m│ \u001b[0mFile: \u001b[1m/Users/chip/pathos.sh\u001b[0m\u001b[m\r\n\u001b[38;5;238m───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n"] 80 | [31.519844, "o", "\u001b[38;5;238m 1\u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;249;38;114mexport\u001b[0m\u001b[38;2;255;255;255m \u001b[0m\u001b[38;2;255;255;255mPATH\u001b[0m\u001b[38;2;249;38;114m=\u001b[0m\u001b[38;2;230;219;116m/Users/chip/.luarocks/bin:/Users/chip/perl5/bin:/Users/chip/.npm-packages/bin:/usr/local/opt/python@3.8/bin:/\u001b[0m\u001b[m\r\n"] 81 | [31.520203, "o", "\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116musr/local/opt/openssl@1.1/bin:/usr/local/opt/openssl/bin:/Users/chip/.rbenv/shims:./bin:/usr/local/bin:/usr/local/sbin:/b\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116min:/usr/bin:/sbin:/usr/sbin:/Users/chip/bin:/usr/local/opt/ruby/bin:/Users/chip/code/go/bin:/Users/chip/Library/Android/s\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116mdk/platform-tools:/Users/chip/Library/Android/sdk/tools:/usr/local/opt/fzf/bin:/Users/chip/n/bin:/Users/chip/.npm-package\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116ms/bin:/usr/local/opt/python@3.8/bin:/usr/local/opt/qt@5.5/bin:/usr/local/opt/openssl/bin:/usr/local/heroku/bin:/Users/chi\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116mp/perl5/bin:/Users/chip/.rbenv/shims:/Users/chip/.rbenv/bin:/Applications/Postgres.app/Contents/Versions/latest/bin:./bin\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116m:/usr/X11/bin:"] 82 | [31.520305, "o", "/usr/local/bin:/usr/local/sbin:/usr/local/git/bin:/bin:/usr/bin:/sbin:/usr/sbin:/Users/chip/bin:/usr/local/\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116mopt/ruby/bin:/Users/chip/.gem/ruby/2.6.0/cache:/opt/local/bin:/opt/local/sbin:/Users/chip/code/go:/usr/local/opt/fzf/bin:\u001b[0m\u001b[m\r\n\u001b[38;5;238m \u001b[0m \u001b[38;5;238m│\u001b[0m \u001b[38;2;230;219;116m/Users/chip/n/bin\u001b[0m\u001b[m\r\n"] 83 | [31.520335, "o", "\u001b[38;5;238m───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[m\r\n"] 84 | [31.520523, "o", "\r\u001b[K\u001b[?1l\u001b>"] 85 | [31.532703, "o", "\u001b]0;~\u0007"] 86 | [31.534015, "o", "\r\n"] 87 | [31.534261, "o", "\u001b[0m\u001b[23m\u001b[24m\u001b[J\u001b[34m~\u001b[39m\r\n\r\u001b[35m❯\u001b[39m \u001b[K\u001b[?2004h"] 88 | -------------------------------------------------------------------------------- /assets/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chip/pathos/134beafa5971b61f5a59ae1bd85bab05b8709df8/assets/demo.gif -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chip/pathos 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/charmbracelet/bubbles v0.13.0 7 | github.com/charmbracelet/bubbletea v0.22.0 8 | github.com/charmbracelet/lipgloss v0.5.0 9 | ) 10 | 11 | require ( 12 | github.com/atotto/clipboard v0.1.4 // indirect 13 | github.com/containerd/console v1.0.3 // indirect 14 | github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 15 | github.com/mattn/go-isatty v0.0.14 // indirect 16 | github.com/mattn/go-runewidth v0.0.13 // indirect 17 | github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect 18 | github.com/muesli/cancelreader v0.2.1 // indirect 19 | github.com/muesli/reflow v0.3.0 // indirect 20 | github.com/muesli/termenv v0.12.0 // indirect 21 | github.com/rivo/uniseg v0.2.0 // indirect 22 | github.com/sahilm/fuzzy v0.1.0 // indirect 23 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect 24 | golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= 2 | github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= 3 | github.com/charmbracelet/bubbles v0.13.0 h1:zP/ROH3wJEBqZWKIsD50ZKKlx3ydLInq3LdD/Nrlb8w= 4 | github.com/charmbracelet/bubbles v0.13.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= 5 | github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= 6 | github.com/charmbracelet/bubbletea v0.22.0 h1:E1BTNSE3iIrq0G0X6TjGAmrQ32cGCbFDPcIuImikrUc= 7 | github.com/charmbracelet/bubbletea v0.22.0/go.mod h1:aoVIwlNlr5wbCB26KhxfrqAn0bMp4YpJcoOelbxApjs= 8 | github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= 9 | github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= 10 | github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= 11 | github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= 12 | github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= 13 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 14 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 15 | github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 16 | github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 17 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 18 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 19 | github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= 20 | github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= 21 | github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= 22 | github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 23 | github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= 24 | github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= 25 | github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= 26 | github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 27 | github.com/muesli/cancelreader v0.2.1 h1:Xzd1B4U5bWQOuSKuN398MyynIGTNT89dxzpEDsalXZs= 28 | github.com/muesli/cancelreader v0.2.1/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 29 | github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= 30 | github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= 31 | github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= 32 | github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= 33 | github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= 34 | github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= 35 | github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= 36 | github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 37 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= 38 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 39 | github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= 40 | github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= 41 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 43 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 44 | golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 45 | golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 46 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= 47 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 48 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 49 | golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= 50 | golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 51 | -------------------------------------------------------------------------------- /pathos: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chip/pathos/134beafa5971b61f5a59ae1bd85bab05b8709df8/pathos -------------------------------------------------------------------------------- /pathos.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "os" 8 | "strings" 9 | 10 | "github.com/charmbracelet/bubbles/help" 11 | "github.com/charmbracelet/bubbles/key" 12 | "github.com/charmbracelet/bubbles/list" 13 | "github.com/charmbracelet/bubbles/textinput" 14 | tea "github.com/charmbracelet/bubbletea" 15 | "github.com/charmbracelet/lipgloss" 16 | ) 17 | 18 | var duplicatePaths map[string]struct{} 19 | 20 | // this is an enum for Go 21 | type sessionState uint 22 | 23 | const ( 24 | listView sessionState = iota 25 | inputView 26 | ) 27 | 28 | type savePathMsg struct { 29 | path string 30 | cursor int 31 | } 32 | type deletePathMsg int 33 | type saveShellSourceMsg struct { 34 | m model 35 | } 36 | 37 | type errMsg error 38 | 39 | // TODO Show color legend 40 | const listHeight = 35 41 | 42 | // Colors: https://www.ditig.com/256-colors-cheat-sheet 43 | var ( 44 | titleStyle = lipgloss.NewStyle().MarginLeft(2) 45 | itemStyle = lipgloss.NewStyle().PaddingLeft(4) 46 | selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("11")) // Xterm Yellow (SYSTEM) 47 | doesNotExistItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("9")) // Xterm Red (SYSTEM) 48 | selectedAndDoesNotExistItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("9")) 49 | duplicateItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("14")) // Xterm Aqua (SYSTEM) 50 | selectedAndDuplicateItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("14")) 51 | quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4) 52 | ) 53 | 54 | type item string 55 | 56 | func (i item) FilterValue() string { return "" } 57 | 58 | type itemDelegate struct{} 59 | 60 | func (d itemDelegate) Height() int { return 1 } 61 | func (d itemDelegate) Spacing() int { return 0 } 62 | func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } 63 | func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { 64 | 65 | i, ok := listItem.(item) 66 | if !ok { 67 | return 68 | } 69 | str := string(i) 70 | 71 | fn := itemStyle.Render 72 | 73 | if !directoryExists(str) { 74 | fn = doesNotExistItemStyle.Render 75 | } else if duplicatePath(str) { 76 | fn = duplicateItemStyle.Render 77 | } 78 | 79 | if index == m.Index() { 80 | fn = func(s string) string { 81 | if directoryExists(s) { 82 | return selectedItemStyle.Render("> " + s) 83 | } else if duplicatePath(str) { 84 | return selectedAndDuplicateItemStyle.Render("> " + s) 85 | } else { 86 | return selectedAndDoesNotExistItemStyle.Render("> " + s) 87 | } 88 | } 89 | } 90 | 91 | fmt.Fprint(w, fn(str)) 92 | } 93 | 94 | type model struct { 95 | keys HelpKeyMap 96 | help help.Model 97 | list list.Model 98 | items []item 99 | 100 | textInput textinput.Model 101 | msg tea.Msg 102 | err error 103 | state sessionState 104 | showPagination bool 105 | } 106 | 107 | func additionalKeys() []key.Binding { 108 | return []key.Binding{ 109 | keys.NewPath, 110 | keys.DeletePath, 111 | keys.SaveShellSource, 112 | } 113 | } 114 | 115 | func initialModel() model { 116 | ti := setupTextInput() 117 | 118 | items := createPaths() 119 | duplicatePaths = findDuplicatePaths(items) 120 | 121 | const defaultWidth = 60 122 | 123 | l := list.New(items, itemDelegate{}, defaultWidth, listHeight) 124 | l.Title = "pathos - CLI for editing a PATH env variable" 125 | 126 | l.SetShowHelp(true) 127 | l.SetShowStatusBar(true) 128 | l.SetFilteringEnabled(false) 129 | l.Styles.Title = titleStyle 130 | 131 | l.AdditionalFullHelpKeys = additionalKeys 132 | l.AdditionalShortHelpKeys = additionalKeys 133 | 134 | m := model{ 135 | keys: keys, 136 | help: help.New(), 137 | list: l, 138 | textInput: ti, 139 | err: nil, 140 | state: listView, 141 | showPagination: false, 142 | } 143 | return m 144 | } 145 | 146 | func directoryExists(dir string) bool { 147 | if _, err := os.Stat(dir); os.IsNotExist(err) { 148 | return false 149 | } 150 | return true 151 | } 152 | 153 | func savePathCmd(cursor int, path string) tea.Cmd { 154 | return func() tea.Msg { 155 | return savePathMsg{path: path, cursor: cursor} 156 | } 157 | } 158 | 159 | func deletePathCmd(m model, id int) tea.Cmd { 160 | return func() tea.Msg { 161 | return deletePathMsg(id) 162 | } 163 | } 164 | 165 | func saveShellSourceCmd(m model) tea.Cmd { 166 | return func() tea.Msg { 167 | return saveShellSourceMsg{m: m} 168 | } 169 | } 170 | 171 | func saveShellSource(m model) (int, error) { 172 | s := []string{} 173 | for _, listItem := range m.list.Items() { 174 | i, _ := listItem.(item) 175 | path := string(i) 176 | if path != "" { 177 | s = append(s, path) 178 | } 179 | } 180 | data := "export PATH=" + strings.Join(s, ":") 181 | 182 | HOME := os.Getenv("HOME") 183 | filename := HOME + "/pathos.sh" 184 | 185 | file, err := os.Create(filename) 186 | if err != nil { 187 | return -1, err 188 | } 189 | defer file.Close() 190 | 191 | return file.WriteString(data) 192 | } 193 | 194 | func (m model) Init() tea.Cmd { 195 | return tea.EnterAltScreen 196 | } 197 | 198 | func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 199 | var cmd tea.Cmd 200 | var cmds []tea.Cmd 201 | 202 | switch msg := msg.(type) { 203 | case tea.WindowSizeMsg: 204 | m.list.SetWidth(msg.Width) 205 | return m, nil 206 | 207 | case savePathMsg: 208 | m.list.InsertItem(msg.cursor, item(msg.path)) 209 | duplicatePaths = findDuplicatePaths(m.list.Items()) 210 | return m, nil 211 | 212 | case deletePathMsg: 213 | 214 | m.list.RemoveItem(int(msg)) 215 | duplicatePaths = findDuplicatePaths(m.list.Items()) 216 | return m, nil 217 | 218 | case saveShellSourceMsg: 219 | saveShellSource(m) 220 | return m, nil 221 | 222 | case tea.KeyMsg: 223 | switch { 224 | 225 | case key.Matches(msg, keys.Quit): 226 | return m, tea.Quit 227 | 228 | case key.Matches(msg, keys.Enter): 229 | 230 | if m.state == inputView { 231 | text := strings.TrimSpace(m.textInput.Value()) 232 | if text != "" { 233 | cursor := m.list.Cursor() 234 | value := m.textInput.Value() 235 | cmds = append(cmds, savePathCmd(cursor, value)) 236 | m.state = listView 237 | } 238 | } 239 | 240 | case key.Matches(msg, keys.NewPath): 241 | m.state = inputView 242 | return m, nil 243 | 244 | case key.Matches(msg, keys.DeletePath): 245 | if m.state == listView { 246 | i := m.list.Index() 247 | cmds = append(cmds, deletePathCmd(m, i)) 248 | } 249 | 250 | case key.Matches(msg, keys.SaveShellSource): 251 | cmds = append(cmds, saveShellSourceCmd(m)) 252 | 253 | } 254 | 255 | // We handle errors just like any other message 256 | case errMsg: 257 | m.err = msg 258 | return m, nil 259 | } 260 | // Update different view states 261 | switch m.state { 262 | case inputView: 263 | m.textInput, cmd = m.textInput.Update(msg) 264 | case listView: 265 | m.list, cmd = m.list.Update(msg) 266 | } 267 | cmds = append(cmds, cmd) 268 | 269 | return m, tea.Batch(cmds...) 270 | } 271 | 272 | func (m model) View() string { 273 | switch m.state { 274 | case inputView: 275 | return m.textInput.View() 276 | default: 277 | 278 | return m.list.View() 279 | } 280 | } 281 | 282 | func getPaths() []string { 283 | PATH := os.Getenv("PATH") 284 | return strings.Split(PATH, ":") 285 | } 286 | 287 | func createPaths() []list.Item { 288 | paths := getPaths() 289 | items := make([]list.Item, len(paths)) 290 | for i, path := range paths { 291 | items[i] = item(path) 292 | } 293 | return items 294 | } 295 | 296 | func setupTextInput() textinput.Model { 297 | ti := textinput.New() 298 | ti.Prompt = "Enter directory: " 299 | ti.Placeholder = "/" 300 | ti.SetValue("") 301 | ti.Blink() 302 | ti.Focus() 303 | ti.CharLimit = 156 304 | ti.Width = 50 305 | 306 | return ti 307 | } 308 | 309 | func duplicatePath(path string) bool { 310 | _, isPresent := duplicatePaths[path] 311 | return isPresent 312 | } 313 | 314 | func findDuplicatePaths(items []list.Item) map[string]struct{} { 315 | pathMap := make(map[string]int) 316 | duplicates := make(map[string]struct{}) 317 | 318 | for _, listItem := range items { 319 | i, ok := listItem.(item) 320 | if ok { 321 | path := string(i) 322 | if value, ok := pathMap[path]; ok { 323 | pathMap[path] = value + 1 324 | } else { 325 | pathMap[path] = 0 326 | } 327 | } 328 | } 329 | for path, count := range pathMap { 330 | if count > 1 { 331 | duplicates[path] = struct{}{} 332 | } 333 | } 334 | return duplicates 335 | } 336 | 337 | type HelpKeyMap struct { 338 | Help key.Binding 339 | Quit key.Binding 340 | NewPath key.Binding 341 | DeletePath key.Binding 342 | SaveShellSource key.Binding 343 | Enter key.Binding 344 | } 345 | 346 | var keys = HelpKeyMap{ 347 | Enter: key.NewBinding( 348 | key.WithKeys("enter"), 349 | key.WithHelp("enter", "submit new path"), 350 | ), 351 | NewPath: key.NewBinding( 352 | key.WithKeys("N"), 353 | key.WithHelp("N", "new"), 354 | ), 355 | DeletePath: key.NewBinding( 356 | key.WithKeys("D"), 357 | key.WithHelp("D", "delete"), 358 | ), 359 | SaveShellSource: key.NewBinding( 360 | key.WithKeys("S"), 361 | key.WithHelp("S", "save paths"), 362 | ), 363 | } 364 | 365 | func main() { 366 | if os.Getenv("HELP_DEBUG") != "" { 367 | if f, err := tea.LogToFile("debug.log", "help"); err != nil { 368 | fmt.Println("Couldn't open a file for logging:", err) 369 | os.Exit(1) 370 | } else { 371 | log.SetOutput(f) 372 | defer f.Close() 373 | } 374 | } 375 | 376 | if err := tea.NewProgram(initialModel()).Start(); err != nil { 377 | fmt.Printf("Could not start program :(\n%v\n", err) 378 | os.Exit(1) 379 | } 380 | } 381 | --------------------------------------------------------------------------------