Searching inside text files directly from ranger is a fantastic idea, and there are several ways to accomplish this using tools like ripgrep
, fzf
, or grep
. Below is a guide to integrate content-based searching into ranger.
1. Search Inside Files Using Ripgrep (Recommended)
ripgrep
(rg
) is fast and well-suited for searching inside text files.
Steps to Add Text Search:
Install Ripgrep:
- On Arch Linux:
sudo pacman -S ripgrep
- On Arch Linux:
Add a Custom Command in Ranger:
- Edit your
commands.py
file (~/.config/ranger/commands.py
) and add:from ranger.api.commands import Command class search_text(Command): """ :search_text <pattern> Search for a pattern inside text files using ripgrep. """ def execute(self): if not self.arg(1): self.fm.notify("Usage: :search_text <pattern>", bad=True) return import subprocess pattern = self.rest(1) command = f"rg --line-number --column {pattern}" process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode == 0: results = stdout.decode("utf-8").strip().split("\n") if results: self.fm.notify(f"Found {len(results)} result(s):") for result in results: self.fm.notify(result) else: self.fm.notify("No matches found.", bad=True) else: self.fm.notify(stderr.decode("utf-8").strip(), bad=True)
- Edit your
Usage:
- Run
:search_text <pattern>
in ranger, where<pattern>
is the text to search for.
- Run
2. Combine Ripgrep with FZF for Interactive Search
To make results interactive, pipe them to fzf
.
Steps:
Modify the
search_text
Command:class search_fzf(Command): """ :search_fzf <pattern> Search for a pattern inside files using ripgrep and select a result with fzf. """ def execute(self): if not self.arg(1): self.fm.notify("Usage: :search_fzf <pattern>", bad=True) return import subprocess pattern = self.rest(1) command = f"rg --line-number --column {pattern} | fzf" process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode == 0: result = stdout.decode("utf-8").strip() if result: # Extract the file path and line number file_path, line_number = result.split(":", 1) self.fm.select_file(file_path) self.fm.notify(f"Opening {file_path} at line {line_number}") else: self.fm.notify("No matches found.", bad=True) else: self.fm.notify(stderr.decode("utf-8").strip(), bad=True)
Usage:
- Run
:search_fzf <pattern>
in ranger. - Select a result interactively with
fzf
, and ranger will open the file.
- Run
3. Search with Grep
If you prefer grep
, the integration is similar:
Custom Command:
class grep_search(Command): """ :grep_search <pattern> Search for a pattern inside text files using grep. """ def execute(self): if not self.arg(1): self.fm.notify("Usage: :grep_search <pattern>", bad=True) return import subprocess pattern = self.rest(1) command = f"grep -rnw . -e '{pattern}'" process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode == 0: results = stdout.decode("utf-8").strip().split("\n") if results: self.fm.notify(f"Found {len(results)} result(s):") for result in results: self.fm.notify(result) else: self.fm.notify("No matches found.", bad=True) else: self.fm.notify(stderr.decode("utf-8").strip(), bad=True)
Usage:
- Run
:grep_search <pattern>
to search inside text files usinggrep
.
- Run
4. Advanced: Use bat
for Highlighted Results
If you use bat
as a previewer:
Install
bat
:- On Arch Linux:
sudo pacman -S bat
- On Arch Linux:
Update the Command:
class search_preview(Command): """ :search_preview <pattern> Search for a pattern inside files using ripgrep and preview matches using bat. """ def execute(self): if not self.arg(1): self.fm.notify("Usage: :search_preview <pattern>", bad=True) return import subprocess pattern = self.rest(1) command = f"rg --line-number --column {pattern} | fzf --preview 'bat --style=numbers --color=always --line-range :500 {}'" process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode == 0: result = stdout.decode("utf-8").strip() if result: file_path, line_number = result.split(":", 1) self.fm.select_file(file_path) else: self.fm.notify(stderr.decode("utf-8").strip(), bad=True)
Usage:
- Run
:search_preview <pattern>
to search with previews.
- Run
Summary of Features
Tool | Description | Interactive | Fast |
---|---|---|---|
Ripgrep | Ultra-fast text search | No | Yes |
FZF | Interactive search with Ripgrep | Yes | Yes |
Grep | Traditional text search | No | No |
Bat | Syntax-highlighted previews | Yes | Yes |