I like this very much, but I’d like to add one more feature. When I chose the file, I’d like to be in the directory where its located.

To implement this feature, we need to ensure that when you select a file from the fzf results, ranger navigates to the directory where the file is located before opening it. This can be easily achieved by using self.fm.cd() to change the working directory to the file’s directory before invoking the editor.

nvim ~/.config/ranger/commands.py

Here’s the updated fzf_content_open script with this feature:

Updated fzf_content_open

class fzf_content_open(Command):
    """
    :fzf_content_open
    Pre-requisites: fzf, rg, bat, awk, vim or neovim.
    Uses `rg` to search file content recursively in the current directory.
    Filters with `fzf` and previews with `bat`.
    Pressing `Enter` on a result opens it in (neo)vim at the matched line.
    After selection, the directory is changed to where the file is located.
    """

    def execute(self):
        import os
        import subprocess  # Ensure subprocess is imported
        from ranger.ext.get_executables import get_executables

        # Check required executables
        rg = 'rg' if 'rg' in get_executables() else None
        fzf = 'fzf' if 'fzf' in get_executables() else None
        bat = 'bat' if 'bat' in get_executables() else None
        editor = 'nvim' if 'nvim' in get_executables() else 'vim' if 'vim' in get_executables() else None

        if not all([rg, fzf, bat, editor]):
            self.fm.notify("Missing required executables: rg, fzf, bat, and/or a suitable editor.", bad=True)
            return

        # Prevent recursive search from the home directory
        if self.fm.thisdir.path == self.fm.home_path:
            self.fm.notify("Searching from the home directory is not allowed.", bad=True)
            return

        # Run the combined rg + fzf + bat command
        command = (
            "rg --line-number --hidden . | "
            "fzf --delimiter ':' "
            "--preview 'bat --color=always --highlight-line {2} {1}' "
            "| awk -F ':' '{print \"+\"$2\" \"$1}'"
        )
        process = self.fm.execute_command(command, universal_newlines=True, stdout=subprocess.PIPE)
        stdout, _ = process.communicate()

        # If a result is selected, process it
        if process.returncode == 0:
            if len(stdout) < 2:
                return

            selected_line = stdout.split()[0]  # Line number
            file_path = stdout.split()[1].strip()  # File path

            # Get the absolute path of the file
            file_fullpath = os.path.abspath(file_path)

            # Change the current directory to the directory of the selected file
            file_dir = os.path.dirname(file_fullpath)
            self.fm.cd(file_dir)

            # Open the file in the editor at the selected line
            editor_command = [editor, selected_line, file_fullpath]
            self.fm.execute_command(editor_command)

Explanation of Changes:

  1. Changing the Directory:

    • self.fm.cd(file_dir) changes the working directory of ranger to the directory where the file is located.
    • file_dir = os.path.dirname(file_fullpath) extracts the directory path from the selected file’s full path.
  2. Editor Command:

    • The editor_command remains unchanged, but now the directory is correctly set to the file’s location before opening it with the editor.

Keybinding in rc.conf

To bind this command to a hotkey (e.g., F5), add the following line to your ~/.config/ranger/rc.conf:

map F5 fzf_content_open

Usage

  1. Restart ranger.
  2. Press F5 to invoke the fzf_content_open command.
  3. Type your search term in fzf.
  4. Select a result and press Enter.
  5. Ranger will change the directory to where the file is located and open the file at the matched line in your editor.