44import logging
55import os
66
7- from yapf .yapflib import file_resources
7+ from yapf .yapflib import file_resources , style
88from yapf .yapflib .yapf_api import FormatCode
99
1010from pylsp import hookimpl
1414
1515
1616@hookimpl
17- def pylsp_format_document (document ):
18- return _format (document )
17+ def pylsp_format_document (document , options = None ):
18+ return _format (document , options = options )
1919
2020
2121@hookimpl
22- def pylsp_format_range (document , range ): # pylint: disable=redefined-builtin
22+ def pylsp_format_range (document , range , options = None ): # pylint: disable=redefined-builtin
2323 # First we 'round' the range up/down to full lines only
2424 range ['start' ]['character' ] = 0
2525 range ['end' ]['line' ] += 1
@@ -33,10 +33,10 @@ def pylsp_format_range(document, range): # pylint: disable=redefined-builtin
3333
3434 # Add 1 for 1-indexing vs LSP's 0-indexing
3535 lines = [(range ['start' ]['line' ] + 1 , range ['end' ]['line' ] + 1 )]
36- return _format (document , lines = lines )
36+ return _format (document , lines = lines , options = options )
3737
3838
39- def _format (document , lines = None ):
39+ def _format (document , lines = None , options = None ):
4040 # Yapf doesn't work with CRLF/CR line endings, so we replace them by '\n'
4141 # and restore them below.
4242 replace_eols = False
@@ -46,13 +46,50 @@ def _format(document, lines=None):
4646 replace_eols = True
4747 source = source .replace (eol_chars , '\n ' )
4848
49+ # Get the default styles as a string
50+ # for a preset configuration, i.e. "pep8"
51+ style_config = file_resources .GetDefaultStyleForDir (
52+ os .path .dirname (document .path )
53+ )
54+ if options is not None :
55+ # We have options passed from LSP format request
56+ # let's pass them to the formatter.
57+ # First we want to get a dictionary of the preset style
58+ # to pass instead of a string so that we can modify it
59+ style_config = style .CreateStyleFromConfig (style_config )
60+
61+ use_tabs = style_config ['USE_TABS' ]
62+ indent_width = style_config ['INDENT_WIDTH' ]
63+
64+ if options .get ('tabSize' ) is not None :
65+ indent_width = max (int (options .get ('tabSize' )), 1 )
66+
67+ if options .get ('insertSpaces' ) is not None :
68+ # TODO is it guaranteed to be a boolean, or can it be a string?
69+ use_tabs = not options .get ('insertSpaces' )
70+
71+ if use_tabs :
72+ # Indent width doesn't make sense when using tabs
73+ # the specifications state: "Size of a tab in spaces"
74+ indent_width = 1
75+
76+ style_config ['USE_TABS' ] = use_tabs
77+ style_config ['INDENT_WIDTH' ] = indent_width
78+ style_config ['CONTINUATION_INDENT_WIDTH' ] = indent_width
79+
80+ for style_option , value in options .items ():
81+ # Apply arbitrary options passed as formatter options
82+ if style_option not in style_config :
83+ # ignore if it's not a known yapf config
84+ continue
85+
86+ style_config [style_option ] = value
87+
4988 new_source , changed = FormatCode (
5089 source ,
5190 lines = lines ,
5291 filename = document .filename ,
53- style_config = file_resources .GetDefaultStyleForDir (
54- os .path .dirname (document .path )
55- )
92+ style_config = style_config
5693 )
5794
5895 if not changed :
0 commit comments