diff options
Diffstat (limited to 'home-manager/programs/ranger/plugins')
13 files changed, 416 insertions, 0 deletions
diff --git a/home-manager/programs/ranger/plugins/__init__.py b/home-manager/programs/ranger/plugins/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/home-manager/programs/ranger/plugins/__init__.py diff --git a/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-310.pyc b/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-310.pyc Binary files differnew file mode 100644 index 0000000..1a26aa3 --- /dev/null +++ b/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-310.pyc diff --git a/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-311.pyc b/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..87b2e7f --- /dev/null +++ b/home-manager/programs/ranger/plugins/__pycache__/__init__.cpython-311.pyc diff --git a/home-manager/programs/ranger/plugins/__pycache__/fd.cpython-311.pyc b/home-manager/programs/ranger/plugins/__pycache__/fd.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..146af23 --- /dev/null +++ b/home-manager/programs/ranger/plugins/__pycache__/fd.cpython-311.pyc diff --git a/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-310.pyc b/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-310.pyc Binary files differnew file mode 100644 index 0000000..49d1db9 --- /dev/null +++ b/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-310.pyc diff --git a/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-311.pyc b/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-311.pyc Binary files differnew file mode 100644 index 0000000..7b3ac1c --- /dev/null +++ b/home-manager/programs/ranger/plugins/__pycache__/quit_cd_wd.cpython-311.pyc diff --git a/home-manager/programs/ranger/plugins/quit_cd_wd.py b/home-manager/programs/ranger/plugins/quit_cd_wd.py new file mode 100644 index 0000000..e47837f --- /dev/null +++ b/home-manager/programs/ranger/plugins/quit_cd_wd.py @@ -0,0 +1,38 @@ +import ranger.api +from ranger.api.commands import * +import os + +def save_wd(command): + with open(os.path.expanduser('~/.ranger_quit_cd_wd'), 'w') as f: + f.write(command.fm.thisdir.path); + +class quit_cd_wd(Command): + """:chdir to working directory of ranger after quiting on ranger. + + """ + def _exit_no_work(self): + if self.fm.loader.has_work(): + self.fm.notify('Not quitting: Tasks in progress: Use `quit!` to force quit') + else: + self.fm.exit() + + def execute(self): + if len(self.fm.tabs) >= 2: + self.fm.tab_close() + else: + save_wd(self) + self._exit_no_work() + +class quitall_cd_wd(Command): + """:chdir to working directory of ranger after quitalling on ranger. + + """ + def _exit_no_work(self): + if self.fm.loader.has_work(): + self.fm.notify('Not quitting: Tasks in progress: Use `quitall!` to force quit') + else: + self.fm.exit() + + def execute(self): + save_wd(self) + self._exit_no_work() diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/.gitignore b/home-manager/programs/ranger/plugins/ranger_fzf_filter/.gitignore new file mode 100644 index 0000000..846dc44 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/.gitignore @@ -0,0 +1,132 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Pycharm +.idea diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/LICENSE b/home-manager/programs/ranger/plugins/ranger_fzf_filter/LICENSE new file mode 100644 index 0000000..bd840f1 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 MuXiu1997 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/README.md b/home-manager/programs/ranger/plugins/ranger_fzf_filter/README.md new file mode 100644 index 0000000..6a65e17 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/README.md @@ -0,0 +1,47 @@ +# ranger-fzf-filter +This is a plugin for [`ranger`](https://github.com/ranger/ranger) that add a fuzzy filter. It depends on [`fzf`](https://github.com/junegunn/fzf) + +https://user-images.githubusercontent.com/49554020/173509108-dc3edca4-8949-4026-a3ca-0ba8dac9bbce.mp4 + + +## Install + +For ranger >= 1.9.3, use Git to clone this repository into your `~/.config/ranger/plugins` folder. For example: + +```sh +git clone git@github.com:MuXiu1997/ranger-fzf-filter.git ~/.config/ranger/plugins/ranger_fzf_filter +``` + +**Legacy Install** + +For ranger versions older than 1.9.3, or to install without Git, download `__init__.py` to your `~/.config/ranger/plugins` directory. For example: + +```shell +mkdir -p ~/.config/ranger/plugins +wget -O ~/.config/ranger/plugins/ranger_fzf_filter.py https://raw.githubusercontent.com/MuXiu1997/ranger-fzf-filter/main/__init__.py +``` + + + +## Usage + +Command: + +- `:fzf_filter [query]`: filtering files with fzf, see this [search syntax](https://github.com/junegunn/fzf#search-syntax) + + + +## Keyboard Shortcut + +Add a binding to your `~/.config/ranger/rc.conf` file to quickly use `:fzf_filter`: + +``` +map f console fzf_filter%space +``` + + + +## License + +[MIT](LICENSE) + diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/__init__.py b/home-manager/programs/ranger/plugins/ranger_fzf_filter/__init__.py new file mode 100644 index 0000000..b5d5b46 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/__init__.py @@ -0,0 +1,35 @@ +import ranger.api +import ranger.container.directory +# noinspection PyUnresolvedReferences +from .command import fzf_filter, KEY_FZF_FILTER + +# region overwrite hook_init +HOOK_INIT_OLD = ranger.api.hook_init + + +def hook_init(fm): + def clear_fzf_filter(signal): + if fm.settings.clear_filters_on_dir_change and signal.previous: + signal.previous.__dict__[KEY_FZF_FILTER] = None + signal.previous.refilter() + + fm.signal_bind('cd', clear_fzf_filter) + return HOOK_INIT_OLD(fm) + + +ranger.api.hook_init = hook_init +# endregion overwrite hook_init + +# region overwrite accept_file +ACCEPT_FILE_OLD = ranger.container.directory.accept_file + + +def accept_file(fobj, filters): + _fzf_filter = fobj.fm.thisdir.__dict__.get(KEY_FZF_FILTER, None) + if _fzf_filter: + filters.append(_fzf_filter) + return ACCEPT_FILE_OLD(fobj, filters) + + +ranger.container.directory.accept_file = accept_file +# endregion overwrite accept_file diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/command.py b/home-manager/programs/ranger/plugins/ranger_fzf_filter/command.py new file mode 100644 index 0000000..92aee83 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/command.py @@ -0,0 +1,59 @@ +import ranger.api.commands +from .filter import FzfFilter + +# noinspection PyUnreachableCode +# This is done to enhance auto-completion and inference in the editor. +if False: + import ranger.core.fm + +KEY_FZF_FILTER = 'fzf_filter' + + +# noinspection PyPep8Naming,PyUnresolvedReferences +class fzf_filter(ranger.api.commands.Command): + """ + :fzf_filter <query> + + This command allows you to use fzf fuzzy search to filter files and directories in the ranger. + """ + + def execute(self): + fm = self.fm # type: ranger.core.fm.FM + # Check if a filter is already set + _filter = fm.thisdir.__dict__.get(KEY_FZF_FILTER, None) + if isinstance(_filter, FzfFilter): + # If a filter is set, just update the query + _filter.set_query(self._get_query()) + else: + # If no filter is set, build a new one + fm.thisdir.__dict__[KEY_FZF_FILTER] = self._build_filter() + + fm.thisdir.refilter() + if self.quickly_executed: + fm.open_console(self.line) + + def cancel(self): + fm = self.fm # type: ranger.core.fm.FM + fm.thisdir.__dict__[KEY_FZF_FILTER] = None + fm.thisdir.refilter() + + def quick(self): + return True + + def _get_query(self): + """ + Get the search query. + + Returns: + str: The search query. + """ + return self.rest(1) + + def _build_filter(self): + """ + Build a new FzfFilter. + + Returns: + FzfFilter: A new FzfFilter object with the current directory and search query. + """ + return FzfFilter(self.fm.thisdir, self._get_query()) diff --git a/home-manager/programs/ranger/plugins/ranger_fzf_filter/filter.py b/home-manager/programs/ranger/plugins/ranger_fzf_filter/filter.py new file mode 100644 index 0000000..3d12756 --- /dev/null +++ b/home-manager/programs/ranger/plugins/ranger_fzf_filter/filter.py @@ -0,0 +1,84 @@ +import os.path +import subprocess + + +class FzfFilter: + """ + A filter class for FZF fuzzy search. + + Attributes: + thisdir (ranger.container.directory.Directory): The current directory. + query (str): The search query. + source (list[str]): List of relative paths of all files in the current directory. + result (list[str]): The result of fzf search. + """ + + def __init__(self, thisdir, query): + """ + Initialize the FzfFilter class. + + Args: + thisdir (ranger.container.directory.Directory): The current directory. + query (str): The search query. + """ + self.thisdir = thisdir + self.files_all = thisdir.files_all + + self.query = query + + self.source = [] + self.recalc_source() + + self.result = [] + self.recalc_result() + + def recalc_source(self): + """ + Recalculate the source list based on the files in the current directory. + """ + self.source = [f.relative_path for f in self.thisdir.files_all] + + def recalc_result(self): + """ + Recalculate the result list by executing the fzf command. + """ + cmd = subprocess.Popen( + ['fzf', '-f', self.query], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + stdout, _ = cmd.communicate('\n'.join(self.source).encode('utf-8')) + self.result = stdout.decode('utf-8').strip().splitlines() + + def set_query(self, query): + """ + Update the query and recalculate the result list. + + Args: + query (str): The new search query. + """ + self.query = query + self.recalc_result() + + def __call__(self, fobj): + """ + Perform the actual filtering. + + Args: + fobj (ranger.container.file.File | ranger.container.directory.Directory): The file or directory to check. + + Returns: + bool: True if the file or directory is in the result list, False otherwise. + """ + # Check if the files in the current directory have changed, and if so, recalculate source and result + if self.thisdir.files_all is not self.files_all: + self.files_all = self.thisdir.files_all + self.recalc_source() + self.recalc_result() + + # Ensure the relative path start of the file or directory is in the current directory + if os.path.relpath(fobj.path, fobj.relative_path) != '.': + return True + + # Check if the relative path of the file or directory is in the result list + return fobj.relative_path in self.result |
