From 98329cc3f9f49c70cb63938625f5581f9cc44a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 May 2024 23:23:19 +0200 Subject: [PATCH] Improve initial experience when using the plugin 1. Uncomment 'cmd' from the config file - since servers are not started by default, this removes one extra step users have to do 2. Add a checkbox to the project properties tab enabling/diabling the plugin instead of using the single combo box for everything. 3. Update documentation with these changes. --- lsp/README | 21 ++++------------ lsp/data/lsp.conf | 10 +++----- lsp/src/lsp-main.c | 58 +++++++++++++++++++++++++++++++-------------- lsp/src/lsp-utils.c | 5 ++-- lsp/src/lsp-utils.h | 10 ++++++-- 5 files changed, 59 insertions(+), 45 deletions(-) diff --git a/lsp/README b/lsp/README index c40497a04..b57f95ff0 100644 --- a/lsp/README +++ b/lsp/README @@ -37,14 +37,15 @@ to use, as some may have specific requirements. Note that many language servers, such as ``clangd``, ``pylsp``, and ``gopls``, are often packaged by Linux distributions, making them easy to install and use. -By default, no language server is started when the plugin is loaded. You can configure servers and other settings using the User configuration file, accessible from:: Tools->LSP Client->User configuration This file provides extensive information about all the settings options, so be -sure to refer to it for more details. +sure to refer to it for more details. The default configuration file comes with +pre-configured values for ``clangd`` (C, C++), ``pylsp`` (Python), and ``gopls`` +(Go). Other servers have to be added manually. By default, the LSP plugin is disabled unless explicitly enabled for a project under @@ -56,17 +57,6 @@ project under This behavior can be controlled by the first three configuration options in the `[all]` section of the configuration file. -To start a language server for a specific file type, create a section named -``[Filetype]`` (where ``Filetype`` is the name of a language as defined in Geany, -such as ``Python``). Within this section, add the configuration option -``cmd=some_command``, where ``some_command`` is the command to start the server -(for example, ``pylsp`` if the server is on your system's ``PATH``, or the full -path to the server). - -The default configuration file comes with pre-configured values for ``clangd`` -(C, C++), ``pylsp`` (Python), and ``gopls`` (Go). To start these servers, simply -uncomment the ``cmd`` configuration option. - Language servers are started lazily, meaning they only launch when you switch a tab to a file with a filetype that has a corresponding LSP server configured. After the initial handshake between the client and server, you can check the @@ -82,15 +72,14 @@ for more details, refer to: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/ In addition to the User configuration file, you can also create a per-project -configuration file or a configuration file shared by multiple projects. This file +configuration file (which can also be shared by multiple projects). This file can be configured under the :: Project->Properties->LSP Client -tab. This tab also provides an option to completely disable LSP for specific -projects. +tab. Furthermore, the plugin offers a range of customizable keybindings, which can be configured from:: diff --git a/lsp/data/lsp.conf b/lsp/data/lsp.conf index 749b0bb49..a99792dbb 100644 --- a/lsp/data/lsp.conf +++ b/lsp/data/lsp.conf @@ -196,9 +196,7 @@ lang_id_mappings=dummylanguage;*.dummy # if your project uses some other build tool (you need to install the bear tool # first). The compile_commands.json file has to be manually regenerated when # the build is modified in any way, such as a file is added/removed. -# -# Uncomment the line below to start using the server -#cmd=clangd +cmd=clangd semantic_tokens_enable=true autocomplete_trigger_sequences=.;::;->;->* #initialization_options={"compilationDatabasePath": "/home/some_user/my_project/my_builddir"} @@ -215,8 +213,7 @@ use=C [Go] -# Uncomment the line below to start using the server -#cmd=gopls +cmd=gopls autocomplete_apply_additional_edits=true lang_id_mappings=go.mod;go.mod;go.sum;go.sum;gotmpl;*tmpl #rpc_log=stdout @@ -225,8 +222,7 @@ lang_id_mappings=go.mod;go.mod;go.sum;go.sum;gotmpl;*tmpl [Python] -# Uncomment the line below to start using the server -#cmd=pylsp +cmd=pylsp use_outside_project_dir=true use_without_project=true #initialization_options_file=/home/some_user/pylsp.json diff --git a/lsp/src/lsp-main.c b/lsp/src/lsp-main.c index 621d972dc..572bdfc07 100644 --- a/lsp/src/lsp-main.c +++ b/lsp/src/lsp-main.c @@ -54,6 +54,7 @@ GeanyPlugin *geany_plugin; GeanyData *geany_data; +LspProjectConfiguration project_configuration; LspProjectConfigurationType project_configuration_type; gchar *project_configuration_file; @@ -157,6 +158,7 @@ struct struct { + GtkWidget *enable_check_button; GtkWidget *settings_type_combo; GtkWidget *config_file_entry; GtkWidget *path_box; @@ -828,7 +830,8 @@ static void on_project_open(G_GNUC_UNUSED GObject *obj, GKeyFile *kf, { gboolean have_project_config; - project_configuration_type = utils_get_setting_integer(kf, "lsp", "settings_type", UnconfiguredConfigurationType); + project_configuration = utils_get_setting_boolean(kf, "lsp", "enabled", UnconfiguredConfiguration); + project_configuration_type = utils_get_setting_integer(kf, "lsp", "settings_type", UserConfigurationType); project_configuration_file = g_key_file_get_string(kf, "lsp", "config_file", NULL); have_project_config = lsp_utils_get_project_config_filename() != NULL; @@ -857,6 +860,7 @@ static void on_project_dialog_confirmed(G_GNUC_UNUSED GObject *obj, GtkWidget *n const gchar *config_file; gboolean have_project_config; + project_configuration = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(project_dialog.enable_check_button)); project_configuration_type = gtk_combo_box_get_active(GTK_COMBO_BOX(project_dialog.settings_type_combo)); config_file = gtk_entry_get_text(GTK_ENTRY(project_dialog.config_file_entry)); SETPTR(project_configuration_file, g_strdup(config_file)); @@ -869,18 +873,19 @@ static void on_project_dialog_confirmed(G_GNUC_UNUSED GObject *obj, GtkWidget *n } -static void update_sensitivity(LspProjectConfigurationType config) +static void update_sensitivity(gboolean checkbox_enabled, LspProjectConfigurationType combo_state) { - if (config == ProjectConfigurationType) - gtk_widget_set_sensitive(project_dialog.path_box, TRUE); - else - gtk_widget_set_sensitive(project_dialog.path_box, FALSE); + gtk_widget_set_sensitive(project_dialog.settings_type_combo, checkbox_enabled); + gtk_widget_set_sensitive(project_dialog.path_box, checkbox_enabled && combo_state == ProjectConfigurationType); } -static void on_combo_changed(void) +static void on_config_changed(void) { - update_sensitivity(gtk_combo_box_get_active(GTK_COMBO_BOX(project_dialog.settings_type_combo))); + LspProjectConfigurationType combo_state = gtk_combo_box_get_active(GTK_COMBO_BOX(project_dialog.settings_type_combo)); + gboolean checkbox_enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(project_dialog.enable_check_button)); + + update_sensitivity(checkbox_enabled, combo_state); } @@ -891,26 +896,43 @@ static void add_project_properties_tab(GtkWidget *notebook) GtkWidget *label; GtkSizeGroup *size_group; gint combo_value; + gboolean project_enabled; + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + + project_dialog.enable_check_button = gtk_check_button_new_with_label(_("Enable LSP client for project")); + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(hbox), project_dialog.enable_check_button, TRUE, TRUE, 12); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 12); table_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12); gtk_box_set_spacing(GTK_BOX(table_box), 6); size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - label = gtk_label_new(_("Configuration:")); + label = gtk_label_new(_("Configuration type:")); gtk_label_set_xalign(GTK_LABEL(label), 0.0); gtk_size_group_add_widget(size_group, label); project_dialog.settings_type_combo = gtk_combo_box_text_new(); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(project_dialog.settings_type_combo), _("Use user configuration")); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(project_dialog.settings_type_combo), _("Use project configuration")); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(project_dialog.settings_type_combo), _("Disable LSP Client for project")); - if (project_configuration_type == UnconfiguredConfigurationType) - combo_value = all_cfg->enable_by_default ? UserConfigurationType : DisableConfigurationType; + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(project_dialog.settings_type_combo), _("Use user configuration file")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(project_dialog.settings_type_combo), _("Use project configuration file")); + + if (project_configuration == UnconfiguredConfiguration) + { + project_enabled = all_cfg->enable_by_default; + combo_value = UserConfigurationType; + } else + { + project_enabled = project_configuration; combo_value = project_configuration_type; + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(project_dialog.enable_check_button), project_enabled); gtk_combo_box_set_active(GTK_COMBO_BOX(project_dialog.settings_type_combo), combo_value); - g_signal_connect(project_dialog.settings_type_combo, "changed", on_combo_changed, NULL); + g_signal_connect(project_dialog.settings_type_combo, "changed", on_config_changed, NULL); + g_signal_connect(project_dialog.enable_check_button, "toggled", on_config_changed, NULL); ebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start(GTK_BOX(ebox), label, FALSE, FALSE, 0); @@ -928,7 +950,7 @@ static void add_project_properties_tab(GtkWidget *notebook) gtk_entry_set_text(GTK_ENTRY(project_dialog.config_file_entry), project_configuration_file ? project_configuration_file : ""); - update_sensitivity(project_configuration_type); + update_sensitivity(project_enabled, combo_value); ebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); gtk_box_pack_start(GTK_BOX(ebox), label, FALSE, FALSE, 0); @@ -937,7 +959,6 @@ static void add_project_properties_tab(GtkWidget *notebook) hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start(GTK_BOX(hbox), table_box, TRUE, TRUE, 12); - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 6); label = gtk_label_new(_("LSP Client")); @@ -969,8 +990,9 @@ static void on_project_dialog_close(G_GNUC_UNUSED GObject * obj, GtkWidget * not static void on_project_save(G_GNUC_UNUSED GObject *obj, GKeyFile *kf, G_GNUC_UNUSED gpointer user_data) { - if (project_configuration_type != UnconfiguredConfigurationType) + if (project_configuration != UnconfiguredConfiguration) { + g_key_file_set_boolean(kf, "lsp", "enabled", project_configuration); g_key_file_set_integer(kf, "lsp", "settings_type", project_configuration_type); g_key_file_set_string(kf, "lsp", "config_file", project_configuration_file ? project_configuration_file : ""); diff --git a/lsp/src/lsp-utils.c b/lsp/src/lsp-utils.c index fd8bf73db..a34b15e3e 100644 --- a/lsp/src/lsp-utils.c +++ b/lsp/src/lsp-utils.c @@ -33,6 +33,7 @@ extern GeanyData *geany_data; +extern LspProjectConfiguration project_configuration; extern LspProjectConfigurationType project_configuration_type; extern gchar *project_configuration_file; @@ -300,8 +301,8 @@ gboolean lsp_utils_is_lsp_disabled_for_project(void) LspServerConfig *all_cfg = lsp_server_get_all_section_config(); return geany->app->project && - (project_configuration_type == DisableConfigurationType || - (project_configuration_type == UnconfiguredConfigurationType && !all_cfg->enable_by_default)); + (project_configuration == DisabledConfiguration || + (project_configuration == UnconfiguredConfiguration && !all_cfg->enable_by_default)); } diff --git a/lsp/src/lsp-utils.h b/lsp/src/lsp-utils.h index bb08aaffc..986e1c51a 100644 --- a/lsp/src/lsp-utils.h +++ b/lsp/src/lsp-utils.h @@ -26,10 +26,16 @@ typedef enum { - UnconfiguredConfigurationType = -1, + UnconfiguredConfiguration = -1, + DisabledConfiguration, + EnabledConfiguration +} LspProjectConfiguration; + + +typedef enum +{ UserConfigurationType, ProjectConfigurationType, - DisableConfigurationType } LspProjectConfigurationType;