Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
5.2 KiB

4 years ago
  1. from ranger.api.commands import Command
  2. class mkcd(Command):
  3. """
  4. :mkcd <dirname>
  5. Creates a directory with the name <dirname> and enters it.
  6. """
  7. def execute(self):
  8. from os.path import join, expanduser, lexists
  9. from os import makedirs
  10. import re
  11. dirname = join(self.fm.thisdir.path, expanduser(self.rest(1)))
  12. if not lexists(dirname):
  13. makedirs(dirname)
  14. match = re.search('^/|^~[^/]*/', dirname)
  15. if match:
  16. self.fm.cd(match.group(0))
  17. dirname = dirname[match.end(0):]
  18. for m in re.finditer('[^/]+', dirname):
  19. s = m.group(0)
  20. if s == '..' or (s.startswith('.') and not self.fm.settings['show_hidden']):
  21. self.fm.cd(s)
  22. else:
  23. ## We force ranger to load content before calling `scout`.
  24. self.fm.thisdir.load_content(schedule=False)
  25. self.fm.execute_console('scout -ae ^{}$'.format(s))
  26. else:
  27. self.fm.notify("file/directory exists!", bad=True)
  28. class toggle_flat(Command):
  29. """
  30. :toggle_flat
  31. Flattens or unflattens the directory view.
  32. """
  33. def execute(self):
  34. if self.fm.thisdir.flat == 0:
  35. self.fm.thisdir.unload()
  36. self.fm.thisdir.flat = -1
  37. self.fm.thisdir.load_content()
  38. else:
  39. self.fm.thisdir.unload()
  40. self.fm.thisdir.flat = 0
  41. self.fm.thisdir.load_content()
  42. class fzf_select(Command):
  43. """
  44. :fzf_select
  45. Find a file using fzf.
  46. With a prefix argument to select only directories.
  47. See: https://github.com/junegunn/fzf
  48. """
  49. def execute(self):
  50. import subprocess
  51. import os
  52. from ranger.ext.get_executables import get_executables
  53. if 'fzf' not in get_executables():
  54. self.fm.notify('Could not find fzf in the PATH.', bad=True)
  55. return
  56. fd = None
  57. if 'fdfind' in get_executables():
  58. fd = 'fdfind'
  59. elif 'fd' in get_executables():
  60. fd = 'fd'
  61. if fd is not None:
  62. hidden = ('--hidden' if self.fm.settings.show_hidden else '')
  63. exclude = "--no-ignore-vcs --exclude '.git' --exclude '*.py[co]' --exclude '__pycache__'"
  64. only_directories = ('--type directory' if self.quantifier else '')
  65. fzf_default_command = '{} --follow {} {} {} --color=always'.format(
  66. fd, hidden, exclude, only_directories
  67. )
  68. else:
  69. hidden = ('-false' if self.fm.settings.show_hidden else r"-path '*/\.*' -prune")
  70. exclude = r"\( -name '\.git' -o -iname '\.*py[co]' -o -fstype 'dev' -o -fstype 'proc' \) -prune"
  71. only_directories = ('-type d' if self.quantifier else '')
  72. fzf_default_command = 'find -L . -mindepth 1 {} -o {} -o {} -print | cut -b3-'.format(
  73. hidden, exclude, only_directories
  74. )
  75. env = os.environ.copy()
  76. env['FZF_DEFAULT_COMMAND'] = fzf_default_command
  77. env['FZF_DEFAULT_OPTS'] = '--height=40% --layout=reverse --ansi --preview="{}"'.format('''
  78. (
  79. batcat --color=always {} ||
  80. bat --color=always {} ||
  81. cat {} ||
  82. tree -ahpCL 3 -I '.git' -I '*.py[co]' -I '__pycache__' {}
  83. ) 2>/dev/null | head -n 100
  84. ''')
  85. fzf = self.fm.execute_command('fzf --no-multi', env=env,
  86. universal_newlines=True, stdout=subprocess.PIPE)
  87. stdout, _ = fzf.communicate()
  88. if fzf.returncode == 0:
  89. selected = os.path.abspath(stdout.strip())
  90. if os.path.isdir(selected):
  91. self.fm.cd(selected)
  92. else:
  93. self.fm.select_file(selected)
  94. class YankContent(Command):
  95. """
  96. Copy the content of image file and text file with xclip
  97. """
  98. def execute(self):
  99. import os
  100. import subprocess
  101. from ranger.container.file import File
  102. from ranger.ext.get_executables import get_executables
  103. if 'xclip' not in get_executables():
  104. self.fm.notify('xclip is not found.', bad=True)
  105. return
  106. arg = self.rest(1)
  107. if arg:
  108. if not os.path.isfile(arg):
  109. self.fm.notify('{} is not a file.'.format(arg))
  110. return
  111. file = File(arg)
  112. else:
  113. file = self.fm.thisfile
  114. if not file.is_file:
  115. self.fm.notify('{} is not a file.'.format(file.relative_path))
  116. return
  117. relative_path = file.relative_path
  118. cmd = ['xclip', '-selection', 'clipboard']
  119. if not file.is_binary():
  120. with open(file.path, 'rb') as fd:
  121. subprocess.check_call(cmd, stdin=fd)
  122. elif file.image:
  123. cmd += ['-t', file.mimetype, file.path]
  124. subprocess.check_call(cmd)
  125. self.fm.notify('Content of {} is copied to x clipboard'.format(relative_path))
  126. else:
  127. self.fm.notify('{} is not an image file or a text file.'.format(relative_path))
  128. def tab(self, tabnum):
  129. return self._tab_directory_content()