main.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #!/usr/bin/env python
  2. # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
  3. import sys
  4. from functools import partial
  5. from typing import List
  6. from kitty.cli import CONFIG_HELP, CompletionSpec
  7. from kitty.conf.types import Definition
  8. from kitty.constants import appname
  9. def main(args: List[str]) -> None:
  10. raise SystemExit('Must be run as kitten diff')
  11. definition = Definition(
  12. '!kittens.diff',
  13. )
  14. agr = definition.add_group
  15. egr = definition.end_group
  16. opt = definition.add_option
  17. map = definition.add_map
  18. mma = definition.add_mouse_map
  19. # diff {{{
  20. agr('diff', 'Diffing')
  21. opt('syntax_aliases', 'pyj:py pyi:py recipe:py', ctype='strdict_ _:', option_type='syntax_aliases',
  22. long_text='''
  23. File extension aliases for syntax highlight. For example, to syntax highlight
  24. :file:`file.xyz` as :file:`file.abc` use a setting of :code:`xyz:abc`.
  25. Multiple aliases must be separated by spaces.
  26. '''
  27. )
  28. opt('num_context_lines', '3', option_type='positive_int',
  29. long_text='The number of lines of context to show around each change.'
  30. )
  31. opt('diff_cmd', 'auto',
  32. long_text='''
  33. The diff command to use. Must contain the placeholder :code:`_CONTEXT_` which
  34. will be replaced by the number of lines of context. A few special values are allowed:
  35. :code:`auto` will automatically pick an available diff implementation. :code:`builtin`
  36. will use the anchored diff algorithm from the Go standard library. :code:`git` will
  37. use the git command to do the diffing. :code:`diff` will use the diff command to
  38. do the diffing.
  39. '''
  40. )
  41. opt('replace_tab_by', '\\x20\\x20\\x20\\x20', option_type='python_string',
  42. long_text='The string to replace tabs with. Default is to use four spaces.'
  43. )
  44. opt('+ignore_name', '', ctype='string',
  45. add_to_default=False,
  46. long_text='''
  47. A glob pattern that is matched against only the filename of files and directories. Matching
  48. files and directories are ignored when scanning the filesystem to look for files to diff.
  49. Can be specified multiple times to use multiple patterns. For example::
  50. ignore_name .git
  51. ignore_name *~
  52. ignore_name *.pyc
  53. ''',
  54. )
  55. egr() # }}}
  56. # colors {{{
  57. agr('colors', 'Colors')
  58. opt('pygments_style', 'default',
  59. long_text='''
  60. The pygments color scheme to use for syntax highlighting. See :link:`pygments
  61. builtin styles <https://pygments.org/styles/>` for a list of schemes. Note that
  62. this **does not** change the colors used for diffing,
  63. only the colors used for syntax highlighting. To change the general colors use the settings below.
  64. '''
  65. )
  66. opt('foreground', 'black',
  67. option_type='to_color',
  68. long_text='Basic colors'
  69. )
  70. opt('background', 'white',
  71. option_type='to_color',
  72. )
  73. opt('title_fg', 'black',
  74. option_type='to_color',
  75. long_text='Title colors'
  76. )
  77. opt('title_bg', 'white',
  78. option_type='to_color',
  79. )
  80. opt('margin_bg', '#fafbfc',
  81. option_type='to_color',
  82. long_text='Margin colors'
  83. )
  84. opt('margin_fg', '#aaaaaa',
  85. option_type='to_color',
  86. )
  87. opt('removed_bg', '#ffeef0',
  88. option_type='to_color',
  89. long_text='Removed text backgrounds'
  90. )
  91. opt('highlight_removed_bg', '#fdb8c0',
  92. option_type='to_color',
  93. )
  94. opt('removed_margin_bg', '#ffdce0',
  95. option_type='to_color',
  96. )
  97. opt('added_bg', '#e6ffed',
  98. option_type='to_color',
  99. long_text='Added text backgrounds'
  100. )
  101. opt('highlight_added_bg', '#acf2bd',
  102. option_type='to_color',
  103. )
  104. opt('added_margin_bg', '#cdffd8',
  105. option_type='to_color',
  106. )
  107. opt('filler_bg', '#fafbfc',
  108. option_type='to_color',
  109. long_text='Filler (empty) line background'
  110. )
  111. opt('margin_filler_bg', 'none',
  112. option_type='to_color_or_none',
  113. long_text='Filler (empty) line background in margins, defaults to the filler background'
  114. )
  115. opt('hunk_margin_bg', '#dbedff',
  116. option_type='to_color',
  117. long_text='Hunk header colors'
  118. )
  119. opt('hunk_bg', '#f1f8ff',
  120. option_type='to_color',
  121. )
  122. opt('search_bg', '#444',
  123. option_type='to_color',
  124. long_text='Highlighting'
  125. )
  126. opt('search_fg', 'white',
  127. option_type='to_color',
  128. )
  129. opt('select_bg', '#b4d5fe',
  130. option_type='to_color',
  131. )
  132. opt('select_fg', 'black',
  133. option_type='to_color_or_none',
  134. )
  135. egr() # }}}
  136. # shortcuts {{{
  137. agr('shortcuts', 'Keyboard shortcuts')
  138. map('Quit',
  139. 'quit q quit',
  140. )
  141. map('Quit',
  142. 'quit esc quit',
  143. )
  144. map('Scroll down',
  145. 'scroll_down j scroll_by 1',
  146. )
  147. map('Scroll down',
  148. 'scroll_down down scroll_by 1',
  149. )
  150. map('Scroll up',
  151. 'scroll_up k scroll_by -1',
  152. )
  153. map('Scroll up',
  154. 'scroll_up up scroll_by -1',
  155. )
  156. map('Scroll to top',
  157. 'scroll_top home scroll_to start',
  158. )
  159. map('Scroll to bottom',
  160. 'scroll_bottom end scroll_to end',
  161. )
  162. map('Scroll to next page',
  163. 'scroll_page_down page_down scroll_to next-page',
  164. )
  165. map('Scroll to next page',
  166. 'scroll_page_down space scroll_to next-page',
  167. )
  168. map('Scroll to previous page',
  169. 'scroll_page_up page_up scroll_to prev-page',
  170. )
  171. map('Scroll to next change',
  172. 'next_change n scroll_to next-change',
  173. )
  174. map('Scroll to previous change',
  175. 'prev_change p scroll_to prev-change',
  176. )
  177. map('Show all context',
  178. 'all_context a change_context all',
  179. )
  180. map('Show default context',
  181. 'default_context = change_context default',
  182. )
  183. map('Increase context',
  184. 'increase_context + change_context 5',
  185. )
  186. map('Decrease context',
  187. 'decrease_context - change_context -5',
  188. )
  189. map('Search forward',
  190. 'search_forward / start_search regex forward',
  191. )
  192. map('Search backward',
  193. 'search_backward ? start_search regex backward',
  194. )
  195. map('Scroll to next search match',
  196. 'next_match . scroll_to next-match',
  197. )
  198. map('Scroll to next search match',
  199. 'next_match > scroll_to next-match',
  200. )
  201. map('Scroll to previous search match',
  202. 'prev_match , scroll_to prev-match',
  203. )
  204. map('Scroll to previous search match',
  205. 'prev_match < scroll_to prev-match',
  206. )
  207. map('Search forward (no regex)',
  208. 'search_forward_simple f start_search substring forward',
  209. )
  210. map('Search backward (no regex)',
  211. 'search_backward_simple b start_search substring backward',
  212. )
  213. map('Copy selection to clipboard', 'copy_to_clipboard y copy_to_clipboard')
  214. map('Copy selection to clipboard or exit if no selection is present', 'copy_to_clipboard_or_exit ctrl+c copy_to_clipboard_or_exit')
  215. egr() # }}}
  216. OPTIONS = partial('''\
  217. --context
  218. type=int
  219. default=-1
  220. Number of lines of context to show between changes. Negative values use the
  221. number set in :file:`diff.conf`.
  222. --config
  223. type=list
  224. completion=type:file ext:conf group:"Config files" kwds:none,NONE
  225. {config_help}
  226. --override -o
  227. type=list
  228. Override individual configuration options, can be specified multiple times.
  229. Syntax: :italic:`name=value`. For example: :italic:`-o background=gray`
  230. '''.format, config_help=CONFIG_HELP.format(conf_name='diff', appname=appname))
  231. help_text = 'Show a side-by-side diff of the specified files/directories. You can also use :italic:`ssh:hostname:remote-file-path` to diff remote files.'
  232. usage = 'file_or_directory_left file_or_directory_right'
  233. if __name__ == '__main__':
  234. main(sys.argv)
  235. elif __name__ == '__doc__':
  236. cd = sys.cli_docs # type: ignore
  237. cd['usage'] = usage
  238. cd['options'] = OPTIONS
  239. cd['help_text'] = help_text
  240. cd['short_desc'] = 'Pretty, side-by-side diffing of files and images'
  241. cd['args_completion'] = CompletionSpec.from_string('type:file mime:text/* mime:image/* group:"Text and image files"')
  242. elif __name__ == '__conf__':
  243. sys.options_definition = definition # type: ignore