aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-01-11 19:52:31 +0100
committerDanielGavin <danielgavin5@hotmail.com>2025-01-11 19:52:31 +0100
commitd22499ba966d2c2c8bb0cd4aee8ced52b986ed74 (patch)
treef58615f9bbcf3392292b25c06ffdd3227c6e0dfd
parent88a91d1328c9b48b45f97e3dc8a03f7767ef8162 (diff)
parenteec5781241a4127488e1606fdfb6672cd193a948 (diff)
Merge branch 'master' of https://github.com/DanielGavin/ols
-rw-r--r--.gitignore3
-rw-r--r--README.md53
-rwxr-xr-xbuild.sh3
-rw-r--r--editors/vscode/package.json12
-rw-r--r--editors/vscode/src/extension.ts107
-rw-r--r--editors/vscode/src/toolchain.ts2
-rw-r--r--misc/ols.schema.json2
-rw-r--r--src/common/ast.odin1
-rw-r--r--src/main.odin5
-rw-r--r--src/server/build.odin1
-rw-r--r--src/server/completion.odin1
-rw-r--r--src/server/hover.odin1
-rw-r--r--src/server/requests.odin1
-rw-r--r--src/server/snippets.odin1
14 files changed, 142 insertions, 51 deletions
diff --git a/.gitignore b/.gitignore
index 94b197c..1c6bedb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,4 +15,5 @@
/odinfmt
tests/tests
ols.json
-.vscode/ \ No newline at end of file
+.vscode/
+deno.lock
diff --git a/README.md b/README.md
index 7958a6d..c42f79c 100644
--- a/README.md
+++ b/README.md
@@ -228,24 +228,65 @@ require'lspconfig'.ols.setup {
### Emacs
+For Emacs, there are two packages available for LSP; lsp-mode and eglot.
+
+The latter is built-in, spec-compliant and favours built-in Emacs functionality and the former offers richer UI elements and automatic installation for some of the servers.
+
+In either case, you'll also need an associated major mode.
+
+Pick either of the below, the former is likely to be more stable but the latter will allow you to take advantage of tree-sitter and other packages that integrate with it.
+
+The `use-package` statements below assume you're using a package manager like Straight or Elpaca and as such should be taken as references rather than guaranteed copy/pasteable. If you're using `package.el` or another package manager then you'll have to look into instructions for that yourself.
+
```elisp
;; Enable odin-mode and configure OLS as the language server
-(use-package! odin-mode
- :mode ("\\.odin\\'" . odin-mode)
- :hook (odin-mode . lsp))
+(use-package odin-mode
+ :ensure (:host github :repo "mattt-b/odin-mode")
+ :mode ("\\.odin\\'" . odin-mode))
+
+;; Or use the WIP tree-sitter mode
+(use-package odin-ts-mode
+ :ensure (:host github :repo "Sampie159/odin-ts-mode")
+ :mode ("\\.odin\\'" . odin-ts-mode))
+```
+
+And then choose either the built-in `eglot` or `lsp-mode` packages below. Both should work very similarly.
+
+#### lsp-mode
+
+```elisp
+;; Pull the lsp-mode package
+(use-package lsp-mode
+ :commands (lsp lsp-deferred))
;; Set up OLS as the language server for Odin, ensuring lsp-mode is loaded first
(with-eval-after-load 'lsp-mode
(setq-default lsp-auto-guess-root t) ;; Helps find the ols.json file with Projectile or project.el
- (setq lsp-language-id-configuration (cons '(odin-mode . "odin") lsp-language-id-configuration))
+ (add-to-list 'lsp-language-id-configuration '(odin-mode . "odin"))
+ (add-to-list 'lsp-language-id-configuration '(odin-ts-mode . "odin"))
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection "/path/to/ols/executable") ;; Adjust the path here
- :major-modes '(odin-mode)
+ :major-modes '(odin-mode odin-ts-mode)
:server-id 'ols
:multi-root t))) ;; Ensures lsp-mode sends "workspaceFolders" to the server
-(add-hook 'odin-mode-hook #'lsp)
+;; Add a hook to autostart OLS
+(add-hook 'odin-mode-hook #'lsp-deferred)
+(add-hook 'odin-ts-mode-hook #'lsp-deferred) ;; If you're using the TS mode
+```
+
+#### eglot
+
+```elisp
+;; Add OLS to the list of available programs
+;; NOTE: As of Emacs 30, this is not needed.
+(with-eval-after-load 'eglot
+ (add-to-list 'eglot-server-programs '((odin-mode odin-ts-mode) . ("ols"))))
+
+;; Add a hook to autostart OLS
+(add-hook 'odin-mode-hook #'eglot-ensure)
+(add-hook 'odin-ts-mode-hook #'eglot-ensure) ;; If you're using the TS mode
```
### Helix
diff --git a/build.sh b/build.sh
index f887e8d..7b83cf3 100755
--- a/build.sh
+++ b/build.sh
@@ -46,5 +46,8 @@ then
exit 0
fi
+version="$(git describe --tags --abbrev=7)"
+version="${version%-*}:${version##*-}"
+sed "s|VERSION :: .*|VERSION :: \"${version}\"|g" src/main.odin > /tmp/main.odin.build && mv -f /tmp/main.odin.build src/main.odin
odin build src/ -show-timings -collection:src=src -out:ols -microarch:native -no-bounds-check -o:speed $@
diff --git a/editors/vscode/package.json b/editors/vscode/package.json
index 82bdbc7..f431984 100644
--- a/editors/vscode/package.json
+++ b/editors/vscode/package.json
@@ -14,9 +14,6 @@
"categories": [
"Programming Languages"
],
- "activationEvents": [
- "onLanguage:odin"
- ],
"icon": "images/emblem.png",
"main": "./out/extension.js",
"contributes": {
@@ -37,8 +34,13 @@
"category": "Odin Language Server"
},
{
- "command": "ols.createOls",
- "title": "Create ols.json file in project",
+ "command": "ols.editProjectConfig",
+ "title": "Edit per-project config file (ols.json), creating it if necessary",
+ "category": "Odin Language Server"
+ },
+ {
+ "command": "ols.editUserConfig",
+ "title": "Edit per-user config file (ols.json), creating it if necessary",
"category": "Odin Language Server"
}
],
diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts
index e3a8f4f..ae776f8 100644
--- a/editors/vscode/src/extension.ts
+++ b/editors/vscode/src/extension.ts
@@ -5,7 +5,7 @@
import * as vscode from 'vscode';
import * as path from "path";
import * as os from "os";
-import { promises as fs, PathLike, constants, writeFileSync } from "fs";
+import { promises as fs, constants, writeFileSync} from "fs";
var AdmZip = require('adm-zip');
@@ -20,13 +20,24 @@ import { RunnableCodeLensProvider } from "./run";
import { PersistentState } from './persistent_state';
import { Config } from './config';
import { fetchRelease, download } from './net';
-import { getPathForExecutable, isOdinInstalled } from './toolchain';
+import { isOdinInstalled } from './toolchain';
import { Ctx } from './ctx';
import { runDebugTest, runTest } from './commands';
import { watchOlsConfigFile } from './watch';
const onDidChange: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
+const defaultConfig = JSON.stringify(
+ {
+ $schema: "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
+ enable_document_symbols: true,
+ enable_hover: true,
+ enable_snippets: true
+ },
+ null,
+ 4,
+);
+
let ctx: Ctx;
export async function activate(context: vscode.ExtensionContext) {
@@ -102,32 +113,40 @@ export async function activate(context: vscode.ExtensionContext) {
ctx.registerCommand("runDebugTest", runDebugTest);
ctx.registerCommand("runTest", runTest);
- const olsFile = path.join(workspaceFolder.uri.fsPath, "ols.json");
-
- fs.access(olsFile, constants.F_OK).catch(async err => {
- if (err) {
+ const projectConfigPath = path.join(workspaceFolder.uri.fsPath, "ols.json");
+ const userConfigPath = path.join(path.dirname(serverPath), "ols.json");
+ fs.access(projectConfigPath, constants.F_OK).catch(async (_e1) => {
+ fs.access(userConfigPath, constants.F_OK).catch( async (_e2) => {
if (!config.askCreateOLS) {
return;
}
const userResponse = await vscode.window.showInformationMessage(
- "No ols config file in the workspace root folder. Do you wish to create one?",
+ "No ols config file found. Do you wish to create one?",
"Yes",
"No",
- "Don't ask again"
+ "Don't ask again",
);
if (userResponse === "Yes") {
- createOlsConfig(ctx);
+ const clarification = await vscode.window.showInformationMessage(
+ "should it be specific to this project or to all your odin projects?",
+ "This project",
+ "All projects",
+ );
+ if (clarification == "This project") {
+ createOrEditProjectConfig();
+ parseOlsFile(config, projectConfigPath);
+ } else {
+ createOrEditUserConfig(serverPath);
+ parseOlsFile(config, userConfigPath);
+ }
} else if (userResponse === "Don't ask again") {
config.updateAskCreateOLS(false);
return;
}
-
- }
-
- parseOlsFile(config, olsFile);
+ })
});
if(!isOdinInstalled()) {
@@ -147,14 +166,18 @@ export async function activate(context: vscode.ExtensionContext) {
client.start();
});
- vscode.commands.registerCommand("ols.createOls", async() => {
- createOlsConfig(ctx);
+ vscode.commands.registerCommand("ols.editProjectConfig", async() => {
+ createOrEditProjectConfig();
+ });
+
+ vscode.commands.registerCommand("ols.editUserConfig", async () => {
+ createOrEditUserConfig(serverPath);
});
client.start();
- parseOlsFile(config, olsFile);
- watchOlsConfigFile(ctx, olsFile);
+ parseOlsFile(config, projectConfigPath);
+ watchOlsConfigFile(ctx, projectConfigPath);
}
async function bootstrap(config: Config, state: PersistentState): Promise<string> {
@@ -219,35 +242,45 @@ async function removeOldServers(config: Config, state: PersistentState): Promise
}
}
-export function createOlsConfig(ctx: Ctx) {
- const odinPath = getPathForExecutable("odin");
-
- const corePath = path.resolve(path.join(path.dirname(odinPath), "core"));
-
- const config = {
- $schema: "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json",
- enable_document_symbols: true,
- enable_hover: true,
- enable_snippets: true
- };
-
- const olsPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
+export function createOrEditProjectConfig() {
+ const projectConfigPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
+ openFileAndCreateIfNotExists("ols.json", projectConfigPath, defaultConfig);
+}
- const edit = new vscode.WorkspaceEdit();
+export function createOrEditUserConfig(serverPath: string) {
+ const userConfigPath = path.dirname(serverPath);
+ openFileAndCreateIfNotExists("ols.json", userConfigPath, defaultConfig);
+}
- const content = JSON.stringify(config, null, 4);
+function openFileAndCreateIfNotExists(file: string, folder: string, defaultContents: string) {
+ const filePath = path.join(folder, file);
+ console.log(filePath);
- writeFileSync(path.join(olsPath, "ols.json"), content);
+ vscode.workspace.openTextDocument(filePath).then(
+ (document) => { vscode.window.showTextDocument(document) },
+ () => {
+ writeFileSync(filePath, defaultContents);
+ vscode.workspace.openTextDocument(filePath).then(
+ (document) => { vscode.window.showTextDocument(document) }
+ );
+ }
+ );
+
}
export async function parseOlsFile(config: Config, file: string) {
/*
We have to parse the collections that they have specificed through the json(This will be changed when odin gets it's own builder files)
*/
- fs.readFile(file).then((data) => {
- const conf = JSON.parse(data.toString());
- config.collections = conf.collections;
- });
+ fs.readFile(file).then(
+ (data) => {
+ const conf = JSON.parse(data.toString());
+ config.collections = conf.collections;
+ },
+ (error) => {
+ console.info("no ols.json found in workspace");
+ },
+ );
}
function serverPath(config: Config): string | null {
diff --git a/editors/vscode/src/toolchain.ts b/editors/vscode/src/toolchain.ts
index 21957ed..3a559de 100644
--- a/editors/vscode/src/toolchain.ts
+++ b/editors/vscode/src/toolchain.ts
@@ -45,7 +45,7 @@ function lookupInPath(exec: string): string | undefined {
return pathToOdin;
}
} catch (realpathError) {
- console.error("realpathError:", realpathError)
+ console.debug("couldn't find odin at", candidates[i], "on account of", realpathError)
}
}
diff --git a/misc/ols.schema.json b/misc/ols.schema.json
index 8093dc9..1ce278c 100644
--- a/misc/ols.schema.json
+++ b/misc/ols.schema.json
@@ -106,7 +106,7 @@
},
"exclude_path": {
"type": "array",
- "description": "List of paths that will be exldued from workspace symbol searches.",
+ "description": "List of paths that will be excluded from workspace symbol searches.",
"items": {
"type": "string"
}
diff --git a/src/common/ast.odin b/src/common/ast.odin
index 4a576d7..b9033b0 100644
--- a/src/common/ast.odin
+++ b/src/common/ast.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package common
import "core:fmt"
diff --git a/src/main.odin b/src/main.odin
index 6e91583..26cf701 100644
--- a/src/main.odin
+++ b/src/main.odin
@@ -19,6 +19,7 @@ import "core:sys/windows"
import "src:common"
import "src:server"
+VERSION :: "dev-2024-11-9:g584f01b"
os_read :: proc(handle: rawptr, data: []byte) -> (int, int) {
ptr := cast(^os.Handle)handle
@@ -101,6 +102,10 @@ end :: proc() {
}
main :: proc() {
+ if len(os.args) > 1 && os.args[1] == "version" {
+ fmt.println("ols version", VERSION)
+ os.exit(0)
+ }
reader := server.make_reader(os_read, cast(rawptr)&os.stdin)
writer := server.make_writer(os_write, cast(rawptr)&os.stdout)
diff --git a/src/server/build.odin b/src/server/build.odin
index e3478ae..a681201 100644
--- a/src/server/build.odin
+++ b/src/server/build.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package server
import "base:runtime"
diff --git a/src/server/completion.odin b/src/server/completion.odin
index 75d0d64..130cc1a 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package server
import "core:fmt"
diff --git a/src/server/hover.odin b/src/server/hover.odin
index ad9a9c6..2edc331 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package server
import "core:fmt"
diff --git a/src/server/requests.odin b/src/server/requests.odin
index d9581ee..f884b0d 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package server
import "base:intrinsics"
diff --git a/src/server/snippets.odin b/src/server/snippets.odin
index 1ab01a1..3dbbc29 100644
--- a/src/server/snippets.odin
+++ b/src/server/snippets.odin
@@ -1,3 +1,4 @@
+#+feature dynamic-literals
package server
Snippet_Info :: struct {