lispython 0.4.3__tar.gz → 0.4.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {lispython-0.4.3 → lispython-0.4.6}/PKG-INFO +23 -11
  2. {lispython-0.4.3 → lispython-0.4.6}/README.md +21 -10
  3. {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/expressions.md +2 -2
  4. lispython-0.4.6/docs/usage/cli.md +41 -0
  5. {lispython-0.4.3 → lispython-0.4.6}/mkdocs.yml +1 -1
  6. {lispython-0.4.3 → lispython-0.4.6}/pyproject.toml +5 -2
  7. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/macro.py +19 -1
  8. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/nodes.py +5 -1
  9. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/server.lpy +79 -0
  10. lispython-0.4.6/src/lispy/tools.lpy +720 -0
  11. lispython-0.4.6/tests/test_literal_unwrap.py +73 -0
  12. {lispython-0.4.3 → lispython-0.4.6}/uv.lock +24 -1
  13. lispython-0.4.3/docs/usage/cli.md +0 -22
  14. lispython-0.4.3/src/lispy/tools.lpy +0 -228
  15. {lispython-0.4.3 → lispython-0.4.6}/.claude/settings.local.json +0 -0
  16. {lispython-0.4.3 → lispython-0.4.6}/.gitignore +0 -0
  17. {lispython-0.4.3 → lispython-0.4.6}/.pre-commit-config.yaml +0 -0
  18. {lispython-0.4.3 → lispython-0.4.6}/.vscode/settings.json +0 -0
  19. {lispython-0.4.3 → lispython-0.4.6}/LICENSE.md +0 -0
  20. {lispython-0.4.3 → lispython-0.4.6}/docs/index.md +0 -0
  21. {lispython-0.4.3 → lispython-0.4.6}/docs/macros.md +0 -0
  22. {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/overview.md +0 -0
  23. {lispython-0.4.3 → lispython-0.4.6}/docs/syntax/statements.md +0 -0
  24. {lispython-0.4.3 → lispython-0.4.6}/docs/usage/getting-started.md +0 -0
  25. {lispython-0.4.3 → lispython-0.4.6}/docs/version_macro.py +0 -0
  26. {lispython-0.4.3 → lispython-0.4.6}/docs/why-lispy.md +0 -0
  27. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/__init__.py +0 -0
  28. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/builtins.py +0 -0
  29. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/__init__.py +0 -0
  30. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/expr.py +0 -0
  31. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/literal.py +0 -0
  32. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/stmt.py +0 -0
  33. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/compiler/utils.py +0 -0
  34. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/importer.py +0 -0
  35. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/meta_functions.py +0 -0
  36. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/parser.py +0 -0
  37. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core/utils.py +0 -0
  38. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/core_meta_functions.lpy +0 -0
  39. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/__init__.py +0 -0
  40. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/lsp/__main__.py +0 -0
  41. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/__init__.py +0 -0
  42. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/init.lpy +0 -0
  43. {lispython-0.4.3 → lispython-0.4.6}/src/lispy/macros/sugar.lpy +0 -0
  44. {lispython-0.4.3 → lispython-0.4.6}/tests/__init__.py +0 -0
  45. {lispython-0.4.3 → lispython-0.4.6}/tests/test_as_thread.py +0 -0
  46. {lispython-0.4.3 → lispython-0.4.6}/tests/test_expr.py +0 -0
  47. {lispython-0.4.3 → lispython-0.4.6}/tests/test_gensym.py +0 -0
  48. {lispython-0.4.3 → lispython-0.4.6}/tests/test_include_meta.py +0 -0
  49. {lispython-0.4.3 → lispython-0.4.6}/tests/test_literal.py +0 -0
  50. {lispython-0.4.3 → lispython-0.4.6}/tests/test_meta_functions.py +0 -0
  51. {lispython-0.4.3 → lispython-0.4.6}/tests/test_parser.py +0 -0
  52. {lispython-0.4.3 → lispython-0.4.6}/tests/test_stmt.py +0 -0
  53. {lispython-0.4.3 → lispython-0.4.6}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lispython
3
- Version: 0.4.3
3
+ Version: 0.4.6
4
4
  Summary: Lisp-like Syntax for Python with Lisp-like Macros
5
5
  Project-URL: Homepage, https://jetack.github.io/lispython
6
6
  Project-URL: Repository, https://github.com/jetack/lispython
@@ -8,6 +8,7 @@ Author-email: Jetack <jetack23@gmail.com>
8
8
  License: MIT
9
9
  License-File: LICENSE.md
10
10
  Requires-Python: >=3.11
11
+ Requires-Dist: prompt-toolkit>=3.0.52
11
12
  Requires-Dist: pygls>=1.0.0
12
13
  Provides-Extra: dev
13
14
  Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
@@ -84,25 +85,36 @@ lpy -m pytest
84
85
  LisPython ships with a language server (`lpy-lsp`) that speaks LSP over stdio. It provides:
85
86
 
86
87
  - Diagnostics (parse / compile errors)
87
- - Hover documentation for special forms
88
+ - Completions (special forms, builtins, file/workspace symbols)
89
+ - Hover documentation for special forms and builtins
88
90
  - Document symbols
89
91
  - Go-to-definition, including across `.lpy` files in the workspace
90
92
 
93
+ ## nREPL Server
94
+ LisPython includes an nREPL server for REPL-driven development:
95
+
96
+ ```bash
97
+ lpy --nrepl # start on a random port
98
+ lpy --nrepl 7888 # start on a specific port
99
+ ```
100
+
101
+ The server accepts newline-delimited JSON over TCP and supports:
102
+ - `eval` — evaluate LisPython code, return value/stdout/error
103
+ - `load-file` — load a `.lpy` file into the session
104
+ - `macroexpand` — expand macros and return the result
105
+ - `complete` — prefix and dot-completion from the live scope
106
+ - `docs` — signature and docstring for a symbol
107
+ - `annotate` — type tag (function/class/module/macro)
108
+
91
109
  ### Editor setup
92
- Point your editor's LSP client at the `lpy-lsp` command for files with the `.lpy` extension. The server speaks LSP over stdio.
93
110
 
94
- #### VSCode
95
- Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension from the VSCode Marketplace.
111
+ #### VS Code
112
+ Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension. It connects to both LSP and nREPL automatically.
96
113
 
97
114
  #### Emacs
98
- Use [`lpy-mode`](https://github.com/jetack/lpy-mode) for syntax highlighting and LSP integration. For completion, install [`lpy-autocomplete`](https://github.com/jetack/lpy-autocomplete).
115
+ Use [`lpy-mode`](https://github.com/jetack/lpy-mode). It provides nREPL integration (eval, completion, eldoc, macroexpand) and LSP via eglot.
99
116
 
100
117
  ## Todo
101
- ### Environment
102
- - [ ] Test on more python versions
103
- - [ ] REPL should track history and arrow key navigation
104
- - [ ] REPL multi-line input support
105
- - [ ] Better compilation error messages
106
118
  ### Python AST
107
119
  - [ ] `type_comment` never considered. Later, it should be covered
108
120
  - [ ] Any missing AST nodes in the version 3.12+
@@ -62,25 +62,36 @@ lpy -m pytest
62
62
  LisPython ships with a language server (`lpy-lsp`) that speaks LSP over stdio. It provides:
63
63
 
64
64
  - Diagnostics (parse / compile errors)
65
- - Hover documentation for special forms
65
+ - Completions (special forms, builtins, file/workspace symbols)
66
+ - Hover documentation for special forms and builtins
66
67
  - Document symbols
67
68
  - Go-to-definition, including across `.lpy` files in the workspace
68
69
 
70
+ ## nREPL Server
71
+ LisPython includes an nREPL server for REPL-driven development:
72
+
73
+ ```bash
74
+ lpy --nrepl # start on a random port
75
+ lpy --nrepl 7888 # start on a specific port
76
+ ```
77
+
78
+ The server accepts newline-delimited JSON over TCP and supports:
79
+ - `eval` — evaluate LisPython code, return value/stdout/error
80
+ - `load-file` — load a `.lpy` file into the session
81
+ - `macroexpand` — expand macros and return the result
82
+ - `complete` — prefix and dot-completion from the live scope
83
+ - `docs` — signature and docstring for a symbol
84
+ - `annotate` — type tag (function/class/module/macro)
85
+
69
86
  ### Editor setup
70
- Point your editor's LSP client at the `lpy-lsp` command for files with the `.lpy` extension. The server speaks LSP over stdio.
71
87
 
72
- #### VSCode
73
- Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension from the VSCode Marketplace.
88
+ #### VS Code
89
+ Install the [LisPython](https://marketplace.visualstudio.com/items?itemName=jetack.vscode-lispython) extension. It connects to both LSP and nREPL automatically.
74
90
 
75
91
  #### Emacs
76
- Use [`lpy-mode`](https://github.com/jetack/lpy-mode) for syntax highlighting and LSP integration. For completion, install [`lpy-autocomplete`](https://github.com/jetack/lpy-autocomplete).
92
+ Use [`lpy-mode`](https://github.com/jetack/lpy-mode). It provides nREPL integration (eval, completion, eldoc, macroexpand) and LSP via eglot.
77
93
 
78
94
  ## Todo
79
- ### Environment
80
- - [ ] Test on more python versions
81
- - [ ] REPL should track history and arrow key navigation
82
- - [ ] REPL multi-line input support
83
- - [ ] Better compilation error messages
84
95
  ### Python AST
85
96
  - [ ] `type_comment` never considered. Later, it should be covered
86
97
  - [ ] Any missing AST nodes in the version 3.12+
@@ -38,11 +38,11 @@ Python version
38
38
  expr1 == expr2 == expr3 == ...
39
39
  ```
40
40
  #### `>`
41
- Python version
41
+ LisPy version
42
42
  ```python
43
43
  (> expr1 expr2 expr3 ...)
44
44
  ```
45
- LisPy version
45
+ Python version
46
46
  ```python
47
47
  expr1 > expr2 > expr3 > ...
48
48
  ```
@@ -0,0 +1,41 @@
1
+ ## REPL
2
+ ```shell
3
+ lpy
4
+ #or
5
+ lpy -t #if you want to print python translation.
6
+ ```
7
+
8
+ The REPL features Emacs-style keybindings (C-a, C-e, C-b, C-f, M-b, M-f, etc.), arrow key navigation, and persistent command history saved to `~/.lpy_history`.
9
+
10
+ ### Auto-closing pairs
11
+
12
+ The REPL automatically inserts closing brackets and quotes when you type an opening one:
13
+
14
+ | You type | REPL inserts | Cursor position |
15
+ |----------|-------------|-----------------|
16
+ | `(` | `()` | between `(` and `)` |
17
+ | `[` | `[]` | between `[` and `]` |
18
+ | `{` | `{}` | between `{` and `}` |
19
+ | `'` | `''` | between the quotes |
20
+ | `"` | `""` | between the quotes |
21
+
22
+ - Typing a closing character (`)`, `]`, `}`) when the cursor is already before one will skip over it instead of inserting a duplicate.
23
+ - Typing a quote (`'`, `"`) when the cursor is before the same quote will skip over it.
24
+ - Pressing backspace between an empty pair deletes both characters.
25
+
26
+ ## Run from source
27
+ ```shell
28
+ lpy {filename}.lpy
29
+ ```
30
+ ## Run translation
31
+ ```shell
32
+ l2py {filename}.lpy
33
+ ```
34
+ It just displays translation. (don't run it)
35
+ ## Run Tests (for development)
36
+ ```shell
37
+ # in project root directory
38
+ pytest
39
+ #or
40
+ lpy -m pytest
41
+ ```
@@ -1,6 +1,6 @@
1
1
  site_name: LisPython
2
2
 
3
- copyright: Copytright &copy; 2023-2025 Jetack
3
+ copyright: Copyright &copy; 2023-2026 Jetack
4
4
 
5
5
  plugins:
6
6
  - macros:
@@ -1,12 +1,15 @@
1
1
  [project]
2
2
  name = "lispython"
3
- version = "0.4.3"
3
+ version = "0.4.6"
4
4
  description = "Lisp-like Syntax for Python with Lisp-like Macros"
5
5
  authors = [{ name = "Jetack", email = "jetack23@gmail.com" }]
6
6
  license = { text = "MIT" }
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.11"
9
- dependencies = ["pygls>=1.0.0"]
9
+ dependencies = [
10
+ "prompt-toolkit>=3.0.52",
11
+ "pygls>=1.0.0",
12
+ ]
10
13
 
11
14
  [project.urls]
12
15
  Homepage = "https://jetack.github.io/lispython"
@@ -8,6 +8,22 @@ from lispy.core.nodes import *
8
8
 
9
9
  __macro_namespace: Dict[str, Callable[[Node], ast.AST]] = {}
10
10
 
11
+ _ast_literal_eval = __import__("ast").literal_eval
12
+
13
+
14
+ def _unwrap_literal(node):
15
+ if isinstance(node, Constant):
16
+ try:
17
+ return _ast_literal_eval(node.value)
18
+ except (ValueError, SyntaxError):
19
+ return node
20
+ elif isinstance(node, String):
21
+ try:
22
+ return _ast_literal_eval(node.value)
23
+ except (ValueError, SyntaxError):
24
+ return node
25
+ return node
26
+
11
27
 
12
28
  def define_macro(sexp, scope, include_meta=True):
13
29
  transformed = defmacro_transform(sexp)
@@ -69,7 +85,9 @@ def macroexpand_1_and_check(sexp, scope=globals(), in_quasi=False, include_meta=
69
85
  elif str(op) == "require" and not in_quasi:
70
86
  sexp = require_macro(sexp, scope, include_meta=include_meta)
71
87
  elif str(op) in scope.setdefault("__macro_namespace", {}) and not in_quasi and isinstance(sexp, Paren):
72
- sexp = scope["__macro_namespace"][str(op)](*operands)
88
+ sexp = scope["__macro_namespace"][str(op)](*[_unwrap_literal(o) for o in operands])
89
+ if not isinstance(sexp, Node):
90
+ sexp = data_to_generator_expression(sexp)
73
91
  expanded = True
74
92
  else:
75
93
  expanded_list, expanded_feedbacks = zip(
@@ -44,7 +44,11 @@ class Node:
44
44
 
45
45
 
46
46
  def data_to_generator_expression(data):
47
- if isinstance(data, str):
47
+ if isinstance(data, bool) or data is None:
48
+ return Constant(str(data))
49
+ elif isinstance(data, (int, float, complex)):
50
+ return Constant(str(data))
51
+ elif isinstance(data, str):
48
52
  return String('"' + data + '"')
49
53
  elif isinstance(data, list):
50
54
  return Bracket(*data)
@@ -751,6 +751,85 @@
751
751
  :range (make-range lineno 0 lineno 0))])))))
752
752
  (return None)))
753
753
 
754
+ ;; ---------------------------------------------------------------------------
755
+ ;; Completion
756
+ ;; ---------------------------------------------------------------------------
757
+
758
+ (= _LPY-KEYWORDS
759
+ ["defn" "cond" "conde" "ife" "when" "unless"
760
+ "do" "deco" "require" "fn" "match" "case"
761
+ "async-def" "async-for" "async-with"
762
+ "yield-from" "except*"
763
+ "->" "->>" "as->"
764
+ "gensym" "pprint"])
765
+
766
+ (deco (server.feature
767
+ lsp.TEXT_DOCUMENT_COMPLETION
768
+ (lsp.CompletionOptions :trigger-characters ["." "-"]))
769
+ (def completion [ls params]
770
+ (= doc (.get-text-document ls.workspace params.text_document.uri))
771
+ (= pos params.position)
772
+ (= items [])
773
+ (= seen (set))
774
+
775
+ ;; 1. Special forms
776
+ (for name in SPECIAL-FORM-DOCS
777
+ (if (not (in name seen))
778
+ (do (seen.add name)
779
+ (items.append
780
+ (lsp.CompletionItem
781
+ :label name
782
+ :kind lsp.CompletionItemKind.Keyword
783
+ :detail "special form")))))
784
+
785
+ ;; 2. LisPython-specific keywords
786
+ (for name in _LPY-KEYWORDS
787
+ (if (not (in name seen))
788
+ (do (seen.add name)
789
+ (items.append
790
+ (lsp.CompletionItem
791
+ :label name
792
+ :kind lsp.CompletionItemKind.Keyword
793
+ :detail "keyword")))))
794
+
795
+ ;; 3. Python builtins
796
+ (for [name info] in (BUILTIN-INFO.items)
797
+ (if (not (in name seen))
798
+ (do (seen.add name)
799
+ (= kind (ife (isinstance (getattr builtins name None) type)
800
+ lsp.CompletionItemKind.Class
801
+ lsp.CompletionItemKind.Function))
802
+ (items.append
803
+ (lsp.CompletionItem
804
+ :label name
805
+ :kind kind
806
+ :detail (or (.get info "signature") ""))))))
807
+
808
+ ;; 4. Symbols from current file
809
+ (try
810
+ (= tree (parse doc.source))
811
+ (= defs (collect-definitions tree doc.uri))
812
+ (for name in defs
813
+ (if (not (in name seen))
814
+ (do (seen.add name)
815
+ (items.append
816
+ (lsp.CompletionItem
817
+ :label name
818
+ :kind lsp.CompletionItemKind.Variable)))))
819
+ (except [Exception] (pass)))
820
+
821
+ ;; 5. Workspace symbols
822
+ (for name in WORKSPACE-INDEX
823
+ (if (not (in name seen))
824
+ (do (seen.add name)
825
+ (items.append
826
+ (lsp.CompletionItem
827
+ :label name
828
+ :kind lsp.CompletionItemKind.Variable
829
+ :detail "workspace")))))
830
+
831
+ (return (lsp.CompletionList :is-incomplete False :items items))))
832
+
754
833
  (deco (server.feature lsp.TEXT_DOCUMENT_REFERENCES)
755
834
  (def references [ls params]
756
835
  (= doc (.get-text-document ls.workspace params.text_document.uri))