Skip to content
Merged
514 changes: 514 additions & 0 deletions app/LSP.hs

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions emacs-telomare-mode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Telomare Mode for Emacs

LSP-enabled major mode for the Telomare programming language, with support for Doom Emacs, Spacemacs, and vanilla Emacs.

## Features

Based on the Telomare LSP server capabilities:
- **Syntax highlighting** via semantic tokens (keywords, comments, strings, numbers, operators)
- **Hover information** showing expression evaluation and parse errors
- **Go to definition** and **Find references** (via LSP)
- **Rename symbol** support
- **Parse error reporting** displayed on hover
- **Comment support** (`-- comments`)

## Installation

### Prerequisites

Ensure your Telomare LSP server is available at the configured path (default: `/home/hhefesto/src/telomare#lsp`).

### Modular Configuration (4 files)

Place all four files in a directory in your load-path. All variants require `telomare-mode-common.el`.

#### Doom Emacs

1. Place all files in `~/.doom.d/lisp/`
2. Add to your `config.el`:
```elisp
(load! "lisp/telomare-mode-doom")
```
3. Run `doom sync`

#### Spacemacs

1. Place all files in `~/.spacemacs.d/lisp/`
2. Add to `dotspacemacs/user-config`:
```elisp
(add-to-list 'load-path "~/.spacemacs.d/lisp/")
(require 'telomare-mode-spacemacs)
```
3. Ensure the `lsp` layer is enabled in `dotspacemacs-configuration-layers`

#### Vanilla Emacs

1. Place all files in `~/.emacs.d/lisp/`
2. Add to your `init.el`:
```elisp
(add-to-list 'load-path "~/.emacs.d/lisp/")
(require 'telomare-mode-vanilla)
```
3. Install lsp-mode if not present:
```elisp
(package-install 'lsp-mode)
```

## Configuration

### Customizing the LSP Command

```elisp
;; Use a different nix path
(setq telomare-lsp-command '("nix" "run" "/path/to/your/telomare#lsp" "--"))

;; Use a local binary
(setq telomare-lsp-command '("/usr/local/bin/telomare-lsp"))
```

## Key Bindings

### Doom Emacs
- `SPC m g` - Go to definition TODO: improve
- `SPC m G` - Find references
- TODO: `SPC m h` - Describe at point (hover)
- TODO: `SPC m r` - Rename symbol

### Spacemacs
- `SPC m g` - Go to definition TODO: improve
- `SPC m G` - Find references
- TODO: `SPC m h` - Describe at point (hover)
- TODO: `SPC m r` - Rename symbol

### Vanilla Emacs
- `M-.` - Go to definition
- `M-?` - Find references
- TODO: `C-c h` - Describe at point (hover)
- TODO: `C-c r` - Rename symbol

## Troubleshooting

1. **LSP not starting**: Test your LSP command in terminal:
```bash
nix run /home/hhefesto/src/telomare#lsp --
```

2. **Check LSP status**: With a `.tel` file open, run:
- `M-x lsp-describe-session`

3. **View LSP logs**: Check the `*lsp-log*` buffer for errors

## File Structure

- `telomare-mode-common.el` - Core mode definition and LSP client registration
- `telomare-mode-doom.el` - Doom Emacs specific keybindings and setup
- `telomare-mode-spacemacs.el` - Spacemacs specific keybindings and setup
- `telomare-mode-vanilla.el` - Vanilla Emacs minimal configuration
50 changes: 50 additions & 0 deletions emacs-telomare-mode/telomare-mode-common.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
;;; telomare-mode-common.el --- Common Telomare mode functionality -*- lexical-binding: t; -*-

;; Author: Your Name
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.1"))
;; Keywords: languages, telomare, lsp

;;; Commentary:

;; Common functionality for Telomare mode shared across all Emacs variants.
;; The LSP server provides semantic tokens, hover, and text synchronization.

;;; Code:

(defgroup telomare nil
"Support for the Telomare language."
:group 'languages)

(defcustom telomare-lsp-command
'("nix" "run" "/home/hhefesto/src/telomare#lsp" "--")
"Command to start the Telomare LSP server."
:type '(repeat string)
:group 'telomare)

;; Define the major mode
;;;###autoload
(define-derived-mode telomare-mode prog-mode "Telomare"
"Major mode for editing Telomare files."
(setq-local comment-start "-- ")
(setq-local comment-end "")
(setq-local comment-start-skip "--+\\s-*"))

;; File association
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.tel\\'" . telomare-mode))

;; Common LSP setup function
(defun telomare-register-lsp-client ()
"Register the Telomare LSP client."
(when (fboundp 'lsp-register-client)
(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection
(lambda () telomare-lsp-command))
:activation-fn (lsp-activate-on "telomare")
:major-modes '(telomare-mode)
:server-id 'telomare-lsp))))

(provide 'telomare-mode-common)
;;; telomare-mode-common.el ends here
32 changes: 32 additions & 0 deletions emacs-telomare-mode/telomare-mode-doom.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
;; ;; telomare lsp:

;; Define Telomare mode
(define-derived-mode telomare-mode prog-mode "Telomare"
"Major mode for editing Telomare files."
(setq-local comment-start "-- ")
(setq-local comment-end ""))

;; Associate .tel files with telomare-mode
(add-to-list 'auto-mode-alist '("\\.tel\\'" . telomare-mode))

;; Configure LSP for Telomare using nix run
(with-eval-after-load 'lsp-mode
;; (add-to-list 'lsp-language-id-configuration '(telomare-mode . "telomare"))

;; Enable semantic tokens
(setq lsp-semantic-tokens-enable t)

(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection
(lambda ()
(list "nix" "run" "/home/hhefesto/src/telomare#lsp" "--")))
:activation-fn (lsp-activate-on "telomare")
:major-modes '(telomare-mode)
:server-id 'telomare-lsp
))
)

;; Auto-start LSP in telomare-mode
;; (add-hook 'telomare-mode-hook #'lsp-deferred) ;; lazier/non-blocking
(add-hook 'telomare-mode-hook #'lsp)
60 changes: 60 additions & 0 deletions emacs-telomare-mode/telomare-mode-spacemacs.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
;;; telomare-mode-spacemacs.el --- Telomare major-mode + LSP for Spacemacs -*- lexical-binding: t; -*-

(defgroup telomare nil
"Support for the Telomare language."
:group 'languages)

(defcustom telomare-project-root
(or (getenv "TELOMARE_ROOT")
;; If this file lives inside the repo, try to auto-detect the flake root:
(let* ((this (or load-file-name (buffer-file-name)))
(dir (and this (file-name-directory this)))
(root (and dir (locate-dominating-file dir "flake.nix"))))
(when root (expand-file-name root))))
"Path to the Telomare flake directory (the folder containing flake.nix).

Users should set this to something like \"~/src/telomare\".
You can also set TELOMARE_ROOT in your environment."
:type '(choice (const :tag "Auto-detect / unset" nil)
(directory :tag "Telomare flake directory"))
:group 'telomare)

(defcustom telomare-lsp-flake-attr "lsp"
"Flake app/package attribute to run for the Telomare language server."
:type 'string
:group 'telomare)

(defun telomare--lsp-command ()
"Return the command list used to start the Telomare LSP server."
(unless (and telomare-project-root
(file-exists-p (expand-file-name "flake.nix" telomare-project-root)))
(user-error "telomare-project-root is not set (or has no flake.nix). Set it to your Telomare repo path"))
(let* ((root (file-truename (expand-file-name telomare-project-root)))
(flake (format "%s#%s" root telomare-lsp-flake-attr)))
(list "nix" "run" flake "--")))

;; Define Telomare mode
(define-derived-mode telomare-mode prog-mode "Telomare"
"Major mode for editing Telomare files."
(setq-local comment-start "-- ")
(setq-local comment-end ""))

;; Associate .tel files with telomare-mode
(add-to-list 'auto-mode-alist '("\\.tel\\'" . telomare-mode))

;; Configure LSP for Telomare
(with-eval-after-load 'lsp-mode
(setq lsp-semantic-tokens-enable t)
(add-to-list 'lsp-language-id-configuration '(telomare-mode . "telomare"))
(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection #'telomare--lsp-command)
:activation-fn (lsp-activate-on "telomare")
:major-modes '(telomare-mode)
:server-id 'telomare-lsp)))

;; Auto-start LSP in telomare-mode
(add-hook 'telomare-mode-hook #'lsp)

(provide 'telomare-mode-spacemacs)
;;; telomare-mode-spacemacs.el ends here
40 changes: 40 additions & 0 deletions emacs-telomare-mode/telomare-mode-vanilla.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
;;; telomare-mode-vanilla.el --- Telomare mode configuration for vanilla Emacs -*- lexical-binding: t; -*-

;; Author: Your Name
;; Version: 0.1.0
;; Package-Requires: ((emacs "26.1") (lsp-mode "8.0.0"))

;;; Commentary:

;; Vanilla Emacs specific configuration for Telomare mode.
;; Add (require 'telomare-mode-vanilla) to your init.el

;;; Code:

;; Load common functionality
(require 'telomare-mode-common)

;; Ensure lsp-mode is available
(require 'lsp-mode)

;; Vanilla Emacs specific setup
(defun telomare-vanilla-setup ()
"Set up Telomare mode for vanilla Emacs."
;; Register LSP client
(telomare-register-lsp-client)

;; Add LSP hook
(add-hook 'telomare-mode-hook #'lsp-deferred 'append)

;; Set up minimal keybindings
(define-key telomare-mode-map (kbd "M-.") #'lsp-find-definition)
(define-key telomare-mode-map (kbd "M-?") #'lsp-find-references)
(define-key telomare-mode-map (kbd "C-c h") #'lsp-describe-thing-at-point)
(define-key telomare-mode-map (kbd "C-c r") #'lsp-rename)
(define-key telomare-mode-map (kbd "C-c a") #'lsp-execute-code-action))

;; Initialize
(telomare-vanilla-setup)

(provide 'telomare-mode-vanilla)
;;; telomare-mode-vanilla.el ends here
9 changes: 7 additions & 2 deletions examples.tel
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
-- File for small illustrative telomare programs and for testing

-- Hello World example.
main = \input -> ("Hello, World!", 0)
aux = "Hello"
-- main = \input -> (aux, 0)
main = \input -> ("Hello", 0)

-- -- refinement fail
-- main : (\x -> if x then "fail" else 0) = 1
Expand All @@ -16,10 +18,13 @@ main = \input -> ("Hello, World!", 0)
-- else abort "Not a MyInt"
-- )
-- in wrapper (# wrapper)

-- aux = \x -> if dEqual x 8 then "Success" else "Failure"
-- main = \i -> (aux ((left MyInt) 8), 0)

-- Case example
-- aux2 = [1,2,3]

-- something
-- main =
-- let toCase = (("a string", 99),(8,"pattern-match"))
-- caseTest =
Expand Down
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
type = "app";
program = self.packages.${system}.telomare + "/bin/telomare-evaluare";
};
apps.lsp = {
type = "app";
program = "${self.packages.${system}.telomare}/bin/telomare-lsp";
};

checks = self'.packages;
};
Expand Down
Loading
Loading