|
1 | | -[](https://discord.gg/FvdkuVyted) |
2 | | - |
3 | | - |
4 | | -<img alt="Lexical logo: Lexi the lynx" src="assets/lexi-logo.svg" width="150" height="200" align="right"/> |
5 | | - |
6 | 1 | # Expert |
7 | 2 |
|
8 | | -Expert is a next-generation language server for the Elixir programming language. |
9 | | - |
10 | | -<br><br><br> |
11 | | - |
12 | | -### Note: Development on Lexical will slow while we transition to the new combined effort, Expert. |
13 | | - |
14 | | -## Features |
15 | | - |
16 | | - * Context aware code completion |
17 | | - * As-you-type compilation |
18 | | - * Advanced error highlighting |
19 | | - * Code actions |
20 | | - * Code Formatting |
21 | | - * Go To Definition |
22 | | - * Completely isolated build environment |
23 | | - |
24 | | -## What makes Lexical different? |
25 | | -There are a couple things that lexical does differently than other language servers. Let's look at what separates it from |
26 | | -the pack. |
27 | | - |
28 | | -#### Architecture |
29 | | - |
30 | | -When lexical starts, it boots an erlang virtual machine that runs the language server and its code. It then boots a |
31 | | -separate virtual machine that runs your project code and connects the two via distribution. This provides the following benefits: |
32 | | - |
33 | | - * None of lexical's dependencies will conflict with your project. This means that lexical can make use of dependencies to make developing in it easier without having to "vendor" them. It also means that you can use lexical to work on your project, **even if lexical depends on your project**. |
34 | | - * Your project can depend on a different version of elixir and erlang than lexical itself. This means that lexical can make use of the latest versions of elixir and erlang while still supporting projects that run on older versions. |
35 | | - * The build environment for your project is only aware of your project, which enables as-you-type compilation and error reporting. |
36 | | - * In the future, there is a possibility of having the lexical vm instance control multiple projects |
37 | | - |
38 | | -#### Ease of contribution |
39 | | - |
40 | | -Lexical has been designed to be easy to contribute to and work on. It features: |
41 | | - |
42 | | - * A consistent data model that represents the Language Server Protocol and `mix` tasks to generate new Language Server models. |
43 | | - * A clearly defined separation between the language server and project code |
44 | | - * A set of utilities that deal with manipulating code |
45 | | - * A set of unit tests and test cases that make testing new features easy. |
46 | | - |
47 | | -#### Focus on developer productivity |
48 | | - |
49 | | -Lexical is also built with an eye on increasing developer productivity, and approaches some common features a little bit |
50 | | -differently. For example, Lexical's code completion is _context aware_, which means that if you type `alias MyModule.|` |
51 | | -you will only receive completions for modules and not the names of functions in `MyModule`. This awareness will extend |
52 | | -to other areas, which means: |
53 | | - |
54 | | - * You won't see completions for random functions and types in strings. In fact, when extended to string literals, Lexical will only show you completions if you're inside of an interpolation (`"hello there #{na|}'`). |
55 | | - * If you're inside of a struct reference (`%StructModule.|`), you will only see modules listed that define structs, or are the parents of modules that define structs. |
56 | | - |
57 | | -Because of this focus, Lexical aims to deliver depth of features rather than breadth of them. We'll likely spend |
58 | | -more time making sure each thing we add works and feels _just right_ rather than adding a whole slew of features |
59 | | -that people mostly won't use. |
60 | | - |
61 | | -#### As you type compilation |
62 | | -Because your project is run in a separate virtual machine, we can compile the code that you're working on as you |
63 | | -type. This means you see errors _immediately_ rather than having to wait for a save. The result is you see and |
64 | | -fix typos, warnings, unused variables and a whole host of errors when they occur, which makes your code better, |
65 | | -faster. |
| 3 | +Expert is the official language server implementation for the Elixir programming language. |
66 | 4 |
|
67 | 5 | ## Installation |
68 | 6 |
|
69 | | -Follow the [Detailed Installation Instructions](pages/installation.md) |
70 | | - |
71 | | -``` |
72 | | -mix package |
73 | | -``` |
74 | | - |
75 | | -Lexical will now be available in `_build/dev/package/lexical` |
76 | | - |
77 | | -If you would like to change the output directory, you can do so with the `--path` option |
78 | | - |
79 | | -``` |
80 | | -mix package --path /path/to/lexical |
81 | | -``` |
82 | | - |
83 | | -Lexical will be available in `/path/to/lexical`. |
84 | | - |
85 | | -## Development |
86 | | - |
87 | | -Lexical is intended to run on any version of Erlang 25+ and Elixir |
88 | | -1.15+. Before beginning development, you should install Erlang |
89 | | -`25.0` and Elixir `1.15.8` and use those versions when you're |
90 | | -building code. |
91 | | - |
92 | | -You should also look at the [complete compatibility |
93 | | -matrix](pages/installation.md#caveats) do see which versions are |
94 | | -supported. |
| 7 | +You can download Expert from the [releases page](https://github.com/elixir-lang/expert/releases) for your |
| 8 | +operating system and architecture. |
95 | 9 |
|
96 | | -You're going to need a local instance in order to develop lexical, so follow the [Detailed Installation Instructions](pages/installation.md) first. |
| 10 | +For editor specific installation instructions, please refer to the [Installation Instructions](pages/installation.md) |
97 | 11 |
|
98 | | -Then, install the git hooks with |
99 | | - |
100 | | -``` |
101 | | -mix hooks |
102 | | -``` |
103 | | - |
104 | | -These are pre-commit hooks that will check for correct formatting and run credo for you. |
105 | | - |
106 | | -After this, you're ready to put together a pull request for Lexical! |
107 | | - |
108 | | -#### Benchmarks |
109 | | - |
110 | | -The `remote_control` project has a set of benchmarks that measure the speed of various internal functions and data structures. In order to use them, you first need to install [git large file storage](https://docs.github.com/en/repositories/working-with-files/managing-large-files/installing-git-large-file-storage), and then run `git pull`. Benchmarks are stored in the `benchmarks` subdirectory, and can be run via |
111 | | - |
112 | | -``` |
113 | | -mix benchmark /benchmarks/<benchmark_file>.exs |
114 | | -``` |
| 12 | +### Nightly Builds |
115 | 13 |
|
116 | | -### Logging |
| 14 | +If you want to try out the latest features, you can download a nightly build. |
117 | 15 |
|
118 | | -When lexical starts up, it creates a `.lexical` directory in the root |
119 | | -directory of a project. Inside that directory are two log files, |
120 | | -`lexical.log` and `project.log`. The `.lexical.log` log file contains |
121 | | -logging and OTP messages from the language server, while the |
122 | | -`project.log` file contains logging and OTP messages from the |
123 | | -project's node. While developing lexical, it's helpful to open up a |
124 | | -terminal and tail both of these log files so you can see any errors |
125 | | -and messages that lexical emits. To do that, run the following in a |
126 | | -terminal while in the project's root directory: |
| 16 | +Using the GH CLI, you can run the following command to download the latest nightly build: |
127 | 17 |
|
128 | 18 | ```shell |
129 | | -tail -f .lexical/*.log |
| 19 | +gh release download nightly --pattern 'expert_linux_amd64' |
130 | 20 | ``` |
131 | 21 |
|
132 | | -Note: These log files roll over when they reach 1 megabyte, so after a |
133 | | -time, it will be necessary to re-run the above command. |
134 | | - |
135 | | -### Debugging |
| 22 | +Then point your editor to the downloaded binary. |
136 | 23 |
|
137 | | -Lexical supports a debug shell, which will connect a remote shell to a |
138 | | -currently-running language server process. To use it, `cd` into your |
139 | | -lexical installation directory and run |
| 24 | +### Building from source |
140 | 25 |
|
141 | | -``` |
142 | | -./bin/debug_shell.sh <name of project> |
143 | | -``` |
| 26 | +To build Expert from source, you need Zig `1.14.1` installed on your system. |
144 | 27 |
|
145 | | -For example, if I would like to run the debug server for a server |
146 | | -running in your `lexical` project, run: |
147 | | - |
148 | | -``` |
149 | | -./bin/debug_shell.sh lexical |
150 | | -``` |
| 28 | +Then you can run the following command: |
151 | 29 |
|
152 | | -...and you will be connected to a remote IEx session _inside_ my |
153 | | -language server. This allows you to investigate processes, make |
154 | | -changes to the running code, or run `:observer`. |
155 | | - |
156 | | -While in the debugging shell, all the functions in |
157 | | -`Expert.IEx.Helpers` are imported for you, and some common |
158 | | -modules, like `Lexical.Project` and `Lexical.Document` are |
159 | | -aliased. |
160 | | - |
161 | | -You can also start the lexical server in interactive mode via |
162 | | -`./bin/start_lexical.sh iex`. Combining this with the helpers that are |
163 | | -imported will allow you to run projects and do completions entirely in |
164 | | -the shell. |
165 | | - |
166 | | - *Note*: The helpers assume that all of your projects are in folders that are siblings with your lexical project. |
167 | | - |
168 | | -Consider the example shell session: |
169 | | - |
170 | | -``` |
171 | | -./bin/start_lexical.sh iex |
172 | | -iex(1)> start_project :other |
173 | | -# the project in the ../other directory is started |
174 | | -compile_project(:other) |
175 | | -# the other project is compiled |
176 | | -iex(2)> complete :other, "defmo|" |
177 | | -[ |
178 | | - #GenLSP.Structures.CompletionItem<[ |
179 | | - detail: "", |
180 | | - insert_text: "defmacro ${1:name}($2) do\n $0\nend\n", |
181 | | - insert_text_format: :snippet, |
182 | | - kind: :class, |
183 | | - label: "defmacro (Define a macro)", |
184 | | - sort_text: "093_defmacro (Define a macro)" |
185 | | - ]>, |
186 | | - #GenLSP.Structures.CompletionItem<[ |
187 | | - detail: "", |
188 | | - insert_text: "defmacrop ${1:name}($2) do\n $0\nend\n", |
189 | | - insert_text_format: :snippet, |
190 | | - kind: :class, |
191 | | - label: "defmacrop (Define a private macro)", |
192 | | - sort_text: "094_defmacrop (Define a private macro)" |
193 | | - ]>, |
194 | | - #GenLSP.Structures.CompletionItem<[ |
195 | | - detail: "", |
196 | | - insert_text: "defmodule ${1:module name} do\n $0\nend\n", |
197 | | - insert_text_format: :snippet, |
198 | | - kind: :class, |
199 | | - label: "defmodule (Define a module)", |
200 | | - sort_text: "092_defmodule (Define a module)" |
201 | | - ]> |
202 | | -] |
| 30 | +```sh |
| 31 | +just release-local |
203 | 32 | ``` |
204 | 33 |
|
205 | | -The same kind of support is available when you run `iex -S mix` in the |
206 | | -lexical directory, and is helpful for narrowing down issues without |
207 | | -disturbing your editor flow. |
| 34 | +This will build the Expert binary and place it in the `apps/expert/burrito_out` directory. You can then point your |
| 35 | +editor to this binary. |
208 | 36 |
|
209 | 37 | ### Other resources |
210 | 38 |
|
211 | | -* [Architecture](pages/architecture.md) |
212 | | -* [Glossary](pages/glossary.md) |
| 39 | +- [Architecture](pages/architecture.md) |
| 40 | +- [Development Guide](pages/development.md) |
| 41 | +- [Glossary](pages/glossary.md) |
| 42 | +- [Installation Instructions](pages/installation.md) |
0 commit comments