Skip to content

Commit aaf4c46

Browse files
authored
🔀 Merge pull request #133 from sansmoraxz/feat/dynamic-ignore
2 parents 12d6b6e + 093e5be commit aaf4c46

File tree

10 files changed

+230
-37
lines changed

10 files changed

+230
-37
lines changed

README.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,53 @@ vim.api.nvim_create_autocmd({'BufEnter', 'BufWinEnter'}, {
7676
name = "hyprlang",
7777
cmd = {"hyprls"},
7878
root_dir = vim.fn.getcwd(),
79-
}
79+
settings = {
80+
hyprls = {
81+
preferIgnoreFile = true, -- set to false to prefer `hyprls.ignore`
82+
ignore = {"hyprlock.conf", "hypridle.conf"}
83+
}
84+
}
85+
}
8086
end
8187
})
8288
```
8389

90+
You can control whether HyprLS prefers a workspace `.hyprlsignore` file or the editor settings with the `hyprls.preferIgnoreFile` option. Example configurations:
91+
92+
- Using `vim.lsp.start` (example above) — set `settings.hyprls.preferIgnoreFile` to `false` to force the server to use `settings.hyprls.ignore`.
93+
94+
- Using `nvim-lspconfig`:
95+
96+
```lua
97+
local lspconfig = require('lspconfig')
98+
lspconfig.hyprlang.setup{
99+
cmd = {"hyprls"},
100+
settings = {
101+
hyprls = {
102+
preferIgnoreFile = false,
103+
ignore = {"hyprlock.conf", "hypridle.conf"}
104+
}
105+
}
106+
}
107+
```
108+
109+
When `preferIgnoreFile` is `true` (the default), HyprLS will read `.hyprlsignore` from your workspace root. When it's `false`, it will use the `hyprls.ignore` array from your editor configuration instead.
110+
111+
Example `.hyprlsignore` (create this file at the workspace root):
112+
113+
```
114+
# ignore session-specific files
115+
hyprlock.conf
116+
hypridle.conf
117+
# ignore any file named workspace-specific.ignore
118+
workspace-specific.ignore
119+
```
120+
121+
Notes for Neovim users:
122+
123+
- If you set `preferIgnoreFile = true`, HyprLS will use the workspace `.hyprlsignore` file and ignore any `settings.hyprls.ignore` values passed from Neovim.
124+
- If you set `preferIgnoreFile = false`, HyprLS will use the `ignore` list you provide in `settings.hyprls` (see `nvim-lspconfig` example above).
125+
84126
### With Emacs
85127
Language server support is provided by the [lsp-bridge](https://github.com/manateelazycat/lsp-bridge).
86128

go.sum

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
22
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
33
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
4-
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
5-
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
64
github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
75
github.com/PuerkitoBio/goquery v1.11.0/go.mod h1:wQHgxUOU3JGuj3oD/QFfxUdlzW6xPHfqyHre6VMY4DQ=
86
github.com/anaskhan96/soup v1.2.5 h1:V/FHiusdTrPrdF4iA1YkVxsOpdNcgvqT1hG+YtcZ5hM=
@@ -75,8 +73,6 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
7573
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
7674
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
7775
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
78-
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
79-
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
8076
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
8177
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
8278
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -97,8 +93,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9793
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
9894
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
9995
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
100-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
101-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
10296
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
10397
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
10498
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
@@ -119,8 +113,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
119113
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
120114
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
121115
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
122-
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
123-
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
124116
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
125117
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
126118
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

handler.go

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package hyprls
22

33
import (
44
"context"
5+
"fmt"
56
"os"
67
"strings"
78

@@ -26,23 +27,69 @@ func NewHandler(ctx context.Context, server protocol.Server, logger *zap.Logger)
2627

2728
const ignoreFile = ".hyprlsignore"
2829

30+
var preferIgnoreFile = true
31+
32+
func (h *Handler) hasIgnoreFile() bool {
33+
f := ignoreFile
34+
stat, err := os.Stat(f)
35+
if err != nil {
36+
return false // assume failure means no file
37+
}
38+
if stat.IsDir() {
39+
return false
40+
}
41+
42+
return true
43+
}
44+
45+
func (h *Handler) parseIgnoresFile(uri protocol.URI) ([]string, error) {
46+
if !preferIgnoreFile {
47+
return []string{}, fmt.Errorf("preferIgnoreFile is false")
48+
}
49+
f := uri.Filename()
50+
if h.hasIgnoreFile() {
51+
b, err := os.ReadFile(f)
52+
if err != nil {
53+
h.Logger.Error("Failed to read ignore file", zap.String("file", f), zap.Error(err))
54+
return []string{}, err
55+
}
56+
contd := string(b)
57+
ignores := strings.Split(contd, "\n")
58+
// drop all comments and empty lines
59+
var filteredIgnores = make([]string, 0, len(ignores))
60+
for _, ig := range ignores {
61+
ig = strings.TrimSpace(ig)
62+
if ig == "" || strings.HasPrefix(ig, "#") || strings.HasPrefix(ig, "//") {
63+
continue
64+
}
65+
filteredIgnores = append(filteredIgnores, ig)
66+
}
67+
ignores = filteredIgnores
68+
h.Logger.Info("Loaded ignores from file", zap.String("file", f), zap.Strings("ignores", ignores))
69+
return ignores, nil
70+
} else {
71+
h.Logger.Info("Ignore file does not exist", zap.String("file", f))
72+
return []string{}, fmt.Errorf("ignore file does not exist")
73+
}
74+
}
75+
2976
func (h Handler) Initialize(ctx context.Context, params *protocol.InitializeParams) (*protocol.InitializeResult, error) {
3077
logger = h.Logger
3178
workspaceFolders := params.WorkspaceFolders
3279
logger.Info("Loading", zap.Any("workspace", workspaceFolders))
3380

81+
igs := defaultIgnores
82+
3483
for _, workspaceFolder := range workspaceFolders {
35-
f := protocol.URI(workspaceFolder.URI + "/" + ignoreFile).Filename()
36-
if info, err := os.Stat(f); err == nil && !info.IsDir() {
37-
logger.Debug("Loading ignore file" + ignoreFile)
38-
b, err := os.ReadFile(f)
39-
if err == nil {
40-
contd := string(b)
41-
ignores = strings.Split(contd, "\n")
42-
}
84+
f := protocol.URI(workspaceFolder.URI + "/" + ignoreFile)
85+
loadedIgs, err := h.parseIgnoresFile(f)
86+
if err == nil {
87+
igs = loadedIgs
88+
break
4389
}
4490
}
45-
logger.Debug("Ignoring files", zap.Any("ignores", ignores))
91+
Ignores = igs
92+
logger.Info("Ignoring files", zap.Any("ignores", Ignores))
4693

4794
return &protocol.InitializeResult{
4895
Capabilities: protocol.ServerCapabilities{
@@ -57,6 +104,12 @@ func (h Handler) Initialize(ctx context.Context, params *protocol.InitializePara
57104
OpenClose: true,
58105
Change: protocol.TextDocumentSyncKindFull,
59106
},
107+
Workspace: &protocol.ServerCapabilitiesWorkspace{
108+
WorkspaceFolders: &protocol.ServerCapabilitiesWorkspaceFolders{
109+
Supported: true,
110+
ChangeNotifications: true,
111+
},
112+
},
60113
},
61114
ServerInfo: &protocol.ServerInfo{
62115
Name: "hyprls",

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func StartServer(logger *zap.Logger, logClientIn string) {
2828

2929
conn.Go(ctx, protocol.ServerHandler(handler, jsonrpc2.MethodNotFoundHandler))
3030
<-conn.Done()
31+
logger.Info("server stopped")
3132
}
3233

3334
type readWriteCloser struct {

state.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package hyprls
22

33
import (
4-
"context"
54
"os"
65
"path/filepath"
76
"slices"
@@ -16,15 +15,12 @@ import (
1615
var logger *zap.Logger
1716

1817
var openedFiles = make(map[protocol.URI]string)
19-
var ignores = []string{"hyprlock.conf", "hypridle.conf"}
18+
var defaultIgnores = []string{"hyprlock.conf", "hypridle.conf"}
19+
var Ignores = defaultIgnores
2020

2121
type state struct {
2222
}
2323

24-
func (h Handler) state(ctx context.Context) state {
25-
return ctx.Value("state").(state)
26-
}
27-
2824
func parse(uri protocol.URI) (parser.Section, error) {
2925
contents, err := file(uri)
3026
if err != nil {
@@ -105,5 +101,5 @@ func currentLine(uri protocol.URI, position protocol.Position) (string, error) {
105101

106102
func isFileIgnored(uri protocol.URI) bool {
107103
n := filepath.Base(uri.Filename())
108-
return slices.Contains(ignores, n)
104+
return slices.Contains(Ignores, n)
109105
}

unimplemented.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,6 @@ func (h Handler) Declaration(ctx context.Context, params *protocol.DeclarationPa
3939
return nil, errors.New("unimplemented")
4040
}
4141

42-
func (h Handler) DidChangeConfiguration(ctx context.Context, params *protocol.DidChangeConfigurationParams) error {
43-
return errors.New("unimplemented")
44-
}
45-
46-
func (h Handler) DidChangeWatchedFiles(ctx context.Context, params *protocol.DidChangeWatchedFilesParams) error {
47-
return errors.New("unimplemented")
48-
}
49-
5042
func (h Handler) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error {
5143
return errors.New("unimplemented")
5244
}

vscode/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,23 @@
33
## Installation
44

55
Requires [installing `hyprls`](https://github.com/ewen-lbh/hyprls) and having in on your PATH.
6+
7+
## Ignore file preference
8+
9+
By default HyprLS will prefer a `.hyprlsignore` file in your workspace to list filenames or patterns that the language server should ignore. This behavior can be overridden by a configuration option exposed by the VSCode extension.
10+
11+
- **Config key:** `hyprls.preferIgnoreFile` (boolean)
12+
- **Default:** `true` — prefer the `.hyprlsignore` file over the extension setting `hyprls.ignore`.
13+
14+
How to set it in VSCode:
15+
16+
```json
17+
// In your Workspace or User settings (settings.json)
18+
{
19+
"hyprls.preferIgnoreFile": false,
20+
"hyprls.ignore": [
21+
"hyprlock.conf",
22+
"hypridle.conf"
23+
]
24+
}
25+
```

vscode/package.json

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"categories": [],
1313
"keywords": [],
1414
"engines": {
15-
"vscode": "^1.999.0"
15+
"vscode": "^1.106.0"
1616
},
1717
"contributes": {
1818
"languages": [
@@ -35,7 +35,31 @@
3535
"title": "Restart language server",
3636
"command": "vscode-hyprls.restart-lsp"
3737
}
38-
]
38+
],
39+
"configuration": {
40+
"type": "object",
41+
"title": "HyprLS",
42+
"properties": {
43+
"hyprls.ignore": {
44+
"type": [
45+
"array"
46+
],
47+
"items": {
48+
"type": "string"
49+
},
50+
"description": "List of files or patterns to ignore",
51+
"default": [
52+
"hyprlock.conf",
53+
"hypridle.conf"
54+
]
55+
},
56+
"hyprls.preferIgnoreFile": {
57+
"type": "boolean",
58+
"description": "Whether to prefer .hyprignore file over 'hyprls.ignore' setting",
59+
"default": true
60+
}
61+
}
62+
}
3963
},
4064
"activationEvents": [
4165
"onLanguage:hyprlang"

vscode/src/extension.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* ------------------------------------------------------------------------------------------ */
55

66
import { commands, ExtensionContext, workspace } from "vscode"
7+
import * as path from "path"
78

89
import {
910
LanguageClient,
@@ -25,7 +26,10 @@ export function activate(context: ExtensionContext) {
2526
transport: TransportKind.stdio,
2627
},
2728
debug: {
28-
command: "/home/uwun/projects/hyprls/hyprlang-lsp",
29+
command: "./hyprlang-lsp",
30+
options: {
31+
cwd: path.join(context.extensionPath, ".."),
32+
},
2933
transport: TransportKind.stdio,
3034
},
3135
}
@@ -36,7 +40,8 @@ export function activate(context: ExtensionContext) {
3640
documentSelector: [{ scheme: "file", language: "hyprlang" }],
3741
outputChannelName: "HyprLS",
3842
synchronize: {
39-
fileEvents: workspace.createFileSystemWatcher("*.hl"),
43+
fileEvents: workspace.createFileSystemWatcher("**/.hyprlsignore"),
44+
configurationSection: "hyprls",
4045
},
4146
}
4247

0 commit comments

Comments
 (0)