@@ -3,41 +3,108 @@ package app
8 "github.com/charmbracelet/crush/internal/config"
10 "github.com/charmbracelet/crush/internal/config"
9 "github.com/charmbracelet/crush/internal/lsp"
11 "github.com/charmbracelet/crush/internal/lsp"
12+ powernapconfig "github.com/charmbracelet/x/powernap/pkg/config"
12// initLSPClients initializes LSP clients.
15// initLSPClients initializes LSP clients.
13func (app *App) initLSPClients(ctx context.Context) {
16func (app *App) initLSPClients(ctx context.Context) {
17+ slog.Info("LSP clients initialization started")
19+ manager := powernapconfig.NewManager()
20+ manager.LoadDefaults()
22+ var userConfiguredLSPs []string
14 for name, clientConfig := range app.config.LSP {
23 for name, clientConfig := range app.config.LSP {
15 if clientConfig.Disabled {
24 if clientConfig.Disabled {
16 slog.Info("Skipping disabled LSP client", "name", name)
25 slog.Info("Skipping disabled LSP client", "name", name)
26+ manager.RemoveServer(name)
30+ // HACK: the user might have the command name in their config, instead
31+ // of the actual name. This finds out these cases, and adjusts the name
33+ if _, ok := manager.GetServer(name); !ok {
34+ for sname, server := range manager.GetServers() {
35+ if server.Command == name {
41+ userConfiguredLSPs = append(userConfiguredLSPs, name)
42+ manager.AddServer(name, &powernapconfig.ServerConfig{
43+ Command: clientConfig.Command,
44+ Args: clientConfig.Args,
45+ Environment: clientConfig.Env,
46+ FileTypes: clientConfig.FileTypes,
47+ RootMarkers: clientConfig.RootMarkers,
48+ InitOptions: clientConfig.InitOptions,
49+ Settings: clientConfig.Options,
53+ servers := manager.GetServers()
54+ filtered := lsp.FilterMatching(app.config.WorkingDir(), servers)
56+ for _, name := range userConfiguredLSPs {
57+ if _, ok := filtered[name]; !ok {
58+ updateLSPState(name, lsp.StateDisabled, nil, nil, 0)
61+ for name, server := range filtered {
62+ if app.config.Options.AutoLSP != nil && !*app.config.Options.AutoLSP && !slices.Contains(userConfiguredLSPs, name) {
63+ slog.Debug("Ignoring non user-define LSP client due to AutoLSP being disabled", "name", name)
19− go app.createAndStartLSPClient(ctx, name, clientConfig)
66+ go app.createAndStartLSPClient(
69+ slices.Contains(userConfiguredLSPs, name),
21− slog.Info("LSP clients initialization started in background")
24−// createAndStartLSPClient creates a new LSP client, initializes it, and starts its workspace watcher
74+func toOurConfig(in *powernapconfig.ServerConfig) config.LSPConfig {
25−func (app *App) createAndStartLSPClient(ctx context.Context, name string, config config.LSPConfig) {
75+ return config.LSPConfig{
26− slog.Debug("Creating LSP client", "name", name, "command", config.Command, "fileTypes", config.FileTypes, "args", config.Args)
76+ Command: in.Command,
79+ FileTypes: in.FileTypes,
80+ RootMarkers: in.RootMarkers,
81+ InitOptions: in.InitOptions,
82+ Options: in.Settings,
28− // Check if any root markers exist in the working directory (config now has defaults)
86+// createAndStartLSPClient creates a new LSP client, initializes it, and starts its workspace watcher.
29− if !lsp.HasRootMarkers(app.config.WorkingDir(), config.RootMarkers) {
87+func (app *App) createAndStartLSPClient(ctx context.Context, name string, config config.LSPConfig, userConfigured bool) {
30− slog.Debug("Skipping LSP client: no root markers found", "name", name, "rootMarkers", config.RootMarkers)
88+ if !userConfigured {
31− updateLSPState(name, lsp.StateDisabled, nil, nil, 0)
89+ if _, err := exec.LookPath(config.Command); err != nil {
90+ slog.Warn("Default LSP config skipped: server not installed", "name", name, "error", err)
95+ slog.Debug("Creating LSP client", "name", name, "command", config.Command, "fileTypes", config.FileTypes, "args", config.Args)
35− // Update state to starting
97+ // Update state to starting.
36 updateLSPState(name, lsp.StateStarting, nil, nil, 0)
98 updateLSPState(name, lsp.StateStarting, nil, nil, 0)
38 // Create LSP client.
100 // Create LSP client.
39 lspClient, err := lsp.New(ctx, name, config, app.config.Resolver())
101 lspClient, err := lsp.New(ctx, name, config, app.config.Resolver())
40 if err != nil {
102 if err != nil {
103+ if !userConfigured {
104+ slog.Warn("Default LSP config skipped due to error", "name", name, "error", err)
105+ updateLSPState(name, lsp.StateDisabled, nil, nil, 0)
41 slog.Error("Failed to create LSP client for", "name", name, "error", err)
108 slog.Error("Failed to create LSP client for", "name", name, "error", err)
42 updateLSPState(name, lsp.StateError, err, nil, 0)
109 updateLSPState(name, lsp.StateError, err, nil, 0)