| Crates.io | molybdenum |
| lib.rs | molybdenum |
| version | 0.1.10 |
| created_at | 2021-05-26 13:19:47.441988+00 |
| updated_at | 2024-06-13 16:06:58.986032+00 |
| description | Recursive search and replace CLI application |
| homepage | |
| repository | https://github.com/gfannes/molybdenum |
| max_upload_size | |
| id | 402275 |
| size | 67,965 |
Recursive, line-based search and replace CLI application.
cargo install molybdenummo -h should print its help and versiongit clone https://github.com/gfannes/molybdenumcargo install --path molybdenummo -h should print its help and versionFollowing commands demonstrate how mo can be used to accomplish different tasks:
mo: When no search pattern is specified, only the filenames are listedmo -l: Explicitly ask to output only the filenamesmo -C FOLDER: Use FOLDER as root for searchingmo -e hpp -e cpp: Only take files with hpp and cpp extension into accountmo -f PART: Keep filenames that match against PARTmo -F PART: Keep filenames that do not match against PARTmo -0: Use 0x00 to separate filenames. This is handy when using the output with xargs.mo -u -U -a: Take hidden files, folders and binary files into account as wellmo PATTERN: Search for PATTERN in files recursivelymo -p PATTERN: Search for PATTERN in files recursivelymo -w PATTERN: Search for PATTERN in files recursively, adding word-boundary constraints arround PATTERNmo -s PATTERN: Search for PATTERN, case-sensitivemo -B 10 -A 10 PATTERN: Output a context of 10 additional lines before and after each matchmo needle -w -r naald -n: Simulate the replacement of the the word needle with the Dutch word naaldmo needle -w -r naald: Really replace the word needle with the Dutch word naaldxargs
mo -l -C FOLDER -0 | xargs -0 -r mo -i PATTERN: Note the -i option to ensure mo will search in files and not Stdin. In addition, the xargs -r option should be set to ensure nothing will run if no filepaths are produced.Next to this, mo detects if input comes from a console or redirection, and will act accordingly, as well as for its output: mo can be used to report or make replacements in a piped stream as well.
Following bash functions allows you to open a file (o) or change to a folder (c) based on the fuzzy search functionality of fzf. You can pass them any argument that mo accepts, making them handy interactive tools. They rely on bat to provide a preview, and nvr to open the selected file in a new or already running instance of neovim, and zoxide to register and track your most popular folders.
# Open file using `bat` as preview
o() {
mo -l $* | fzf --multi --preview 'bat --style=numbers --color=always --line-range :500 {}' --preview-window 'right:60%' | xargs -I % nvr --remote-tab %
}
# Open file using `mo` as preview
s() {
export all_args="$*"
mo -l $* | fzf --multi --preview 'mo -c -i ${all_args} -C {}' --preview-window 'right:60%' | xargs -I % nvr --remote-tab %
}
# Change to dir using `z`
c() {
z `mo -L $* | fzf`
}
Powerful search can be found without problems, eg, grep, ack, ag, ripgrep or broot.
Tools for replacing recursively in a folder are more difficult to find, although some exist: fart-it. Typically, people use a combination of searching, xargs and a replacement tool like sed or rpl.
I use code searching a lot to investigate a large source code base before attempting a replace. Even with 100k files, search is fast and fairly easy. Recursively replacing text is much more dangerous, especially if it requires the combination of several less frequently used tools; it's difficult to remember a search-xargs-replace combination if not used on a daily basis. On top of this, the search tool used to filter the set of files and perform a dry-run, is not per-se using the same search query as the replace tool. After all, these are different tools. It would be better if a single tool could be used for every-day searching and replacing. This is exactly what The Molybdenum Replacer intends to achieve.
In addition, I find it difficult to use ag and rg to filter against the file path and search for content in the remaining files; the -g option for ag and rg is confusing in my opinion. As such, I would expect ag -g /auro/ -w test to search for the word test in all files that have /auro/ in their path, but that is not what actually happens. It filters with /auro/ and test against the filename (or something that looks like it).
The real reason, of course, is that I had some free time and was looking for a nice project/excuse to learn rust.
Following features are implemented and usable in the current version:
.gitignore files-L optionFollowing features might be added sooner or later:
--n (and use a different name)-cmo -ws test0x0a.mo is currently single-threaded. To achieve ripgrep-like performance, all CPU's are probably required.-l is used to only output filenames, mo can stop searching after the first match.wcmolybdenum, and it is very hard to type. mo is better, but difficult to search on the internet.Scenario: count all files
Running `mo -l -u -U -a | wc`
Elapsed time: 0:00.29
Output: 184675 187146 16959297
Running `rg --files -uu -a | wc`
Elapsed time: 0:00.15
Output: 184675 187146 16589947
Running `ag -l -uu -a | wc`
Elapsed time: 0:00.66
Output: 184675 187146 16589947
Scenario: search for word `test` in .cpp files in subfolder `core` where path contains /auro/
Running `mo -C core -e cpp -f /auro/ -w -p test -l | wc`
Elapsed time: 0:00.03
Output: 165 165 9008
Running `rg -t cpp --files core | rg /auro/ | rg '.cpp$' | tr '\n' '\0' | xargs -0 rg -i -w test -l | wc`
Elapsed time: 0:00.01
Output: 165 165 9008
Running `ag --cpp -l . core | ag /auro/ | ag '.cpp$' | tr '\n' '\0' | xargs -0 ag -w test -l | wc`
Elapsed time: 0:00.05
Output: 165 165 9008
I don't know how I can accomplish this scenario with ag and rg in a single command without relying on xargs and tr.
.out extension to the list of binary files-f and -F is now case-sensitive only when -s is set-m. This should be replaced with proper Regex submatch support.-P % is specified, the replacement string specified via -r will substitute capture groups for all occurences of % or %[0-9].$EDITOR using the -o option. Best used in combo with -l.-R option