feat: add initialization options (#6)

* feat: add initialization options

* docs: add section about how to configure

* refactor: clippy
This commit is contained in:
Jozef Steinhübl 2024-08-03 21:36:23 +02:00 committed by GitHub
parent 5277297f19
commit ad5333a502
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 108 additions and 16 deletions

6
Cargo.lock generated
View file

@ -119,6 +119,7 @@ version = "0.2.1"
dependencies = [ dependencies = [
"discord-rich-presence", "discord-rich-presence",
"git2", "git2",
"serde_json",
"tokio", "tokio",
"tower-lsp", "tower-lsp",
] ]
@ -618,11 +619,12 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.120" version = "1.0.122"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr",
"ryu", "ryu",
"serde", "serde",
] ]

View file

@ -13,3 +13,21 @@ The easiest way to get [rust](https://rust-lang.org) is by using [rustup](https:
2. <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>P</kbd> and select <kbd>zed: install dev extension</kbd> 2. <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>P</kbd> and select <kbd>zed: install dev extension</kbd>
3. Choose the directory where you cloned this repository 3. Choose the directory where you cloned this repository
4. Enjoy :) 4. Enjoy :)
## How to configure?
You can configure state, details and git integration by changing Discord Presence LSP settings. This can be done in <kbd>zed: open settings</kbd> with following configuration:
```json
{
"lsp": {
"discord_presence": {
"initialization_options": {
"state": "Working on {filename}",
"details": "In {workspace}",
"git_integration": true
}
}
}
}
```

View file

@ -8,3 +8,4 @@ discord-rich-presence = "0.2.4"
tokio = { version = "1.37.0", features = ["full"] } tokio = { version = "1.37.0", features = ["full"] }
tower-lsp = "0.20.0" tower-lsp = "0.20.0"
git2 = "0.19.0" git2 = "0.19.0"
serde_json = "1.0.122"

57
lsp/src/configuration.rs Normal file
View file

@ -0,0 +1,57 @@
/*
* This file is part of discord-presence. Extension for Zed that adds support for Discord Rich Presence using LSP.
*
* Copyright (c) 2024 Steinhübl
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
use serde_json::Value;
#[derive(Debug)]
pub struct Configuration {
pub state: String,
pub details: String,
pub git_integration: bool,
}
impl Configuration {
pub fn new() -> Self {
Self {
state: String::from("Working on {filename}"),
details: String::from("In {workspace}"),
git_integration: true,
}
}
pub fn set(&mut self, initialization_options: Option<Value>) {
if initialization_options.is_none() {
return;
}
let initialization_options = initialization_options.unwrap();
if let Some(state) = initialization_options.get("state") {
self.state = state.as_str().unwrap().to_string();
}
if let Some(details) = initialization_options.get("details") {
self.details = details.as_str().unwrap().to_string();
}
if let Some(git_integration) = initialization_options.get("git_integration") {
self.git_integration = git_integration.as_bool().unwrap_or(true);
}
}
}

View file

@ -60,19 +60,11 @@ impl Discord {
result.unwrap(); result.unwrap();
} }
pub fn change_file(&self, filename: &str, workspace: &str, git_remote_url: Option<String>) {
self.change_activity(
format!("Working on {}", filename),
format!("In {}", workspace),
git_remote_url,
)
}
pub fn get_client(&self) -> MutexGuard<DiscordIpcClient> { pub fn get_client(&self) -> MutexGuard<DiscordIpcClient> {
return self.client.lock().expect("Failed to lock discord client"); return self.client.lock().expect("Failed to lock discord client");
} }
fn change_activity(&self, state: String, details: String, git_remote_url: Option<String>) { pub fn change_activity(&self, state: String, details: String, git_remote_url: Option<String>) {
let mut client = self.get_client(); let mut client = self.get_client();
let timestamp: i64 = self.start_timestamp.as_millis() as i64; let timestamp: i64 = self.start_timestamp.as_millis() as i64;

View file

@ -21,12 +21,14 @@ use std::fmt::Debug;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
use configuration::Configuration;
use discord::Discord; use discord::Discord;
use git::get_repository_and_remote; use git::get_repository_and_remote;
use tower_lsp::jsonrpc::Result; use tower_lsp::jsonrpc::Result;
use tower_lsp::lsp_types::*; use tower_lsp::lsp_types::*;
use tower_lsp::{Client, LanguageServer, LspService, Server}; use tower_lsp::{Client, LanguageServer, LspService, Server};
mod configuration;
mod discord; mod discord;
mod git; mod git;
@ -41,6 +43,7 @@ struct Backend {
client: Client, client: Client,
workspace_file_name: Mutex<String>, workspace_file_name: Mutex<String>,
git_remote_url: Mutex<Option<String>>, git_remote_url: Mutex<Option<String>>,
config: Mutex<Configuration>,
} }
impl Document { impl Document {
@ -65,15 +68,27 @@ impl Backend {
discord: Discord::new(), discord: Discord::new(),
workspace_file_name: Mutex::new(String::new()), workspace_file_name: Mutex::new(String::new()),
git_remote_url: Mutex::new(None), git_remote_url: Mutex::new(None),
config: Mutex::new(Configuration::new()),
} }
} }
async fn on_change(&self, doc: Document) { async fn on_change(&self, doc: Document) {
self.discord.change_file( let config = self.get_config();
doc.get_filename(),
self.get_workspace_file_name().as_str(), let state = config.state.replace("{filename}", doc.get_filename());
self.get_git_remote_url(), let details = config
) .details
.replace("{workspace}", &self.get_workspace_file_name());
self.discord.change_activity(
state,
details,
if config.git_integration {
self.get_git_remote_url()
} else {
None
},
);
} }
fn get_workspace_file_name(&self) -> MutexGuard<'_, String> { fn get_workspace_file_name(&self) -> MutexGuard<'_, String> {
@ -91,6 +106,10 @@ impl Backend {
guard.clone() guard.clone()
} }
fn get_config(&self) -> MutexGuard<Configuration> {
return self.config.lock().expect("Failed to lock config");
}
} }
#[tower_lsp::async_trait] #[tower_lsp::async_trait]
@ -116,6 +135,9 @@ impl LanguageServer for Backend {
let mut git_remote_url = self.git_remote_url.lock().unwrap(); let mut git_remote_url = self.git_remote_url.lock().unwrap();
*git_remote_url = get_repository_and_remote(workspace_path.to_str().unwrap()); *git_remote_url = get_repository_and_remote(workspace_path.to_str().unwrap());
let mut config = self.config.lock().unwrap();
config.set(params.initialization_options);
Ok(InitializeResult { Ok(InitializeResult {
server_info: Some(ServerInfo { server_info: Some(ServerInfo {
name: env!("CARGO_PKG_NAME").into(), name: env!("CARGO_PKG_NAME").into(),