File tree Expand file tree Collapse file tree 9 files changed +276
-0
lines changed Expand file tree Collapse file tree 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