File tree 9 files changed +276
-0
lines changed
9 files changed +276
-0
lines changed Original file line number Diff line number Diff line change
1
+ # Static project files
2
+ /env /
3
+
4
+ # Python files
5
+ .Python
6
+ .python-version
7
+ * .pyc
8
+ __pycache__
9
+ pip-selfcheck.json
10
+
11
+ # Build files
12
+ * .egg-info /
13
+ /build /
14
+ /dist /
15
+
16
+ # OS and project files
17
+ .DS_Store
18
+ .mypy_cache
19
+ .template-version
20
+ .vscode
21
+ .pytest_cache /
22
+ .env
23
+ * .swp
24
+ .idea /
25
+ .helix /
26
+
27
+ # Coverage
28
+ .coverage
29
+ coverage.xml
30
+ htmlcov /
Original file line number Diff line number Diff line change
1
+ # Django template LSP
2
+
3
+ A simple Django template LSP for completions
4
+
5
+
6
+
7
+ ## Install
8
+
9
+ pip install django-template-lsp
10
+
11
+
12
+ ## Editors
13
+
14
+ ### Helix
15
+
16
+ In your global or project ` languages.toml ` add the following
17
+
18
+ ``` toml
19
+ [language-server .djlsp ]
20
+ command = " djlsp"
21
+
22
+ [[language ]]
23
+ name = " html"
24
+ language-servers = [ " vscode-html-language-server" , " djlsp" ]
25
+ ```
Original file line number Diff line number Diff line change
1
+ __version__ = "0.1.0"
Original file line number Diff line number Diff line change
1
+ from djlsp .cli import main
2
+
3
+ main ()
Original file line number Diff line number Diff line change
1
+ from djlsp .server import server
2
+
3
+
4
+ def main ():
5
+ server .start_io ()
Original file line number Diff line number Diff line change
1
+ import re
2
+
3
+ TAGS = [
4
+ "autoescape" ,
5
+ "block" ,
6
+ "comment" ,
7
+ "filter" ,
8
+ "for" ,
9
+ "if" ,
10
+ "ifchanged" ,
11
+ "spaceless" ,
12
+ "verbatim" ,
13
+ "with" ,
14
+ # TODO: check if i18n is loaded
15
+ "blocktranslate" ,
16
+ # TODO: check if l10n is loaded
17
+ "localize" ,
18
+ # TODO: check if tz is loaded
19
+ "localtime" ,
20
+ "timezone" ,
21
+ ]
22
+
23
+ SIMPLE_TAGS = [
24
+ "csrf_token" ,
25
+ "cycle" ,
26
+ "debug" ,
27
+ "extends" ,
28
+ "firstof" ,
29
+ "include" ,
30
+ "load" ,
31
+ "lorem" ,
32
+ "now" ,
33
+ "regroup" ,
34
+ "resetcycle" ,
35
+ "templatetag" ,
36
+ "url" ,
37
+ "widthratio" ,
38
+ # TODO: check if statis is loaded
39
+ "static" ,
40
+ # TODO: check if i18n is loaded
41
+ "translate" ,
42
+ # TODO: Hack to make empy and else work, should check if inside if or for
43
+ "empty" ,
44
+ "else" ,
45
+ ]
46
+
47
+ FILTERS = [
48
+ "add" ,
49
+ "addslashes" ,
50
+ "capfirst" ,
51
+ "center" ,
52
+ "cut" ,
53
+ "date" ,
54
+ "default" ,
55
+ "default_if_none" ,
56
+ "dictsort" ,
57
+ "dictsortreversed" ,
58
+ "divisibleby" ,
59
+ "escape" ,
60
+ "escapejs" ,
61
+ "escapeseq" ,
62
+ "filesizeformat" ,
63
+ "first" ,
64
+ "floatformat" ,
65
+ "force_escape" ,
66
+ "get_digit" ,
67
+ "iriencode" ,
68
+ "join" ,
69
+ "json_script" ,
70
+ "last" ,
71
+ "length" ,
72
+ "length_is" ,
73
+ "linebreaks" ,
74
+ "linebreaksbr" ,
75
+ "linenumbers" ,
76
+ "ljust" ,
77
+ "lower" ,
78
+ "make_list" ,
79
+ "phone2numeric" ,
80
+ "pluralize" ,
81
+ "pprint" ,
82
+ "random" ,
83
+ "rjust" ,
84
+ "safe" ,
85
+ "safeseq" ,
86
+ "slice" ,
87
+ "slugify" ,
88
+ "stringformat" ,
89
+ "striptags" ,
90
+ "time" ,
91
+ "timesince" ,
92
+ "timeuntil" ,
93
+ "title" ,
94
+ "truncatechars" ,
95
+ "truncatechars_html" ,
96
+ "truncatewords" ,
97
+ "truncatewords_html" ,
98
+ "unordered_list" ,
99
+ "upper" ,
100
+ "urlencode" ,
101
+ "urlize" ,
102
+ "urlizetrunc" ,
103
+ "wordcount" ,
104
+ "wordwrap" ,
105
+ "yesno" ,
106
+ # TODO: check if l10n is loaded
107
+ "localize" ,
108
+ "unlocalize" ,
109
+ # TODO: check if tz is loaded
110
+ "localtime" ,
111
+ "utc" ,
112
+ "timezone" ,
113
+ ]
114
+
115
+ re_tag = re .compile (r"^.*{% ?(\w*)$" )
116
+ re_end_tag = re .compile (r"^.*{% ?(e\w*)$" )
117
+ re_filter = re .compile (r"^.*({%|{{) ?[\w \.\|]*\|(\w*)$" )
118
+
119
+
120
+ def get_completions (line_fragment ):
121
+ # TODO: Maybe replace logic with tree-sitter
122
+
123
+ if match := re_filter .match (line_fragment ):
124
+ search = match .group (2 ).lower ()
125
+ for filter_name in FILTERS :
126
+ if filter_name .startswith (search ):
127
+ yield filter_name
128
+ elif match := re_end_tag .match (line_fragment ):
129
+ # TODO only show end tags for open/used tags
130
+ search = match .group (1 ).lower ()
131
+ for tag in TAGS :
132
+ end_tag = f"end{ tag } "
133
+ if end_tag .startswith (search ):
134
+ yield end_tag
135
+ elif match := re_tag .match (line_fragment ):
136
+ search = match .group (1 )
137
+ for tag in TAGS + SIMPLE_TAGS :
138
+ if tag .startswith (search ):
139
+ yield tag
Original file line number Diff line number Diff line change
1
+ from lsprotocol .types import (TEXT_DOCUMENT_COMPLETION ,
2
+ TEXT_DOCUMENT_DID_CHANGE , CompletionItem ,
3
+ CompletionList , CompletionOptions ,
4
+ CompletionParams , DidChangeTextDocumentParams )
5
+ from pygls .server import LanguageServer
6
+
7
+ from djlsp import __version__
8
+ from djlsp .completion import get_completions
9
+
10
+ server = LanguageServer ("django-template-lsp" , __version__ )
11
+
12
+
13
+ @server .feature (
14
+ TEXT_DOCUMENT_COMPLETION , CompletionOptions (trigger_characters = [" " , "|" ])
15
+ )
16
+ def completions (params : CompletionParams ):
17
+ items = []
18
+ document = server .workspace .get_document (params .text_document .uri )
19
+ line_fragment = document .lines [params .position .line ][: params .position .character ]
20
+ for completion in get_completions (line_fragment ):
21
+ items .append (CompletionItem (label = completion ))
22
+ return CompletionList (is_incomplete = False , items = items )
Original file line number Diff line number Diff line change
1
+ import os
2
+
3
+ from setuptools import Command , find_packages , setup
4
+
5
+ from djlsp import __version__
6
+
7
+
8
+ def readme ():
9
+ with open ("README.md" ) as f :
10
+ return f .read ()
11
+
12
+
13
+ setup (
14
+ name = "django-template-lsp" ,
15
+ version = __version__ ,
16
+ description = "Django template LSP" ,
17
+ long_description = readme (),
18
+ long_description_content_type = "text/markdown" ,
19
+ packages = find_packages (include = ["djlsp" , "djlsp.*" ]),
20
+ entry_points = {
21
+ "console_scripts" : [
22
+ "djlsp = djlsp.cli:main" ,
23
+ "django-template-lsp = djlsp.cli:main" ,
24
+ ]
25
+ },
26
+ python_requires = ">= 3.9" ,
27
+ install_requires = [
28
+ "pygls" ,
29
+ ],
30
+ extras_require = {
31
+ "dev" : [
32
+ "black" ,
33
+ "isort" ,
34
+ "flake8" ,
35
+ "pytest" ,
36
+ "pytest-check" ,
37
+ "pytest-cov" ,
38
+ ]
39
+ },
40
+ )
Original file line number Diff line number Diff line change
1
+ {% if asdsad|
2
+ asdssd
3
+ asdsda asdds
4
+ {%}
5
+ {% ifchanged }
6
+
7
+ {% e}
8
+
9
+
10
+ {% blocktranslate %}
11
+ :
You can’t perform that action at this time.
0 commit comments