├── .flake8
├── .gitignore
├── .pre-commit-config.yaml
├── LICENSE
├── README.md
├── poetry.lock
├── pyproject.toml
├── ranger_tmux
├── __init__.py
├── __main__.py
├── cwd_sync.py
├── cwd_track.py
├── drop.py
├── dropdown.py
├── open_in_window.py
├── plugin.py
├── set_window_name.py
├── splits.py
└── util.py
└── scripts
└── publish.py
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | select = B,B9,BLK,C4,D,DAR,E,F,I,S,TC,W
3 | ignore = E203,E501,W503,ANN101,ANN102,ANN204,S101,B010
4 | max-line-length = 88
5 | max-complexity = 10
6 | application-import-names = euporie,tests
7 | import-order-style = google
8 | docstring-convention = google
9 | docstring_style = google
10 | per-file-ignores = tests/*:S101
11 | strictness = short
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
98 | __pypackages__/
99 |
100 | # Celery stuff
101 | celerybeat-schedule
102 | celerybeat.pid
103 |
104 | # SageMath parsed files
105 | *.sage.py
106 |
107 | # Environments
108 | .env
109 | .venv
110 | env/
111 | venv/
112 | ENV/
113 | env.bak/
114 | venv.bak/
115 |
116 | # Spyder project settings
117 | .spyderproject
118 | .spyproject
119 |
120 | # Rope project settings
121 | .ropeproject
122 |
123 | # mkdocs documentation
124 | /site
125 |
126 | # mypy
127 | .mypy_cache/
128 | .dmypy.json
129 | dmypy.json
130 |
131 | # Pyre type checker
132 | .pyre/
133 |
134 | # pytype static type analyzer
135 | .pytype/
136 |
137 | # Cython debug symbols
138 | cython_debug/
139 | # Byte-compiled / optimized / DLL files
140 | __pycache__/
141 | *.py[cod]
142 | *$py.class
143 |
144 | # C extensions
145 | *.so
146 |
147 | # Distribution / packaging
148 | .Python
149 | build/
150 | develop-eggs/
151 | dist/
152 | downloads/
153 | eggs/
154 | .eggs/
155 | lib/
156 | lib64/
157 | parts/
158 | sdist/
159 | var/
160 | wheels/
161 | share/python-wheels/
162 | *.egg-info/
163 | .installed.cfg
164 | *.egg
165 | MANIFEST
166 |
167 | # PyInstaller
168 | # Usually these files are written by a python script from a template
169 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
170 | *.manifest
171 | *.spec
172 |
173 | # Installer logs
174 | pip-log.txt
175 | pip-delete-this-directory.txt
176 |
177 | # Unit test / coverage reports
178 | htmlcov/
179 | .tox/
180 | .nox/
181 | .coverage
182 | .coverage.*
183 | .cache
184 | nosetests.xml
185 | coverage.xml
186 | *.cover
187 | *.py,cover
188 | .hypothesis/
189 | .pytest_cache/
190 | cover/
191 |
192 | # Translations
193 | *.mo
194 | *.pot
195 |
196 | # Django stuff:
197 | *.log
198 | local_settings.py
199 | db.sqlite3
200 | db.sqlite3-journal
201 |
202 | # Flask stuff:
203 | instance/
204 | .webassets-cache
205 |
206 | # Scrapy stuff:
207 | .scrapy
208 |
209 | # Sphinx documentation
210 | docs/_build/
211 |
212 | # PyBuilder
213 | .pybuilder/
214 | target/
215 |
216 | # Jupyter Notebook
217 | .ipynb_checkpoints
218 |
219 | # IPython
220 | profile_default/
221 | ipython_config.py
222 |
223 | # pyenv
224 | # For a library or package, you might want to ignore these files since the code is
225 | # intended to run in multiple environments; otherwise, check them in:
226 | # .python-version
227 |
228 | # pipenv
229 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
230 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
231 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
232 | # install all needed dependencies.
233 | #Pipfile.lock
234 |
235 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
236 | __pypackages__/
237 |
238 | # Celery stuff
239 | celerybeat-schedule
240 | celerybeat.pid
241 |
242 | # SageMath parsed files
243 | *.sage.py
244 |
245 | # Environments
246 | .env
247 | .venv
248 | env/
249 | venv/
250 | ENV/
251 | env.bak/
252 | venv.bak/
253 |
254 | # Spyder project settings
255 | .spyderproject
256 | .spyproject
257 |
258 | # Rope project settings
259 | .ropeproject
260 |
261 | # mkdocs documentation
262 | /site
263 |
264 | # mypy
265 | .mypy_cache/
266 | .dmypy.json
267 | dmypy.json
268 |
269 | # Pyre type checker
270 | .pyre/
271 |
272 | # pytype static type analyzer
273 | .pytype/
274 |
275 | # Cython debug symbols
276 | cython_debug/
277 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v3.4.0
4 | hooks:
5 | - id: fix-byte-order-marker
6 | - id: fix-encoding-pragma
7 | - id: check-yaml
8 | - id: end-of-file-fixer
9 | - id: trailing-whitespace
10 | - repo: https://github.com/pre-commit/mirrors-prettier
11 | rev: v2.2.1
12 | hooks:
13 | - id: prettier
14 | - repo: local
15 | hooks:
16 | - id: black
17 | name: black
18 | entry: poetry run black
19 | language: system
20 | types: [python]
21 | - id: flake8
22 | name: flake8
23 | entry: poetry run flake8
24 | language: system
25 | types: [python]
26 | - id: isort
27 | name: isort
28 | entry: poetry run isort
29 | args: ["--profile", "black", "--filter-files"]
30 | language: system
31 | types: [python]
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Josiah Outram Halstead
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do 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 | # ranger-tmux
2 |
3 | Tmux integration for ranger
4 |
5 | ## Install
6 |
7 | To install this plugin, clone the respository into ranger's plugins folder, or install it with pip:
8 |
9 | ```
10 | pip install ranger-tmux
11 | # Then run this to install the package as a ranger plugin:
12 | python -m ranger_tmux install
13 | ```
14 |
15 | ## Features
16 |
17 |
18 |
19 | - Open files from ranger in a new tmux window or pane
20 | - Make your terminal track ranger's directory
21 | - Make ranger track your terminal's directory
22 | - Set tmux window title to show ranger is running
23 | - Drop down file-manager in your tmux session
24 | - Easily split a ranger pane to launch a shell in the current folder
25 |
26 | ### Other pane tracking & syncing
27 |
28 | This plugin enables syncing of the current working directory between ranger and other tmux panes in the same window.
29 |
30 | The pane to be used for syncing or tracking is determined in the following order:
31 |
32 | 1. A marked pane;
33 | 2. The currently selected pane;
34 | 3. The last selected pane;
35 | 4. The next pane.
36 |
37 | Ranger will only sync its working directory to another pane if the process running in another pane does not have any child processes. This prevents ranger typing `cd` commands if you have launched a text editor from the shell in the other pane.
38 |
39 | ### Drop-down ranger
40 |
41 | When installing the plugin, you will be asked if you want to install a key-binding in `~/.tmux.conf` for drop-down ranger. This allows you to toggle ranger in a drop-down tmux pane in the current window. This can be run manually by running `python -m ranger_tmux.drop` in a tmux session.
42 |
43 | The key binding can be installed by running `python -m ranger_tmux --tmux install`, or by running the `:install_tmux_dropdown_shortcut` command in ranger (or typing the `xh` shortcut). The default key-binding installed is `prefix, backspace`, but this can be changed by editing the lines added to `~/.tmux.conf`.
44 |
45 | ## Shortcut keys
46 |
47 | | Key Sequence | Command |
48 | | ------------ | --------------------------------------------------------------------------------- |
49 | | `xc` | Change the current working directory in the other pane to the directory in ranger |
50 | | `xd` | Change ranger's current directory to the directory of the other pane |
51 | | `xs` | Toggle syncing of ranger's current directory to the other pane |
52 | | `xt` | Toggle tracking of the other pane's working directory to tmux |
53 | | `xw` | Toggle opening files in a new tmux window |
54 | | `xi` | Toggle setting the tmux window's title to "ranger" when ranger is running |
55 | | `xe` | Open the selected file with rifle in a new tmux window |
56 | | `x\|` | Split ranger's current tmux pane vertially |
57 | | `x-` | Split ranger's current tmux pane horizontally |
58 | | `xh` | Adds the dropdown shortcut to `~/.tmux.conf` |
59 |
60 | ## Settings
61 |
62 | This plugin adds several settings to ranger:
63 |
64 | | Setting | Type | Default | Meaning |
65 | | ------------------------- | ----- | ------- | ---------------------------------------------------------------------------------------- |
66 | | `tmux_cwd_sync` | bool | False | When True, ranger's current directory is synced to the other pane |
67 | | `tmux_cwd_sync_now_focus` | bool | False | When True, the other pane will be focused after manually syncing it with ranger |
68 | | `tmux_cwd_track` | bool | False | When True, ranger's current directory tracks the other pane |
69 | | `tmux_cwd_track_interval` | float | 0.5 | Time between checks of the directory of the other pane when tracking |
70 | | `tmux_open_in_window` | bool | True | When True, files opened with ranger will open in a new tmux window |
71 | | `tmux_set_title` | bool | True | When True, the tmux window will be renamed to "ranger" when ranger is running |
72 | | `tmux_dropdown_percent` | int | 60 | The height of the pane created when the drop-down tmux key-binding is installed and used |
73 | | `tmux_dropdown_animate` | bool | True | When True, dropped-down ranger will grow / shrink when summoned |
74 | | `tmux_dropdown_duration` | float | 100 | Drop-down animation time in miliseconds |
75 |
76 | The default values can be modified by setting them in `~/.config/ranger/rc.conf`, e.g.:
77 |
78 | ```
79 | set tmux_cwd_sync true
80 | set tmux_cwd_track true
81 | set tmux_set_title true
82 | set tmux_open_in_window true
83 | set tmux_dropdown_percent 60
84 | ```
85 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "appdirs"
3 | version = "1.4.4"
4 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
5 | category = "dev"
6 | optional = false
7 | python-versions = "*"
8 |
9 | [[package]]
10 | name = "backports.functools-lru-cache"
11 | version = "1.6.4"
12 | description = "Backport of functools.lru_cache"
13 | category = "dev"
14 | optional = false
15 | python-versions = ">=2.6"
16 |
17 | [package.extras]
18 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
19 | testing = ["pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-checkdocs (>=2.4)"]
20 |
21 | [[package]]
22 | name = "black"
23 | version = "20.8b1"
24 | description = "The uncompromising code formatter."
25 | category = "dev"
26 | optional = false
27 | python-versions = ">=3.6"
28 |
29 | [package.dependencies]
30 | appdirs = "*"
31 | click = ">=7.1.2"
32 | dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""}
33 | mypy-extensions = ">=0.4.3"
34 | pathspec = ">=0.6,<1"
35 | regex = ">=2020.1.8"
36 | toml = ">=0.10.1"
37 | typed-ast = ">=1.4.0"
38 | typing-extensions = ">=3.7.4"
39 |
40 | [package.extras]
41 | colorama = ["colorama (>=0.4.3)"]
42 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
43 |
44 | [[package]]
45 | name = "click"
46 | version = "8.0.3"
47 | description = "Composable command line interface toolkit"
48 | category = "dev"
49 | optional = false
50 | python-versions = ">=3.6"
51 |
52 | [package.dependencies]
53 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
54 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
55 |
56 | [[package]]
57 | name = "colorama"
58 | version = "0.4.4"
59 | description = "Cross-platform colored terminal text."
60 | category = "dev"
61 | optional = false
62 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
63 |
64 | [[package]]
65 | name = "configparser"
66 | version = "4.0.2"
67 | description = "Updated configparser from Python 3.7 for Python 2.6+."
68 | category = "main"
69 | optional = false
70 | python-versions = ">=2.6"
71 |
72 | [package.extras]
73 | docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
74 | testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2)", "pytest-flake8", "pytest-black-multipy"]
75 |
76 | [[package]]
77 | name = "contextlib2"
78 | version = "0.6.0.post1"
79 | description = "Backports and enhancements for the contextlib module"
80 | category = "main"
81 | optional = false
82 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
83 |
84 | [[package]]
85 | name = "dataclasses"
86 | version = "0.8"
87 | description = "A backport of the dataclasses module for Python 3.6"
88 | category = "dev"
89 | optional = false
90 | python-versions = ">=3.6, <3.7"
91 |
92 | [[package]]
93 | name = "enum34"
94 | version = "1.1.10"
95 | description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4"
96 | category = "dev"
97 | optional = false
98 | python-versions = "*"
99 |
100 | [[package]]
101 | name = "flake8"
102 | version = "3.9.2"
103 | description = "the modular source code checker: pep8 pyflakes and co"
104 | category = "dev"
105 | optional = false
106 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
107 |
108 | [package.dependencies]
109 | configparser = {version = "*", markers = "python_version < \"3.2\""}
110 | enum34 = {version = "*", markers = "python_version < \"3.4\""}
111 | functools32 = {version = "*", markers = "python_version < \"3.2\""}
112 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
113 | mccabe = ">=0.6.0,<0.7.0"
114 | pycodestyle = ">=2.7.0,<2.8.0"
115 | pyflakes = ">=2.3.0,<2.4.0"
116 | typing = {version = "*", markers = "python_version < \"3.5\""}
117 |
118 | [[package]]
119 | name = "flake8-black"
120 | version = "0.2.3"
121 | description = "flake8 plugin to call black as a code style validator"
122 | category = "dev"
123 | optional = false
124 | python-versions = "*"
125 |
126 | [package.dependencies]
127 | black = "*"
128 | flake8 = ">=3.0.0"
129 | toml = "*"
130 |
131 | [[package]]
132 | name = "functools32"
133 | version = "3.2.3-2"
134 | description = "Backport of the functools module from Python 3.2.3 for use on 2.7 and PyPy."
135 | category = "dev"
136 | optional = false
137 | python-versions = "*"
138 |
139 | [[package]]
140 | name = "futures"
141 | version = "3.3.0"
142 | description = "Backport of the concurrent.futures package from Python 3"
143 | category = "dev"
144 | optional = false
145 | python-versions = ">=2.6, <3"
146 |
147 | [[package]]
148 | name = "importlib-metadata"
149 | version = "2.1.2"
150 | description = "Read metadata from Python packages"
151 | category = "main"
152 | optional = false
153 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
154 |
155 | [package.dependencies]
156 | configparser = {version = ">=3.5", markers = "python_version < \"3\""}
157 | contextlib2 = {version = "*", markers = "python_version < \"3\""}
158 | pathlib2 = {version = "*", markers = "python_version < \"3\""}
159 | zipp = ">=0.5"
160 |
161 | [package.extras]
162 | docs = ["sphinx", "rst.linker"]
163 | testing = ["packaging", "pep517", "unittest2", "importlib-resources (>=1.3)"]
164 |
165 | [[package]]
166 | name = "importlib-resources"
167 | version = "3.3.1"
168 | description = "Read resources from Python packages"
169 | category = "main"
170 | optional = false
171 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
172 |
173 | [package.dependencies]
174 | contextlib2 = {version = "*", markers = "python_version < \"3\""}
175 | pathlib2 = {version = "*", markers = "python_version < \"3\""}
176 | singledispatch = {version = "*", markers = "python_version < \"3.4\""}
177 | typing = {version = "*", markers = "python_version < \"3.5\""}
178 | zipp = {version = ">=0.4", markers = "python_version < \"3.8\""}
179 |
180 | [package.extras]
181 | docs = ["sphinx", "rst.linker", "jaraco.packaging"]
182 |
183 | [[package]]
184 | name = "isort"
185 | version = "4.3.21"
186 | description = "A Python utility / library to sort Python imports."
187 | category = "dev"
188 | optional = false
189 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
190 |
191 | [package.dependencies]
192 | "backports.functools-lru-cache" = {version = "*", markers = "python_version < \"3.2\""}
193 | futures = {version = "*", markers = "python_version < \"3.2\""}
194 |
195 | [package.extras]
196 | pipfile = ["pipreqs", "requirementslib"]
197 | pyproject = ["toml"]
198 | requirements = ["pipreqs", "pip-api"]
199 | xdg_home = ["appdirs (>=1.4.0)"]
200 |
201 | [[package]]
202 | name = "mccabe"
203 | version = "0.6.1"
204 | description = "McCabe checker, plugin for flake8"
205 | category = "dev"
206 | optional = false
207 | python-versions = "*"
208 |
209 | [[package]]
210 | name = "mypy-extensions"
211 | version = "0.4.3"
212 | description = "Experimental type system extensions for programs checked with the mypy typechecker."
213 | category = "dev"
214 | optional = false
215 | python-versions = "*"
216 |
217 | [[package]]
218 | name = "pathlib2"
219 | version = "2.3.6"
220 | description = "Object-oriented filesystem paths"
221 | category = "main"
222 | optional = false
223 | python-versions = "*"
224 |
225 | [package.dependencies]
226 | scandir = {version = "*", markers = "python_version < \"3.5\""}
227 | six = "*"
228 |
229 | [[package]]
230 | name = "pathspec"
231 | version = "0.9.0"
232 | description = "Utility library for gitignore style pattern matching of file paths."
233 | category = "dev"
234 | optional = false
235 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
236 |
237 | [[package]]
238 | name = "psutil"
239 | version = "5.8.0"
240 | description = "Cross-platform lib for process and system monitoring in Python."
241 | category = "main"
242 | optional = false
243 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
244 |
245 | [package.extras]
246 | test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
247 |
248 | [[package]]
249 | name = "pycodestyle"
250 | version = "2.7.0"
251 | description = "Python style guide checker"
252 | category = "dev"
253 | optional = false
254 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
255 |
256 | [[package]]
257 | name = "pyflakes"
258 | version = "2.3.1"
259 | description = "passive checker of Python programs"
260 | category = "dev"
261 | optional = false
262 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
263 |
264 | [[package]]
265 | name = "ranger-fm"
266 | version = "1.9.3"
267 | description = "Vim-like file manager"
268 | category = "main"
269 | optional = false
270 | python-versions = "*"
271 |
272 | [[package]]
273 | name = "regex"
274 | version = "2021.11.10"
275 | description = "Alternative regular expression module, to replace re."
276 | category = "dev"
277 | optional = false
278 | python-versions = "*"
279 |
280 | [[package]]
281 | name = "scandir"
282 | version = "1.10.0"
283 | description = "scandir, a better directory iterator and faster os.walk()"
284 | category = "main"
285 | optional = false
286 | python-versions = "*"
287 |
288 | [[package]]
289 | name = "singledispatch"
290 | version = "3.7.0"
291 | description = "Backport functools.singledispatch from Python 3.4 to Python 2.6-3.3."
292 | category = "main"
293 | optional = false
294 | python-versions = ">=2.6"
295 |
296 | [package.dependencies]
297 | six = "*"
298 |
299 | [package.extras]
300 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
301 | testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "unittest2", "pytest-checkdocs (>=2.4)"]
302 |
303 | [[package]]
304 | name = "six"
305 | version = "1.16.0"
306 | description = "Python 2 and 3 compatibility utilities"
307 | category = "main"
308 | optional = false
309 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
310 |
311 | [[package]]
312 | name = "toml"
313 | version = "0.10.2"
314 | description = "Python Library for Tom's Obvious, Minimal Language"
315 | category = "dev"
316 | optional = false
317 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
318 |
319 | [[package]]
320 | name = "typed-ast"
321 | version = "1.5.1"
322 | description = "a fork of Python 2 and 3 ast modules with type comment support"
323 | category = "dev"
324 | optional = false
325 | python-versions = ">=3.6"
326 |
327 | [[package]]
328 | name = "typing"
329 | version = "3.10.0.0"
330 | description = "Type Hints for Python"
331 | category = "main"
332 | optional = false
333 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <3.5"
334 |
335 | [[package]]
336 | name = "typing-extensions"
337 | version = "4.0.1"
338 | description = "Backported and Experimental Type Hints for Python 3.6+"
339 | category = "dev"
340 | optional = false
341 | python-versions = ">=3.6"
342 |
343 | [[package]]
344 | name = "zipp"
345 | version = "1.2.0"
346 | description = "Backport of pathlib-compatible object wrapper for zip files"
347 | category = "main"
348 | optional = false
349 | python-versions = ">=2.7"
350 |
351 | [package.dependencies]
352 | contextlib2 = {version = "*", markers = "python_version < \"3.4\""}
353 |
354 | [package.extras]
355 | docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
356 | testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"]
357 |
358 | [metadata]
359 | lock-version = "1.1"
360 | python-versions = ">=2.7 <3 || >=3.6"
361 | content-hash = "8e58d0b0056e011a6067fafee1167544b1a87f67cce5e7239e6692767ca75257"
362 |
363 | [metadata.files]
364 | appdirs = [
365 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
366 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
367 | ]
368 | "backports.functools-lru-cache" = [
369 | {file = "backports.functools_lru_cache-1.6.4-py2.py3-none-any.whl", hash = "sha256:dbead04b9daa817909ec64e8d2855fb78feafe0b901d4568758e3a60559d8978"},
370 | {file = "backports.functools_lru_cache-1.6.4.tar.gz", hash = "sha256:d5ed2169378b67d3c545e5600d363a923b09c456dab1593914935a68ad478271"},
371 | ]
372 | black = [
373 | {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
374 | ]
375 | click = [
376 | {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"},
377 | {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"},
378 | ]
379 | colorama = [
380 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
381 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
382 | ]
383 | configparser = [
384 | {file = "configparser-4.0.2-py2.py3-none-any.whl", hash = "sha256:254c1d9c79f60c45dfde850850883d5aaa7f19a23f13561243a050d5a7c3fe4c"},
385 | {file = "configparser-4.0.2.tar.gz", hash = "sha256:c7d282687a5308319bf3d2e7706e575c635b0a470342641c93bea0ea3b5331df"},
386 | ]
387 | contextlib2 = [
388 | {file = "contextlib2-0.6.0.post1-py2.py3-none-any.whl", hash = "sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"},
389 | {file = "contextlib2-0.6.0.post1.tar.gz", hash = "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e"},
390 | ]
391 | dataclasses = [
392 | {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"},
393 | {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"},
394 | ]
395 | enum34 = [
396 | {file = "enum34-1.1.10-py2-none-any.whl", hash = "sha256:a98a201d6de3f2ab3db284e70a33b0f896fbf35f8086594e8c9e74b909058d53"},
397 | {file = "enum34-1.1.10-py3-none-any.whl", hash = "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328"},
398 | {file = "enum34-1.1.10.tar.gz", hash = "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"},
399 | ]
400 | flake8 = [
401 | {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
402 | {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
403 | ]
404 | flake8-black = [
405 | {file = "flake8-black-0.2.3.tar.gz", hash = "sha256:c199844bc1b559d91195ebe8620216f21ed67f2cc1ff6884294c91a0d2492684"},
406 | {file = "flake8_black-0.2.3-py3-none-any.whl", hash = "sha256:cc080ba5b3773b69ba102b6617a00cc4ecbad8914109690cfda4d565ea435d96"},
407 | ]
408 | functools32 = [
409 | {file = "functools32-3.2.3-2.tar.gz", hash = "sha256:f6253dfbe0538ad2e387bd8fdfd9293c925d63553f5813c4e587745416501e6d"},
410 | {file = "functools32-3.2.3-2.zip", hash = "sha256:89d824aa6c358c421a234d7f9ee0bd75933a67c29588ce50aaa3acdf4d403fa0"},
411 | ]
412 | futures = [
413 | {file = "futures-3.3.0-py2-none-any.whl", hash = "sha256:49b3f5b064b6e3afc3316421a3f25f66c137ae88f068abbf72830170033c5e16"},
414 | {file = "futures-3.3.0.tar.gz", hash = "sha256:7e033af76a5e35f58e56da7a91e687706faf4e7bdfb2cbc3f2cca6b9bcda9794"},
415 | ]
416 | importlib-metadata = [
417 | {file = "importlib_metadata-2.1.2-py2.py3-none-any.whl", hash = "sha256:cd6a92d78385dd145f5f233b3a6919acf5e8e43922aa9b9dbe78573e3540eb56"},
418 | {file = "importlib_metadata-2.1.2.tar.gz", hash = "sha256:09db40742204610ef6826af16e49f0479d11d0d54687d0169ff7fddf8b3f557f"},
419 | ]
420 | importlib-resources = [
421 | {file = "importlib_resources-3.3.1-py2.py3-none-any.whl", hash = "sha256:42068585cc5e8c2bf0a17449817401102a5125cbfbb26bb0f43cde1568f6f2df"},
422 | {file = "importlib_resources-3.3.1.tar.gz", hash = "sha256:0ed250dbd291947d1a298e89f39afcc477d5a6624770503034b72588601bcc05"},
423 | ]
424 | isort = [
425 | {file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
426 | {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
427 | ]
428 | mccabe = [
429 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
430 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
431 | ]
432 | mypy-extensions = [
433 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
434 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
435 | ]
436 | pathlib2 = [
437 | {file = "pathlib2-2.3.6-py2.py3-none-any.whl", hash = "sha256:3a130b266b3a36134dcc79c17b3c7ac9634f083825ca6ea9d8f557ee6195c9c8"},
438 | {file = "pathlib2-2.3.6.tar.gz", hash = "sha256:7d8bcb5555003cdf4a8d2872c538faa3a0f5d20630cb360e518ca3b981795e5f"},
439 | ]
440 | pathspec = [
441 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
442 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
443 | ]
444 | psutil = [
445 | {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"},
446 | {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"},
447 | {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"},
448 | {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"},
449 | {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"},
450 | {file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"},
451 | {file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"},
452 | {file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"},
453 | {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"},
454 | {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"},
455 | {file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"},
456 | {file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"},
457 | {file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"},
458 | {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"},
459 | {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"},
460 | {file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"},
461 | {file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"},
462 | {file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"},
463 | {file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"},
464 | {file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"},
465 | {file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"},
466 | {file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"},
467 | {file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"},
468 | {file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"},
469 | {file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"},
470 | {file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"},
471 | {file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"},
472 | {file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"},
473 | ]
474 | pycodestyle = [
475 | {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
476 | {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
477 | ]
478 | pyflakes = [
479 | {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
480 | {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
481 | ]
482 | ranger-fm = [
483 | {file = "ranger-fm-1.9.3.tar.gz", hash = "sha256:9476ed1971c641f4ba3dde1b8b80387f0216fcde3507426d06871f9d7189ac5e"},
484 | ]
485 | regex = [
486 | {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"},
487 | {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"},
488 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"},
489 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"},
490 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"},
491 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"},
492 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"},
493 | {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"},
494 | {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9ed0b1e5e0759d6b7f8e2f143894b2a7f3edd313f38cf44e1e15d360e11749b"},
495 | {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:473e67837f786404570eae33c3b64a4b9635ae9f00145250851a1292f484c063"},
496 | {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2fee3ed82a011184807d2127f1733b4f6b2ff6ec7151d83ef3477f3b96a13d03"},
497 | {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d5fd67df77bab0d3f4ea1d7afca9ef15c2ee35dfb348c7b57ffb9782a6e4db6e"},
498 | {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5d408a642a5484b9b4d11dea15a489ea0928c7e410c7525cd892f4d04f2f617b"},
499 | {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"},
500 | {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"},
501 | {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"},
502 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"},
503 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"},
504 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"},
505 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"},
506 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"},
507 | {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"},
508 | {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:74cbeac0451f27d4f50e6e8a8f3a52ca074b5e2da9f7b505c4201a57a8ed6286"},
509 | {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:3598893bde43091ee5ca0a6ad20f08a0435e93a69255eeb5f81b85e81e329264"},
510 | {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:50a7ddf3d131dc5633dccdb51417e2d1910d25cbcf842115a3a5893509140a3a"},
511 | {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:61600a7ca4bcf78a96a68a27c2ae9389763b5b94b63943d5158f2a377e09d29a"},
512 | {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:563d5f9354e15e048465061509403f68424fef37d5add3064038c2511c8f5e00"},
513 | {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"},
514 | {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"},
515 | {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"},
516 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"},
517 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"},
518 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"},
519 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"},
520 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"},
521 | {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"},
522 | {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:42b50fa6666b0d50c30a990527127334d6b96dd969011e843e726a64011485da"},
523 | {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6e1d2cc79e8dae442b3fa4a26c5794428b98f81389af90623ffcc650ce9f6732"},
524 | {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:0416f7399e918c4b0e074a0f66e5191077ee2ca32a0f99d4c187a62beb47aa05"},
525 | {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ce298e3d0c65bd03fa65ffcc6db0e2b578e8f626d468db64fdf8457731052942"},
526 | {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dc07f021ee80510f3cd3af2cad5b6a3b3a10b057521d9e6aaeb621730d320c5a"},
527 | {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"},
528 | {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"},
529 | {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"},
530 | {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"},
531 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"},
532 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"},
533 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"},
534 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"},
535 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"},
536 | {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"},
537 | {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f5be7805e53dafe94d295399cfbe5227f39995a997f4fd8539bf3cbdc8f47ca8"},
538 | {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a955b747d620a50408b7fdf948e04359d6e762ff8a85f5775d907ceced715129"},
539 | {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:139a23d1f5d30db2cc6c7fd9c6d6497872a672db22c4ae1910be22d4f4b2068a"},
540 | {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ca49e1ab99593438b204e00f3970e7a5f70d045267051dfa6b5f4304fcfa1dbf"},
541 | {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96fc32c16ea6d60d3ca7f63397bff5c75c5a562f7db6dec7d412f7c4d2e78ec0"},
542 | {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"},
543 | {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"},
544 | {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"},
545 | {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"},
546 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"},
547 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"},
548 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"},
549 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"},
550 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"},
551 | {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"},
552 | {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cd410a1cbb2d297c67d8521759ab2ee3f1d66206d2e4328502a487589a2cb21b"},
553 | {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e6096b0688e6e14af6a1b10eaad86b4ff17935c49aa774eac7c95a57a4e8c296"},
554 | {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:529801a0d58809b60b3531ee804d3e3be4b412c94b5d267daa3de7fadef00f49"},
555 | {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f594b96fe2e0821d026365f72ac7b4f0b487487fb3d4aaf10dd9d97d88a9737"},
556 | {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2409b5c9cef7054dde93a9803156b411b677affc84fca69e908b1cb2c540025d"},
557 | {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"},
558 | {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"},
559 | {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"},
560 | ]
561 | scandir = [
562 | {file = "scandir-1.10.0-cp27-cp27m-win32.whl", hash = "sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188"},
563 | {file = "scandir-1.10.0-cp27-cp27m-win_amd64.whl", hash = "sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac"},
564 | {file = "scandir-1.10.0-cp34-cp34m-win32.whl", hash = "sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f"},
565 | {file = "scandir-1.10.0-cp34-cp34m-win_amd64.whl", hash = "sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e"},
566 | {file = "scandir-1.10.0-cp35-cp35m-win32.whl", hash = "sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f"},
567 | {file = "scandir-1.10.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32"},
568 | {file = "scandir-1.10.0-cp36-cp36m-win32.whl", hash = "sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022"},
569 | {file = "scandir-1.10.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4"},
570 | {file = "scandir-1.10.0-cp37-cp37m-win32.whl", hash = "sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173"},
571 | {file = "scandir-1.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d"},
572 | {file = "scandir-1.10.0.tar.gz", hash = "sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae"},
573 | ]
574 | singledispatch = [
575 | {file = "singledispatch-3.7.0-py2.py3-none-any.whl", hash = "sha256:bc77afa97c8a22596d6d4fc20f1b7bdd2b86edc2a65a4262bdd7cc3cc19aa989"},
576 | {file = "singledispatch-3.7.0.tar.gz", hash = "sha256:c1a4d5c1da310c3fd8fccfb8d4e1cb7df076148fd5d858a819e37fffe44f3092"},
577 | ]
578 | six = [
579 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
580 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
581 | ]
582 | toml = [
583 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
584 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
585 | ]
586 | typed-ast = [
587 | {file = "typed_ast-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d8314c92414ce7481eee7ad42b353943679cf6f30237b5ecbf7d835519e1212"},
588 | {file = "typed_ast-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b53ae5de5500529c76225d18eeb060efbcec90ad5e030713fe8dab0fb4531631"},
589 | {file = "typed_ast-1.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:24058827d8f5d633f97223f5148a7d22628099a3d2efe06654ce872f46f07cdb"},
590 | {file = "typed_ast-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a6d495c1ef572519a7bac9534dbf6d94c40e5b6a608ef41136133377bba4aa08"},
591 | {file = "typed_ast-1.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:de4ecae89c7d8b56169473e08f6bfd2df7f95015591f43126e4ea7865928677e"},
592 | {file = "typed_ast-1.5.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:256115a5bc7ea9e665c6314ed6671ee2c08ca380f9d5f130bd4d2c1f5848d695"},
593 | {file = "typed_ast-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:7c42707ab981b6cf4b73490c16e9d17fcd5227039720ca14abe415d39a173a30"},
594 | {file = "typed_ast-1.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:71dcda943a471d826ea930dd449ac7e76db7be778fcd722deb63642bab32ea3f"},
595 | {file = "typed_ast-1.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4f30a2bcd8e68adbb791ce1567fdb897357506f7ea6716f6bbdd3053ac4d9471"},
596 | {file = "typed_ast-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ca9e8300d8ba0b66d140820cf463438c8e7b4cdc6fd710c059bfcfb1531d03fb"},
597 | {file = "typed_ast-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9caaf2b440efb39ecbc45e2fabde809cbe56272719131a6318fd9bf08b58e2cb"},
598 | {file = "typed_ast-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9bcad65d66d594bffab8575f39420fe0ee96f66e23c4d927ebb4e24354ec1af"},
599 | {file = "typed_ast-1.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:591bc04e507595887160ed7aa8d6785867fb86c5793911be79ccede61ae96f4d"},
600 | {file = "typed_ast-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:a80d84f535642420dd17e16ae25bb46c7f4c16ee231105e7f3eb43976a89670a"},
601 | {file = "typed_ast-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:38cf5c642fa808300bae1281460d4f9b7617cf864d4e383054a5ef336e344d32"},
602 | {file = "typed_ast-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b6ab14c56bc9c7e3c30228a0a0b54b915b1579613f6e463ba6f4eb1382e7fd4"},
603 | {file = "typed_ast-1.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2b8d7007f6280e36fa42652df47087ac7b0a7d7f09f9468f07792ba646aac2d"},
604 | {file = "typed_ast-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:b6d17f37f6edd879141e64a5db17b67488cfeffeedad8c5cec0392305e9bc775"},
605 | {file = "typed_ast-1.5.1.tar.gz", hash = "sha256:484137cab8ecf47e137260daa20bafbba5f4e3ec7fda1c1e69ab299b75fa81c5"},
606 | ]
607 | typing = [
608 | {file = "typing-3.10.0.0-py2-none-any.whl", hash = "sha256:c7219ef20c5fbf413b4567092adfc46fa6203cb8454eda33c3fc1afe1398a308"},
609 | {file = "typing-3.10.0.0-py3-none-any.whl", hash = "sha256:12fbdfbe7d6cca1a42e485229afcb0b0c8259258cfb919b8a5e2a5c953742f89"},
610 | {file = "typing-3.10.0.0.tar.gz", hash = "sha256:13b4ad211f54ddbf93e5901a9967b1e07720c1d1b78d596ac6a439641aa1b130"},
611 | ]
612 | typing-extensions = [
613 | {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
614 | {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
615 | ]
616 | zipp = [
617 | {file = "zipp-1.2.0-py2.py3-none-any.whl", hash = "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"},
618 | {file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"},
619 | ]
620 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "ranger-tmux"
3 | version = "1.0.8"
4 | description = "Tmux integration for ranger"
5 | authors = ["Josiah Outram Halstead "]
6 | license = "MIT"
7 | readme = "README.md"
8 | homepage = "https://github.com/joouha/ranger_tmux"
9 | classifiers = [
10 | "Environment :: Plugins",
11 | ]
12 |
13 | [tool.poetry.dependencies]
14 | python = ">=2.7 <3 || >=3.6"
15 | ranger-fm = "^1.9.3"
16 | psutil = "^5.8.0"
17 | pathlib2 = {version = "^2.3.6", python = ">2.7 <3"}
18 | importlib-resources = {version = ">=3.3.1", python = ">=2.7,<3.9"}
19 | importlib-metadata = {version = ">=2.1.2", python = ">=2.7,<3.8"}
20 |
21 | [tool.poetry.dev-dependencies]
22 | flake8 = "^3.9.2"
23 | black = {version = "^20.8b1", python = ">=3.6"}
24 | flake8-black = "^0.2.3"
25 | isort = ">=4.3.21"
26 |
27 | [build-system]
28 | requires = ["poetry-core>=1.0.0"]
29 | build-backend = "poetry.core.masonry.api"
30 |
31 | [tool.poetry.plugins."ranger.plugins"]
32 | "ranger_tmux" = "ranger_tmux.plugin"
33 |
--------------------------------------------------------------------------------
/ranger_tmux/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """A tmux plugin for ranger, and ranger integration for tmux."""
3 | __version__ = "1.0.8"
4 |
--------------------------------------------------------------------------------
/ranger_tmux/__main__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import print_function
3 |
4 | import argparse
5 | import os
6 | import sys
7 |
8 | try:
9 | from pathlib import Path
10 | except ImportError:
11 | from pathlib2 import Path
12 |
13 | try:
14 | import importlib_resources
15 | except ImportError:
16 | import importlib.resources as importlib_resources
17 |
18 | TMUX_CONFIG = [
19 | ["#-#-#", "start_of_ranger_tmux_config", "#-#-#"],
20 | [
21 | "bind-key",
22 | "Bspace",
23 | "run-shell",
24 | "-b",
25 | "{} -m ranger_tmux.drop".format(sys.executable),
26 | ],
27 | # [
28 | # "bind-key",
29 | # "Tab",
30 | # "split-pane",
31 | # "-hbf",
32 | # "-l",
33 | # "30",
34 | # f"{util.get_ranger_script()}"
35 | # ' --cmd="set tmux_cwd_track True"'
36 | # ' --cmd="set viewmode multipane"'
37 | # " --cmd=tmux_cwd_track_now",
38 | # ],
39 | ["#-#-#", "end_of_ranger_tmux_config", "#-#-#"],
40 | ]
41 |
42 |
43 | def tmux_keybindings(install=True):
44 |
45 | tmux_user_config_path = Path.home() / ".tmux.conf"
46 | tmux_config_lines = [
47 | " ".join(
48 | [
49 | # Quote command components if they contain spaces
50 | ("'{}'".format(cmd) if " " in cmd else str(cmd))
51 | for cmd in line
52 | ]
53 | )
54 | for line in TMUX_CONFIG
55 | ]
56 | new_lines = []
57 | if tmux_user_config_path.exists():
58 | # Read existing lines
59 | with open(str(tmux_user_config_path), "r") as f:
60 | old_lines = [x.strip() for x in f.readlines()]
61 | # Search for tmux_ranger config in tmux config
62 | start_line = len(old_lines) + 1
63 | for i, line in enumerate(old_lines):
64 | if line == tmux_config_lines[0]:
65 | start_line = i
66 | break
67 | end_line = start_line
68 | for i in range(start_line, len(old_lines)):
69 | if old_lines[i] == tmux_config_lines[-1]:
70 | end_line = i
71 | break
72 | # Merge in the new config
73 | new_lines += old_lines[:start_line]
74 | if install:
75 | new_lines += tmux_config_lines
76 | new_lines += old_lines[end_line + 1 :]
77 | else:
78 | # No config at all, just use ours
79 | new_lines += tmux_config_lines
80 |
81 | # Write the updated tmux configuration file
82 | with open(str(tmux_user_config_path), "w") as f:
83 | f.write("\n".join(new_lines) + "\n")
84 |
85 | return TMUX_CONFIG[1:-1]
86 |
87 |
88 | def confirm_choice(query, options=("y", "n")):
89 | while True:
90 | confirm = input("{} ({})\n".format(query, "/".join(options)))
91 | if confirm.lower() in options:
92 | return confirm
93 | else:
94 | print("Invalid Option. Please Enter a Valid Option.")
95 |
96 |
97 | def install(args):
98 | print("Installing ranger_tmux plugin")
99 | print("- Plugin installation located at `{}`".format(args.plugin_script_path))
100 | if args.ranger_plugin_path.exists():
101 | print("- Removing existing symlink")
102 | if args.ranger_plugin_path.exists():
103 | args.ranger_plugin_path.unlink()
104 | print("- Creating symlink at `{}`".format(args.ranger_plugin_path))
105 | args.plugin_script_path.parent.mkdir(parents=True, exist_ok=True)
106 | args.ranger_plugin_path.symlink_to(args.plugin_script_path)
107 |
108 | if args.tmux is None:
109 | tmux = (
110 | confirm_choice(
111 | "Do you want to install a key-binding for"
112 | " drop-down ranger in `~/.tmux.conf`?",
113 | ("y", "n"),
114 | )
115 | == "y"
116 | )
117 | else:
118 | tmux = args.tmux
119 | if tmux:
120 | print("Installing tmux key-bindings")
121 | tmux_keybindings(install=True)
122 |
123 | print("Installation complete")
124 |
125 |
126 | def uninstall(args):
127 | print("Uninstalling ranger_tmux plugin")
128 | if args.ranger_plugin_path.exists():
129 | print("- Removing existing symlink `{}`".format(args.ranger_plugin_path))
130 | if args.ranger_plugin_path.exists():
131 | args.ranger_plugin_path.unlink()
132 |
133 | if args.tmux:
134 | print("Uninstalling tmux key-bindings")
135 | tmux_keybindings(install=False)
136 |
137 | print("Uninstallation complete")
138 |
139 |
140 | def reinstall(args):
141 | uninstall(args)
142 | install(args)
143 |
144 |
145 | def main():
146 | parser = argparse.ArgumentParser(description="Install ranger_tmux plugin")
147 | parser.add_argument(
148 | "--tmux",
149 | default=True,
150 | action="store_true",
151 | help="Install/uninstall key-bindings for tmux",
152 | )
153 | parser.add_argument(
154 | "--no-tmux",
155 | dest="tmux",
156 | action="store_false",
157 | help="Install/uninstall key-bindings for tmux",
158 | )
159 | subparsers = parser.add_subparsers(
160 | help="Command to run", dest="command" # , required=True
161 | )
162 | parser_install = subparsers.add_parser("install", help="Install plugin")
163 | parser_install.set_defaults(func=install)
164 | parser_uninstall = subparsers.add_parser("uninstall", help="Unnstall plugin")
165 | parser_uninstall.set_defaults(func=uninstall)
166 | parser_reinstall = subparsers.add_parser("reinstall", help="Re-install plugin")
167 | parser_reinstall.set_defaults(func=reinstall)
168 |
169 | parser.add_argument(
170 | "--plugin_script_path",
171 | help=argparse.SUPPRESS,
172 | default=importlib_resources.files("ranger_tmux").joinpath("plugin.py"),
173 | )
174 | parser.add_argument(
175 | "--ranger_plugin_path",
176 | help=argparse.SUPPRESS,
177 | default=Path(
178 | os.environ.get(
179 | "XDG_CONFIG_HOME",
180 | Path.home() / ".config",
181 | )
182 | )
183 | / "ranger"
184 | / "plugins"
185 | / "ranger_tmux.py",
186 | )
187 |
188 | args = parser.parse_args()
189 | args.func(args)
190 |
191 |
192 | if __name__ == "__main__":
193 | main()
194 |
--------------------------------------------------------------------------------
/ranger_tmux/cwd_sync.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """Add options and commands for syncing panes to ranger's current working directory."""
3 |
4 | from ranger.api.commands import Command
5 |
6 | from . import util
7 |
8 | SETTINGS = {
9 | "tmux_cwd_sync": {"key": "s", "type": bool},
10 | "tmux_cwd_sync_now_focus": {"type": bool},
11 | }
12 |
13 |
14 | class tmux_cwd_sync_now(Command):
15 | """Sync working directory of the "other" pane to match ranger's."""
16 |
17 | ranger_pane = None
18 |
19 | def execute(self):
20 | """Executes the command."""
21 | if self.ranger_pane:
22 | pane_id = util.select_shell_pane(self.ranger_pane)
23 | if pane_id:
24 | util.cd_pane(self.fm.thisdir.path, pane_id)
25 | if self.fm.settings.get("tmux_cwd_sync_now_focus", False):
26 | util.tmux("select-pane", "-t", pane_id)
27 |
28 |
29 | def tmux_cwd_sync_init(fm, setting, *args):
30 | """Allows ranger to sync it's cwd to the other tmux pane."""
31 | fm.execute_console('map xc eval fm.execute_console("tmux_cwd_sync_now")')
32 |
33 | # Find pane with current instance of ranger in it
34 | ranger_pane = util.get_ranger_pane()
35 | tmux_cwd_sync_now.ranger_pane = ranger_pane
36 |
37 | non_local = {"cd_signal_handler": None}
38 |
39 | def cd_hook(signal):
40 | if "new" in signal:
41 | pane_id = util.select_shell_pane(ranger_pane)
42 | if pane_id:
43 | util.cd_pane(signal.new, pane_id)
44 |
45 | def setting_signal_handler(signal):
46 | if signal.value:
47 | non_local["cd_signal_handler"] = fm.signal_bind("cd", cd_hook)
48 | else:
49 | if non_local["cd_signal_handler"]:
50 | fm.signal_unbind(non_local["cd_signal_handler"])
51 |
52 | fm.settings.signal_bind("setopt.{}".format(setting), setting_signal_handler)
53 |
54 | if fm.settings.__getitem__(setting):
55 | non_local["cd_signal_handler"] = fm.signal_bind("cd", cd_hook)
56 |
--------------------------------------------------------------------------------
/ranger_tmux/cwd_track.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import time
3 | from threading import Thread
4 |
5 | from ranger.api.commands import Command
6 |
7 | from . import util
8 |
9 | SETTINGS = {
10 | "tmux_cwd_track": {"key": "t", "type": bool},
11 | "tmux_cwd_track_interval": {"type": float, "default": 0.5},
12 | }
13 |
14 |
15 | class tmux_cwd_track_now(Command):
16 | ranger_pane = None
17 |
18 | def execute(self):
19 | if self.ranger_pane:
20 | pane_id = util.select_shell_pane(self.ranger_pane)
21 | if pane_id:
22 | new_path = util.tmux(
23 | "display", "-p", "-t", pane_id, "-F", "#{pane_current_path}"
24 | )
25 | if new_path != self.fm.thisdir.path:
26 | self.fm.cd(new_path)
27 |
28 |
29 | class MonitorPane(Thread):
30 | def __init__(self, fm, ranger_pane):
31 | Thread.__init__(self)
32 | self.daemon = True
33 | self.stopped = False
34 | self.fm = fm
35 | self.last_path = None
36 | self.ranger_pane = ranger_pane
37 | self.start()
38 |
39 | def run(self):
40 | while not self.stopped:
41 | pane_id = util.select_shell_pane(self.ranger_pane)
42 | if pane_id:
43 | new_path = util.tmux(
44 | "display", "-p", "-t", pane_id, "-F", "#{pane_current_path}"
45 | )
46 | if self.last_path != new_path and new_path != self.fm.thisdir.path:
47 | self.fm.cd(new_path)
48 | self.last_path = new_path
49 | time.sleep(self.fm.settings.get("tmux_cwd_track_interval", 1))
50 |
51 |
52 | def tmux_cwd_track_init(fm, setting, *args):
53 | """"""
54 |
55 | fm.execute_console('map xd eval fm.execute_console("tmux_cwd_track_now")')
56 |
57 | # Find pane with current instance of ranger in it
58 | ranger_pane = util.get_ranger_pane()
59 | tmux_cwd_track_now.ranger_pane = ranger_pane
60 |
61 | non_local = {"pane_monitor_thread": None}
62 |
63 | def enable():
64 | non_local["pane_monitor_thread"] = MonitorPane(fm, ranger_pane)
65 |
66 | def disable():
67 | if non_local["pane_monitor_thread"]:
68 | non_local["pane_monitor_thread"].stopped = True
69 |
70 | def setting_signal_handler(signal):
71 | if signal.value:
72 | enable()
73 | else:
74 | disable()
75 |
76 | fm.settings.signal_bind("setopt.{}".format(setting), setting_signal_handler)
77 |
78 | if fm.settings.__getitem__(setting):
79 | enable()
80 |
--------------------------------------------------------------------------------
/ranger_tmux/drop.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """Performs the drop-down action in tmux.
3 |
4 | Intended to be triggered by a keyboard-shortcut in tmux.
5 | """
6 | import signal
7 | import sys
8 | import time
9 |
10 | import psutil
11 | import ranger
12 | from ranger.container.settings import Settings
13 | from ranger.core.fm import FM
14 | from ranger.core.main import parse_arguments
15 | from ranger.core.shared import FileManagerAware, SettingsAware
16 |
17 | from ranger_tmux import util
18 |
19 |
20 | def animated_resize(pane_id, target_perc, duration=200):
21 | """Animates the resizing a tmux pane."""
22 | pane_height = int(util.tmux("display", "-t", "{top}", "-p", "#{pane_height}"))
23 | window_height = int(util.tmux("display", "-p", "#{window_height}"))
24 | target_height = int(target_perc / 100 * window_height)
25 | direction = pane_height < target_height
26 | lines = int(duration < 500) + 1
27 | frames = max(1, abs(pane_height - target_height) // lines - 1)
28 | timeout = duration / 1000 / frames
29 | for _ in range(frames):
30 | util.tmux("resize-pane", "-D" if direction else "-U", "-t", pane_id, lines)
31 | time.sleep(timeout)
32 | util.tmux("resize-pane", "-t", pane_id, "-y", f"{target_perc}%")
33 |
34 |
35 | def main():
36 | """Launches ranger in a new pane, optionally driving pane animation."""
37 | ranger_script_path = util.get_ranger_script()
38 |
39 | # Initiate ranger just enough to allow us to access the settings
40 | ranger.args = parse_arguments()
41 | fm = FM()
42 | SettingsAware.settings_set(Settings())
43 | FileManagerAware.fm_set(fm)
44 | ranger.core.main.load_settings(fm, clean=False)
45 |
46 | # Check we're actually in tmux
47 | if not util.check_tmux(fm):
48 | sys.exit()
49 |
50 | # Check if we need to animate the drop
51 | animate = fm.settings.get("tmux_dropdown_animate")
52 | duration = fm.settings.get("tmux_dropdown_duration")
53 |
54 | pane_id, command, pid = util.tmux(
55 | "display", "-t", "{top}", "-p", "#{pane_id}|#{pane_start_command}|#{pane_pid}"
56 | ).split("|")
57 |
58 | # Ranger is open - we will close it
59 | if command == f"{sys.executable} {ranger_script_path} -- .":
60 | # Animate close if wanted
61 | if animate:
62 | animated_resize(pane_id, 0, duration)
63 | # Get a handel on ranger
64 | process = psutil.Process(int(pid))
65 | # Send interupt to ranger to cancel any unfinished command entry
66 | process.send_signal(signal.SIGINT)
67 | # Ask ranger to quit nicely
68 | util.tmux("send-keys", "-t", pane_id, "Q")
69 | # Give range half a second to quit before vicously killing it
70 | dead, alive = psutil.wait_procs([process], timeout=0.5)
71 | for p in alive:
72 | p.kill()
73 |
74 | # Ranger is not open - we will open it
75 | else:
76 | # Load ranger pane height from ranger settings
77 | percent = fm.settings.get("tmux_dropdown_percent")
78 | # Make initial size smaller if we're going to animate
79 | initial_size = "1" if animate else f"{percent}%"
80 | # Get other pane folder
81 | pane_dir = util.tmux(
82 | "display-message", "-p", "-t", pane_id, "#{pane_current_path}"
83 | )
84 | # Create a new ranger pane
85 | pane_id = util.tmux(
86 | "split-window",
87 | "-bfv",
88 | "-F",
89 | "#{pane_id}",
90 | "-c",
91 | pane_dir,
92 | "-t",
93 | "{top}",
94 | "-l",
95 | initial_size,
96 | sys.executable,
97 | ranger_script_path,
98 | "--",
99 | ".",
100 | )
101 | # Animate open if wanted
102 | if animate:
103 | animated_resize(pane_id, percent, duration)
104 |
105 |
106 | if __name__ == "__main__":
107 | main()
108 |
--------------------------------------------------------------------------------
/ranger_tmux/dropdown.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from ranger.api.commands import Command
3 |
4 | from ranger_tmux.__main__ import tmux_keybindings
5 |
6 | from . import util
7 |
8 | SETTINGS = {
9 | "tmux_dropdown_percent": {"type": int, "default": 60},
10 | "tmux_dropdown_animate": {"type": bool, "default": True},
11 | "tmux_dropdown_duration": {"type": int, "default": 100},
12 | }
13 |
14 |
15 | class install_tmux_dropdown_shortcut(Command):
16 | def execute(self):
17 | def callback(answer):
18 | if answer == "y":
19 | tmux_cmds = tmux_keybindings(install=True)
20 | # Add shortcut to current session
21 | for cmd in tmux_cmds:
22 | util.tmux(*cmd)
23 | util.tmux("display", "Tmux shortcut for drop-down ranger installed")
24 |
25 | self.fm.ui.console.ask(
26 | "Are you sure you want to install the drop-down ranger key-binding in"
27 | " ~/.tmux.conf? (y/n)",
28 | callback,
29 | "yn",
30 | )
31 |
32 |
33 | def init(fm, *args):
34 | fm.execute_console(
35 | 'map xh eval fm.execute_console("install_tmux_dropdown_shortcut")'
36 | )
37 |
--------------------------------------------------------------------------------
/ranger_tmux/open_in_window.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import ranger.api
3 |
4 | HOOK_INIT_OLD = ranger.api.hook_init
5 |
6 | SETTINGS = {"tmux_open_in_window": {"key": "w", "type": bool, "default": True}}
7 |
8 |
9 | def tmux_open_in_window_init(fm, setting, *args):
10 | """Monkey-patch rifle's preprocessing function.
11 |
12 | This re-writes rifle commands, causing them to run in a new tmux window.
13 |
14 | """
15 |
16 | # Add shortcuts to open selected file in new window / pane
17 | fm.execute_console('map xo shell tmux new-window -a "rifle %f"')
18 | fm.execute_console('map xl shell tmux split-pane -h "rifle %f"')
19 | fm.execute_console('map xp shell tmux split-pane -v "rifle %f"')
20 |
21 | # Hook rifle's post-processing command
22 | old_postprocessing_command = fm.rifle.hook_command_postprocessing
23 |
24 | def new_postprocessing_command(command):
25 | if fm.settings.__getitem__(setting):
26 | command = command.replace('"', r"\"").replace("$", r"\$")
27 | command = 'tmux new-window -a "{}"'.format(command)
28 | return old_postprocessing_command(command)
29 |
30 | fm.rifle.hook_command_postprocessing = new_postprocessing_command
31 |
--------------------------------------------------------------------------------
/ranger_tmux/plugin.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import ranger.api
3 | from ranger.container.settings import (
4 | ALLOWED_SETTINGS,
5 | SIGNAL_PRIORITY_SANITIZE,
6 | SIGNAL_PRIORITY_SYNC,
7 | )
8 |
9 | from ranger_tmux import (
10 | cwd_sync,
11 | cwd_track,
12 | dropdown,
13 | open_in_window,
14 | set_window_name,
15 | splits,
16 | util,
17 | )
18 | from ranger_tmux.cwd_sync import tmux_cwd_sync_now # noqa F401
19 | from ranger_tmux.cwd_track import tmux_cwd_track_now # noqa F401
20 | from ranger_tmux.dropdown import install_tmux_dropdown_shortcut # noqa F401
21 |
22 | MODULES = [open_in_window, set_window_name, cwd_sync, cwd_track, dropdown, splits]
23 |
24 | HOOK_INIT_OLD = ranger.api.hook_init
25 |
26 |
27 | # Add settings to ranger when plugin is loaded
28 | # Adding these at import means the plugin's settings are available to ranger
29 | for mod in MODULES:
30 | if hasattr(mod, "SETTINGS"):
31 | for setting, info in mod.SETTINGS.items():
32 | ALLOWED_SETTINGS[setting] = info.get("type", bool)
33 | value = info.get("default")
34 | if value:
35 | ranger.fm.settings._raw_set(setting, value)
36 | ranger.fm.settings.signal_bind(
37 | "setopt.{}".format(setting),
38 | ranger.fm.settings._sanitize,
39 | priority=SIGNAL_PRIORITY_SANITIZE,
40 | )
41 | ranger.fm.settings.signal_bind(
42 | "setopt.{}".format(setting),
43 | ranger.fm.settings._raw_set_with_signal,
44 | priority=SIGNAL_PRIORITY_SYNC,
45 | )
46 |
47 |
48 | def hook_init(fm):
49 |
50 | # Add ranger_tmux hooks if we are in a tmux session
51 | if util.check_tmux(fm):
52 |
53 | # Load all modules
54 | for mod in MODULES:
55 | # Add key-bindings for module
56 | if hasattr(mod, "SETTINGS"):
57 | for setting, info in mod.SETTINGS.items():
58 | if hasattr(mod, "{}_init".format(setting)):
59 | getattr(mod, "{}_init".format(setting))(fm, setting, MODULES)
60 | key = info.get("key")
61 | if key:
62 | fm.execute_console("map x{} set {}!".format(key, setting))
63 | if hasattr(mod, "init"):
64 | mod.init(fm, MODULES)
65 |
66 | return HOOK_INIT_OLD(fm)
67 |
68 |
69 | ranger.api.hook_init = hook_init
70 |
--------------------------------------------------------------------------------
/ranger_tmux/set_window_name.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import atexit
3 |
4 | from . import util
5 |
6 | SETTINGS = {"tmux_set_title": {"key": "i", "type": bool, "default": True}}
7 |
8 |
9 | def set_tmux_window_title(msg):
10 | """Set tmux's window format"""
11 | util.tmux("set-option", "-p", "automatic-rename-format", msg)
12 |
13 |
14 | def tmux_set_title_init(fm, setting, *args):
15 |
16 | # Save tmux's original title format
17 | original_format = util.tmux("show-options", "-gv", "automatic-rename-format")
18 |
19 | def enable():
20 | # Set window name to "ranger" on this panel
21 | set_tmux_window_title("ranger")
22 | # Reset title at exit
23 | atexit.register(disable)
24 |
25 | def disable():
26 | set_tmux_window_title(original_format)
27 | if hasattr(atexit, "unregister"):
28 | atexit.unregister(disable)
29 | else:
30 | # Python 2 version of above
31 | for i, handler in enumerate(atexit._exithandlers):
32 | if handler == (disable, (), {}):
33 | del atexit._exithandlers[i]
34 |
35 | def setting_signal_handler(signal):
36 | if signal.value:
37 | enable()
38 | else:
39 | disable()
40 |
41 | setting = list(SETTINGS.keys())[0]
42 | fm.settings.signal_bind("setopt.{}".format(setting), setting_signal_handler)
43 |
44 | if fm.settings.__getitem__(setting):
45 | enable()
46 |
--------------------------------------------------------------------------------
/ranger_tmux/splits.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | def init(fm, *args):
5 | """Extra tmux key-bindings to splt tmux windows."""
6 | fm.execute_console("map x- shell tmux split-window -v -c %d")
7 | fm.execute_console("map x| shell tmux split-window -h -c %d")
8 |
--------------------------------------------------------------------------------
/ranger_tmux/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import os
3 | import shutil
4 | import signal
5 | from subprocess import CalledProcessError, check_output
6 |
7 | try:
8 | import importlib_metadata
9 | except ImportError:
10 | import importlib.metadata as importlib_metadata
11 |
12 |
13 | def get_ranger_script():
14 | scripts = importlib_metadata.files("ranger-fm")
15 | if scripts is not None:
16 | ranger_script_paths = [path for path in scripts if path.name == "ranger"]
17 | if ranger_script_paths:
18 | return ranger_script_paths[0].locate().resolve()
19 | return shutil.which("ranger")
20 |
21 |
22 | def check_tmux(fm):
23 | # TODO chcek tmux is in path too
24 | tmuxed = os.environ.get("TMUX")
25 | if not tmuxed:
26 | fm.notify("Not running in tmux session, ranger_tmux is disabled")
27 | return tmuxed
28 |
29 |
30 | def tmux(*args):
31 | try:
32 | return check_output(["tmux"] + list(map(str, args))).decode("utf8").strip()
33 | except CalledProcessError:
34 | return
35 |
36 |
37 | def get_ranger_pane():
38 | import psutil
39 |
40 | # Find pane with current instance of ranger in
41 | ranger_pid = os.getpid()
42 | panes = tmux("list-panes", "-aF", "#{pane_pid},#{pane_id}")
43 | if panes:
44 | panes = {
45 | int(pid): pane_id.strip()
46 | for pid, pane_id in [info.split(",") for info in panes.split("\n")]
47 | }
48 | for pid, pane_id in panes.items():
49 | if ranger_pid == pid or ranger_pid in [
50 | x.pid for x in psutil.Process(pid).children(recursive=True)
51 | ]:
52 | return pane_id
53 |
54 |
55 | def select_shell_pane(ranger_pane):
56 |
57 | # Panes can move windows, so check this every time
58 | ranger_window = tmux("display", "-t", ranger_pane, "-p", "#{window_id}")
59 |
60 | # Get all panes in this window
61 | window_panes = tmux("list-panes", "-F", "#{pane_id}", "-t", ranger_window).split(
62 | "\n"
63 | )
64 | other_panes = set(window_panes) - set(ranger_pane)
65 |
66 | if not other_panes:
67 | return
68 |
69 | # Check for a marked pane in this window
70 | marks = tmux("display", "-p", "-F", "#{window_flags}", "-t", ranger_pane)
71 | has_marked_pane = "M" in marks # marks' values can be `#!~*-MZ`
72 | if has_marked_pane:
73 | pane = tmux("display", "-p", "-t", "{marked}", "#{pane_id}")
74 | if pane in other_panes and pane != ranger_pane:
75 | return pane
76 |
77 | pane = tmux("display", "-p", "#{pane_id}")
78 | if pane in other_panes and pane != ranger_pane:
79 | return pane
80 |
81 | pane = tmux("display", "-p", "-t", "{last}", "#{pane_id}")
82 | if pane in other_panes and pane != ranger_pane:
83 | return pane
84 |
85 | pane = tmux("display", "-p", "-t", "{next}", "#{pane_id}")
86 | if pane in other_panes and pane != ranger_pane:
87 | return pane
88 |
89 | if other_panes:
90 | return list(sorted(other_panes))[0]
91 |
92 |
93 | def cd_pane(path, pane_id):
94 | import psutil
95 |
96 | pane_process = psutil.Process(
97 | int(tmux("display", "-p", "-t", pane_id, "-F", "#{pane_pid}"))
98 | )
99 | with pane_process.oneshot():
100 | if not pane_process.children():
101 | if pane_process.cwd() != str(path):
102 | pane_process.send_signal(signal.SIGINT)
103 | tmux("send-keys", "-t", pane_id, ' cd "{}"'.format(path), "Enter")
104 |
--------------------------------------------------------------------------------
/scripts/publish.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """Publishes a new releases of ranger-tmux."""
3 | from pathlib import Path
4 |
5 | from poetry_publish.publish import poetry_publish # type: ignore
6 |
7 | import ranger_tmux
8 |
9 |
10 | def publish() -> "None":
11 | """Publishes a new releasse of euporie to pypi.org."""
12 | poetry_publish(
13 | package_root=Path(ranger_tmux.__file__).parent.parent,
14 | version=ranger_tmux.__version__,
15 | )
16 |
17 |
18 | if __name__ == "__main__":
19 | publish()
20 |
--------------------------------------------------------------------------------