]> git.madduck.net Git - etc/vim.git/blob - autoload/black.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Add LocalStack and Twisted to projects using Black
[etc/vim.git] / autoload / black.vim
1 python3 << EndPython3
2 import collections
3 import os
4 import sys
5 import vim
6 from distutils.util import strtobool
7
8
9 class Flag(collections.namedtuple("FlagBase", "name, cast")):
10   @property
11   def var_name(self):
12     return self.name.replace("-", "_")
13
14   @property
15   def vim_rc_name(self):
16     name = self.var_name
17     if name == "line_length":
18       name = name.replace("_", "")
19     return "g:black_" + name
20
21
22 FLAGS = [
23   Flag(name="line_length", cast=int),
24   Flag(name="fast", cast=strtobool),
25   Flag(name="skip_string_normalization", cast=strtobool),
26   Flag(name="quiet", cast=strtobool),
27 ]
28
29
30 def _get_python_binary(exec_prefix):
31   try:
32     default = vim.eval("g:pymode_python").strip()
33   except vim.error:
34     default = ""
35   if default and os.path.exists(default):
36     return default
37   if sys.platform[:3] == "win":
38     return exec_prefix / 'python.exe'
39   return exec_prefix / 'bin' / 'python3'
40
41 def _get_pip(venv_path):
42   if sys.platform[:3] == "win":
43     return venv_path / 'Scripts' / 'pip.exe'
44   return venv_path / 'bin' / 'pip'
45
46 def _get_virtualenv_site_packages(venv_path, pyver):
47   if sys.platform[:3] == "win":
48     return venv_path / 'Lib' / 'site-packages'
49   return venv_path / 'lib' / f'python{pyver[0]}.{pyver[1]}' / 'site-packages'
50
51 def _initialize_black_env(upgrade=False):
52   pyver = sys.version_info[:3]
53   if pyver < (3, 6, 2):
54     print("Sorry, Black requires Python 3.6.2+ to run.")
55     return False
56
57   from pathlib import Path
58   import subprocess
59   import venv
60   virtualenv_path = Path(vim.eval("g:black_virtualenv")).expanduser()
61   virtualenv_site_packages = str(_get_virtualenv_site_packages(virtualenv_path, pyver))
62   first_install = False
63   if not virtualenv_path.is_dir():
64     print('Please wait, one time setup for Black.')
65     _executable = sys.executable
66     _base_executable = getattr(sys, "_base_executable", _executable)
67     try:
68       executable = str(_get_python_binary(Path(sys.exec_prefix)))
69       sys.executable = executable
70       sys._base_executable = executable
71       print(f'Creating a virtualenv in {virtualenv_path}...')
72       print('(this path can be customized in .vimrc by setting g:black_virtualenv)')
73       venv.create(virtualenv_path, with_pip=True)
74     except Exception:
75       print('Encountered exception while creating virtualenv (see traceback below).')
76       print(f'Removing {virtualenv_path}...')
77       import shutil
78       shutil.rmtree(virtualenv_path)
79       raise
80     finally:
81       sys.executable = _executable
82       sys._base_executable = _base_executable
83     first_install = True
84   if first_install:
85     print('Installing Black with pip...')
86   if upgrade:
87     print('Upgrading Black with pip...')
88   if first_install or upgrade:
89     subprocess.run([str(_get_pip(virtualenv_path)), 'install', '-U', 'black'], stdout=subprocess.PIPE)
90     print('DONE! You are all set, thanks for waiting ✨ 🍰 ✨')
91   if first_install:
92     print('Pro-tip: to upgrade Black in the future, use the :BlackUpgrade command and restart Vim.\n')
93   if virtualenv_site_packages not in sys.path:
94     sys.path.insert(0, virtualenv_site_packages)
95   return True
96
97 if _initialize_black_env():
98   import black
99   import time
100
101 def Black():
102   start = time.time()
103   configs = get_configs()
104   mode = black.FileMode(
105     line_length=configs["line_length"],
106     string_normalization=not configs["skip_string_normalization"],
107     is_pyi=vim.current.buffer.name.endswith('.pyi'),
108   )
109   quiet = configs["quiet"]
110
111   buffer_str = '\n'.join(vim.current.buffer) + '\n'
112   try:
113     new_buffer_str = black.format_file_contents(
114       buffer_str,
115       fast=configs["fast"],
116       mode=mode,
117     )
118   except black.NothingChanged:
119     if not quiet:
120       print(f'Already well formatted, good job. (took {time.time() - start:.4f}s)')
121   except Exception as exc:
122     print(exc)
123   else:
124     current_buffer = vim.current.window.buffer
125     cursors = []
126     for i, tabpage in enumerate(vim.tabpages):
127       if tabpage.valid:
128         for j, window in enumerate(tabpage.windows):
129           if window.valid and window.buffer == current_buffer:
130             cursors.append((i, j, window.cursor))
131     vim.current.buffer[:] = new_buffer_str.split('\n')[:-1]
132     for i, j, cursor in cursors:
133       window = vim.tabpages[i].windows[j]
134       try:
135         window.cursor = cursor
136       except vim.error:
137         window.cursor = (len(window.buffer), 0)
138     if not quiet:
139       print(f'Reformatted in {time.time() - start:.4f}s.')
140
141 def get_configs():
142   filename = vim.eval("@%")
143   path_pyproject_toml = black.find_pyproject_toml((filename,))
144   if path_pyproject_toml:
145     toml_config = black.parse_pyproject_toml(path_pyproject_toml)
146   else:
147     toml_config = {}
148
149   return {
150     flag.var_name: toml_config.get(flag.name, flag.cast(vim.eval(flag.vim_rc_name)))
151     for flag in FLAGS
152   }
153
154
155 def BlackUpgrade():
156   _initialize_black_env(upgrade=True)
157
158 def BlackVersion():
159   print(f'Black, version {black.__version__} on Python {sys.version}.')
160
161 EndPython3
162
163 function black#Black()
164   :py3 Black()
165 endfunction
166
167 function black#BlackUpgrade()
168   :py3 BlackUpgrade()
169 endfunction
170
171 function black#BlackVersion()
172   :py3 BlackVersion()
173 endfunction