Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/telomare-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
extraPullNames: nix-community
- name: hlint linting
run: |
output=$(nix develop -c hlint "--ignore=Parse error" app/Evaluare.hs . --no-exit-code)
output=$(nix develop -c hlint . --no-exit-code)
if [ "$output" = "No hints" ]; then
echo "Success! No Hlint suggestions."
else
Expand Down
57 changes: 16 additions & 41 deletions Prelude.tel
Original file line number Diff line number Diff line change
Expand Up @@ -143,44 +143,19 @@ gcd = \a b ->
lcm = \a b -> dDiv (dTimes a b) (gcd a b)

[Rational, fromRational, toRational, rPlus, rTimes, rMinus, rDiv] = \h ->
[ \n d -> if dEqual d 0
then abort "Denominator cannot be zero"
else
let g = gcd n d
num = dDiv n g
den = dDiv d g
in (h, (num, den))
, \i -> Rational i
, \a b ->
let n1 = left (right a)
d1 = right (right a)
n2 = left (right b)
d2 = right (right b)
num = dPlus (dTimes n1 d2) (dTimes n2 d1)
den = dTimes d1 d2
in fromRational num den
, \a b ->
let n1 = left (right a)
d1 = right (right a)
n2 = left (right b)
d2 = right (right b)
num = dTimes n1 n2
den = dTimes d1 d2
in fromRational num den
, \a b ->
let n1 = left (right a)
d1 = right (right a)
n2 = left (right b)
d2 = right (right b)
num = dMinus (dTimes n1 d2) (dTimes n2 d1)
den = dTimes d1 d2
in fromRational num den
, \a b ->
let n1 = left (right a)
d1 = right (right a)
n2 = left (right b)
d2 = right (right b)
num = dTimes n1 d2
den = dTimes d1 n2
in fromRational num den
]
let rNum = \x -> left (right x)
rDen = \x -> right (right x)
in [ \n d -> if dEqual d 0
then abort "Denominator cannot be zero"
else let g = gcd n d
in (h, (dDiv n g, dDiv d g))
, Rational
, \a b -> fromRational (dPlus (dTimes (rNum a) (rDen b)) (dTimes (rNum b) (rDen a)))
(dTimes (rDen a) (rDen b))
, \a b -> fromRational (dTimes (rNum a) (rNum b))
(dTimes (rDen a) (rDen b))
, \a b -> fromRational (dMinus (dTimes (rNum a) (rDen b)) (dTimes (rNum b) (rDen a)))
(dTimes (rDen a) (rDen b))
, \a b -> fromRational (dTimes (rNum a) (rDen b))
(dTimes (rDen a) (rNum b))
]
131 changes: 130 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,136 @@ This project is in active development. Do expect bugs and general trouble, and p
$ cabal run telomare-repl -- --haskell # or nix run .#repl
```
2. Profit!


## Editor Support (LSP)

Telomare ships a language server (`telomare-lsp`) and an Emacs major mode
under [`emacs-telomare-mode/`](emacs-telomare-mode/), with variants for
Spacemacs, Doom, and vanilla Emacs.

### LSP capabilities

The language server provides:

- **Diagnostics** — on every document open and edit it reports parse
errors, missing imported modules, undefined variable references, and
resolver errors. Diagnostics are cleared when the document is closed.
- **Go to definition** — jumps to local `let`, lambda, and case-pattern
binders, to top-level definitions, and to definitions in qualified
imported modules.
- **Find references** — lists every reference to a symbol, optionally
including its declaration.
- **Semantic-token highlighting** — keywords, comments, strings,
numbers, and operators, for the whole file or a requested range.
- **Code action** — *Partially evaluate*: select an expression and the
server evaluates it, reporting the result in an editor popup.
- **Workspace commands**:
- `telomare.version` — reports the server version as a UTC timestamp.
- `telomare.partialEval` — evaluates a given expression; this backs
the partial-evaluation code action.

Document sync is full-text (whole-document). Hover and rename are not
implemented yet.

### Installing the Emacs mode

The recommended Spacemacs setup is to load Telomare's Emacs mode from the
same Telomare flake input that provides the language server. Do not point
Spacemacs at a random checkout unless you are actively developing the mode;
make the editor use the same pinned source that NixOS or Home Manager builds.

For a NixOS/Home Manager Spacemacs config, add Telomare as a flake input and
load the mode file from that input:

```elisp
(load "${telomare}/emacs-telomare-mode/telomare-mode-spacemacs.el")
```

The mode auto-detects the surrounding flake source path and starts the LSP with
`nix run path:<telomare-source>#lsp --`. This matters for Nix store paths:
`nix run /nix/store/...-source#lsp --` is parsed incorrectly by Nix, while
`nix run path:/nix/store/...-source#lsp --` is the intended absolute-path flake
form.

For a manual checkout-based setup, load the mode from this repository and set
`TELOMARE_ROOT` only if auto-detection cannot find `flake.nix`:

```elisp
(load "/path/to/telomare/emacs-telomare-mode/telomare-mode-spacemacs.el")
```

For Doom and vanilla Emacs setup, see
[`emacs-telomare-mode/README.md`](emacs-telomare-mode/README.md).

### Keybindings

The mode binds only features the server implements. Some entries below
come from `lsp-mode` rather than Telomare's mode — these are marked
*(lsp-mode)*. Spacemacs exposes the major-mode leader as `SPC m` in Evil
state and as `M-m m` in holy-mode; the leader entries are otherwise the
same bindings.

**Spacemacs — Evil mode** (`SPC m` major-mode leader):

| Key | Action |
|-----|--------|
| `SPC m g` | Go to definition |
| `SPC m G` | Find references |
| `SPC m a` | Execute code action (partial evaluation) |
| `SPC m v` | Show Telomare LSP version |
| `C-c C-v` | Show Telomare LSP version |
| `g d` | Go to definition *(lsp-mode / Evil default)* |

**Spacemacs — holy mode** (`M-m m` major-mode leader):

| Key | Action |
|-----|--------|
| `M-m m g` | Go to definition |
| `M-m m G` | Find references |
| `M-m m a` | Execute code action (partial evaluation) |
| `M-m m v` | Show Telomare LSP version |
| `C-c C-v` | Show Telomare LSP version |
| `M-.` | Go to definition *(lsp-mode)* |
| `M-?` | Find references *(lsp-mode)* |
| `M-,` | Jump back *(xref)* |

Vanilla Emacs binds `M-.`, `M-?`, `C-c a`, and `C-c C-v`.

### Troubleshooting

If navigation does not work, check the active LSP session with
`M-x lsp-describe-session`, restart it with `M-x lsp-workspace-restart`, and
confirm the server command with:

```elisp
M-: (telomare--lsp-command)
```

The expected command shape is:

```elisp
("nix" "run" "path:/nix/store/...-source#lsp" "--")
```

### LSP version command

`C-c C-v` (or `SPC m v` / `M-m m v` in Spacemacs) reports the server
version as a UTC timestamp truncated to minutes, using the parent commit
timestamp when git history is available and the flake source timestamp
when launched from a Nix store source without `.git`. It can also be
invoked directly:

```elisp
(lsp-request "workspace/executeCommand"
`(:command "telomare.version" :arguments []))
```

The command shows an editor message such as:

```text
Telomare LSP version: 2026-05-22T10:14Z
```

## Git Hooks

You can setup your git configuration to automatically format and look for lint suggestions. Just run:
Expand Down
Loading
Loading