Skip to content

Commit d92537c

Browse files
committed
Unifies command line interface with fortls files
The two interfaces now share all options which should decrease the maintainance time and also make easier adding new options. A dictionary with the possible command line options is passed into LangServer which is then used to set class attributes. A unittest has been added which tests both the command line interface and the LangServer configuration file loading functions This commit also deprecates the `--preserve_keyword_order` argument and replaces it with its opposite `--sort_keywords`. Because fortls should not by default be altering the display of the written code.
1 parent 37a179a commit d92537c

File tree

9 files changed

+640
-355
lines changed

9 files changed

+640
-355
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
- Update constant parameters for `omp_lib` and `omp_lib_kinds` Interface v5.0
1818
- Format json files with `prettier`
1919
- Initialises the log channel and adds `$/setTrace` to override client's (i.e. VS Code) loglevel
20+
- Unified the interfaces from the command line and the configuration options file
21+
([gnikit/fortls#17](https://github.com/gnikit/fortls/issues/17))
22+
23+
### Deprecated
24+
25+
- Option `--preserve_keyword_order` has been substituted with its opposite `--sort_keywords`
2026

2127
### Fixed
2228

fortls/__init__.py

Lines changed: 4 additions & 300 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import print_function
22

3-
import argparse
43
import json
54
import os
65
import pprint
@@ -12,6 +11,7 @@
1211
from .jsonrpc import JSONRPC2Connection, ReadWriter, path_from_uri
1312
from .langserver import LangServer
1413
from .parse_fortran import fortran_file, process_file
14+
from .interface import commandline_args
1515

1616

1717
def error_exit(error_str):
@@ -22,7 +22,7 @@ def error_exit(error_str):
2222
def main():
2323
#
2424
freeze_support()
25-
args = parse_args()
25+
args = commandline_args(__name__).parse_args()
2626

2727
if args.version:
2828
print("{0}".format(__version__))
@@ -43,315 +43,20 @@ def main():
4343
or args.debug_workspace_symbols
4444
)
4545

46-
settings = set_settings(args)
47-
4846
if args.debug_parser:
4947
debug_server_parser(args)
5048

5149
elif debug_server:
52-
debug_server_general(args, settings)
50+
debug_server_general(args, vars(args))
5351

5452
else:
5553
stdin, stdout = _binary_stdio()
5654
LangServer(
5755
conn=JSONRPC2Connection(ReadWriter(stdin, stdout)),
58-
debug_log=args.debug_log,
59-
settings=settings,
56+
settings=vars(args),
6057
).run()
6158

6259

63-
def parse_args() -> argparse.Namespace:
64-
"""Parses the command line arguments to the Language Server
65-
66-
Returns
67-
-------
68-
argparse.Namespace
69-
command line arguments
70-
"""
71-
72-
parser = argparse.ArgumentParser(
73-
description=f"fortls {__version__}",
74-
prog=__name__,
75-
usage="%(prog)s [options] [debug options]",
76-
)
77-
78-
parser.add_argument(
79-
"-v",
80-
"--version",
81-
action="store_true",
82-
help="Print server version number and exit",
83-
)
84-
parser.add_argument(
85-
"--config", type=str, default=".fortls", help="Configuration options file"
86-
)
87-
parser.add_argument(
88-
"--nthreads",
89-
type=int,
90-
default=4,
91-
help="Number of threads to use during workspace initialization (default: 4)",
92-
)
93-
parser.add_argument(
94-
"--notify_init",
95-
action="store_true",
96-
help="Send notification message when workspace initialization is complete",
97-
)
98-
parser.add_argument(
99-
"--symbol_skip_mem",
100-
action="store_true",
101-
help="Do not include type members in document symbol results",
102-
)
103-
parser.add_argument(
104-
"--incremental_sync",
105-
action="store_true",
106-
help="Use incremental document synchronization (beta)",
107-
)
108-
parser.add_argument(
109-
"--autocomplete_no_prefix",
110-
action="store_true",
111-
help="Do not filter autocomplete results by variable prefix",
112-
)
113-
parser.add_argument(
114-
"--autocomplete_no_snippets",
115-
action="store_true",
116-
help="Do not use snippets with place holders in autocomplete results",
117-
)
118-
parser.add_argument(
119-
"--autocomplete_name_only",
120-
action="store_true",
121-
help="Complete only the name of procedures and not the parameters",
122-
)
123-
parser.add_argument(
124-
"--lowercase_intrinsics",
125-
action="store_true",
126-
help="Use lowercase for intrinsics and keywords in autocomplete requests",
127-
)
128-
parser.add_argument(
129-
"--use_signature_help",
130-
action="store_true",
131-
help="Use signature help instead of subroutine/function snippets",
132-
)
133-
parser.add_argument(
134-
"--variable_hover",
135-
action="store_true",
136-
help=(
137-
"Show hover information for variables (default: subroutines/functions only)"
138-
),
139-
)
140-
parser.add_argument(
141-
"--hover_signature",
142-
action="store_true",
143-
help=(
144-
"Show signature information in hover for argument (also enables"
145-
" '--variable_hover')"
146-
),
147-
)
148-
parser.add_argument(
149-
"--hover_language",
150-
type=str,
151-
default=None,
152-
help=(
153-
"Language used for responses to hover requests (for editor syntax"
154-
" highlighting)"
155-
),
156-
)
157-
parser.add_argument(
158-
"--preserve_keyword_order",
159-
action="store_true",
160-
help=(
161-
"Display variable keywords information in original order (default: sort to"
162-
" consistent ordering)"
163-
),
164-
)
165-
parser.add_argument(
166-
"--enable_code_actions",
167-
action="store_true",
168-
help="Enable experimental code actions (default: false)",
169-
)
170-
parser.add_argument(
171-
"--max_line_length",
172-
type=int,
173-
default=-1,
174-
help="Maximum line length (default: none)",
175-
)
176-
parser.add_argument(
177-
"--max_comment_line_length",
178-
type=int,
179-
default=-1,
180-
help="Maximum comment line length (default: none)",
181-
)
182-
parser.add_argument(
183-
"--disable_diagnostics", action="store_true", help="Disable diagnostics"
184-
)
185-
parser.add_argument(
186-
"--debug_log",
187-
action="store_true",
188-
help="Generate debug log in project root folder",
189-
)
190-
parser.add_argument(
191-
"--debug_help", action="help", help="Display options for debugging fortls"
192-
)
193-
194-
# By default debug arguments are hidden
195-
parse_debug_args(parser)
196-
197-
return parser.parse_args()
198-
199-
200-
def parse_debug_args(parser: argparse.ArgumentParser) -> None:
201-
"""Parse the debug arguments if any are present.
202-
if none are present the arguments are suppressed in the help menu
203-
204-
Parameters
205-
----------
206-
parser : argparse.ArgumentParser
207-
an argument parser
208-
209-
Returns
210-
-------
211-
None
212-
Operates and updates the parser
213-
"""
214-
215-
# Only show debug options if an argument starting with --debug_ was input.
216-
# if suppressed the option will be hidden from the help menu.
217-
HIDE_DEBUG = True
218-
if any("--debug_" in arg for arg in sys.argv):
219-
HIDE_DEBUG = False
220-
221-
def hide_opt(help: str) -> str:
222-
if not HIDE_DEBUG:
223-
return help
224-
else:
225-
return argparse.SUPPRESS
226-
227-
group = parser.add_argument_group(
228-
hide_opt("DEBUG"), hide_opt("Options for debugging language server")
229-
)
230-
group.add_argument(
231-
"--debug_parser",
232-
action="store_true",
233-
help=hide_opt("Test source code parser on specified file"),
234-
)
235-
group.add_argument(
236-
"--debug_diagnostics",
237-
action="store_true",
238-
help=hide_opt("Test diagnostic notifications for specified file"),
239-
)
240-
group.add_argument(
241-
"--debug_symbols",
242-
action="store_true",
243-
help=hide_opt("Test symbol request for specified file"),
244-
)
245-
group.add_argument(
246-
"--debug_workspace_symbols",
247-
type=str,
248-
help=hide_opt("Test workspace/symbol request"),
249-
)
250-
group.add_argument(
251-
"--debug_completion",
252-
action="store_true",
253-
help=hide_opt("Test completion request for specified file and position"),
254-
)
255-
group.add_argument(
256-
"--debug_signature",
257-
action="store_true",
258-
help=hide_opt("Test signatureHelp request for specified file and position"),
259-
)
260-
group.add_argument(
261-
"--debug_definition",
262-
action="store_true",
263-
help=hide_opt("Test definition request for specified file and position"),
264-
)
265-
group.add_argument(
266-
"--debug_hover",
267-
action="store_true",
268-
help=hide_opt("Test hover request for specified file and position"),
269-
)
270-
group.add_argument(
271-
"--debug_implementation",
272-
action="store_true",
273-
help=hide_opt("Test implementation request for specified file and position"),
274-
)
275-
group.add_argument(
276-
"--debug_references",
277-
action="store_true",
278-
help=hide_opt("Test references request for specified file and position"),
279-
)
280-
group.add_argument(
281-
"--debug_rename",
282-
type=str,
283-
help=hide_opt("Test rename request for specified file and position"),
284-
)
285-
group.add_argument(
286-
"--debug_actions",
287-
action="store_true",
288-
help=hide_opt("Test codeAction request for specified file and position"),
289-
)
290-
group.add_argument(
291-
"--debug_filepath",
292-
type=str,
293-
help=hide_opt("File path for language server tests"),
294-
)
295-
group.add_argument(
296-
"--debug_rootpath",
297-
type=str,
298-
help=hide_opt("Root path for language server tests"),
299-
)
300-
group.add_argument(
301-
"--debug_line",
302-
type=int,
303-
help=hide_opt("Line position for language server tests (1-indexed)"),
304-
)
305-
group.add_argument(
306-
"--debug_char",
307-
type=int,
308-
help=hide_opt("Character position for language server tests (1-indexed)"),
309-
)
310-
group.add_argument(
311-
"--debug_full_result",
312-
action="store_true",
313-
help=hide_opt("Print full result object instead of condensed version"),
314-
)
315-
316-
317-
def set_settings(args):
318-
"""Sets the settings dictionary from the command line arguments
319-
320-
Parameters
321-
----------
322-
args : Namespace
323-
command line arguments
324-
325-
Returns
326-
-------
327-
dict[str, Any]
328-
settings for the Language Server
329-
"""
330-
settings = {
331-
"config": args.config,
332-
"nthreads": args.nthreads,
333-
"notify_init": args.notify_init,
334-
"symbol_include_mem": (not args.symbol_skip_mem),
335-
"sync_type": 2 if args.incremental_sync else 1,
336-
"autocomplete_no_prefix": args.autocomplete_no_prefix,
337-
"autocomplete_no_snippets": args.autocomplete_no_snippets,
338-
"autocomplete_name_only": args.autocomplete_name_only,
339-
"lowercase_intrinsics": args.lowercase_intrinsics,
340-
"use_signature_help": args.use_signature_help,
341-
"variable_hover": (args.variable_hover or args.hover_signature),
342-
"hover_signature": args.hover_signature,
343-
"sort_keywords": (not args.preserve_keyword_order),
344-
"enable_code_actions": (args.enable_code_actions or args.debug_actions),
345-
"max_line_length": args.max_line_length,
346-
"max_comment_line_length": args.max_comment_line_length,
347-
"disable_diagnostics": args.disable_diagnostics,
348-
}
349-
if args.hover_language is not None:
350-
settings["hover_language"] = args.hover_language
351-
352-
return settings
353-
354-
35560
def debug_server_general(args, settings):
35661
"""Outputs debug information about the server.
35762
Triggers with any option under the DEBUG group except debug parser.
@@ -369,7 +74,6 @@ def debug_server_general(args, settings):
36974
tmpout = os.fdopen(pwb, "wb")
37075
s = LangServer(
37176
conn=JSONRPC2Connection(ReadWriter(tmpin, tmpout)),
372-
debug_log=args.debug_log,
37377
settings=settings,
37478
)
37579
#

0 commit comments

Comments
 (0)