Skip to content

Commit

Permalink
Merge pull request #85 from Kxnr/remove-completion
Browse files Browse the repository at this point in the history
feat: add lsp workspace commands to open daily notes
  • Loading branch information
Feel-ix-343 authored May 20, 2024
2 parents 7218698 + ccce5e7 commit 418c50b
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 5 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ repository = "https://github.com/Feel-ix-343/markdown-oxide"
anyhow = "1.0.80"
chrono = "0.4.35"
config = "0.14.0"
fuzzydate = "0.2.2"
indexmap = "2.2.6"
itertools = "0.10.5"
nanoid = "0.4.0"
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,30 @@ Markdown Oxide's features are implemented in the form of a language server aimin
</details>
- <details>
<summary>(optional) Enable opening daily notes with natural langauge</summary>
Modify your lsp `on_attach` function to support opening daily notes with, for example, `:Daily two days ago` or `:Daily next monday`. The specification can be found [here](https://docs.rs/fuzzydate/latest/fuzzydate/)
```lua
-- setup Markdown Oxide daily note commands
if client.name == "markdown_oxide" then
vim.api.nvim_create_user_command(
"Daily",
function(args)
local input = args.args
vim.lsp.buf.execute_command({command="jump", arguments={input}})
end,
{desc = 'Open daily note', nargs = "*"}
)
end
```
</details>
### VSCode
Expand Down
88 changes: 88 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use std::fs::File;
use std::path::Path;

use crate::config::Settings;
use chrono::offset::Local;
use chrono::NaiveDateTime;
use fuzzydate::parse;
use serde_json::Value;
use tower_lsp::jsonrpc::{Error, Result};
use tower_lsp::lsp_types::{MessageType, ShowDocumentParams, Url};

fn datetime_to_file(datetime: NaiveDateTime, dailynote_format: &str, root_dir: &Path) -> Option<Url> {
let filename = datetime.format(dailynote_format).to_string();
let path = root_dir.join(&filename);

println!("path: {:?}", path);

Url::from_file_path(path.with_extension("md")).ok()
}

pub async fn jump(
client: &tower_lsp::Client,
root_dir: &Path,
settings: &Settings,
jump_to: Option<&str>,
) -> Result<Option<Value>> {
// if jump_to is None, use the current time.

let daily_note_format = &settings.dailynote;
let note_file = match jump_to {
Some(jmp_str) => parse(jmp_str)
.ok()
.and_then(|dt| datetime_to_file(dt, &daily_note_format, root_dir)),
None => datetime_to_file(Local::now().naive_local(), &daily_note_format, root_dir),
};

if let Some(uri) = note_file {
// file creation can fail and return an Err, ignore this and try
// to open the file on the off chance the client knows what to do
// TODO: log failure to create file
let _ = uri.to_file_path().map(|path| {
path.parent().map(|parent| std::fs::create_dir_all(parent));
if !path.exists() {
let _ = File::create(path.as_path().to_owned());
}
});

client
.show_document(ShowDocumentParams {
uri,
external: Some(false),
take_focus: Some(true),
selection: None,
})
.await
.map(|success| Some(success.into()))
} else {
client
.log_message(
MessageType::ERROR,
format!("could not parse {jump_to:?}: {:?}", jump_to.map(parse)),
)
.await;
Err(Error::invalid_params(
format!("Could not parse journal format ({jump_to:?}) as a valid uri: {:?}.", jump_to.map(parse)),
))
}
}

// tests
#[cfg(test)]
mod tests {
use fuzzydate::parse;

use super::datetime_to_file;


#[test]
fn test_string_to_file() {

let input = "today";

let parsed_datetime = parse(input).unwrap();

let _ = datetime_to_file(parsed_datetime, "%Y-%m-%d", &std::fs::canonicalize("./").unwrap()).unwrap();

}
}
19 changes: 14 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::collections::HashSet;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::path::PathBuf;
use std::sync::Arc;

use completion::get_completions;
Expand All @@ -23,6 +22,7 @@ use vault::Vault;

mod codeactions;
mod codelens;
mod commands;
mod completion;
mod config;
mod diagnostics;
Expand Down Expand Up @@ -291,9 +291,10 @@ impl Backend {
#[tower_lsp::async_trait]
impl LanguageServer for Backend {
async fn initialize(&self, i: InitializeParams) -> Result<InitializeResult> {

let root_dir = match i.root_uri {
Some(uri) => uri.to_file_path().or(Err(Error::new(ErrorCode::InvalidParams)))?,
Some(uri) => uri
.to_file_path()
.or(Err(Error::new(ErrorCode::InvalidParams)))?,
None => std::env::current_dir().or(Err(Error::new(ErrorCode::InvalidParams)))?,
};

Expand Down Expand Up @@ -371,7 +372,7 @@ impl LanguageServer for Backend {
resolve_provider: None,
}),
execute_command_provider: Some(ExecuteCommandOptions {
commands: vec!["apply_edits".into()],
commands: vec!["apply_edits".into(), "jump".into()],
..Default::default()
}),
semantic_tokens_provider: Some(
Expand Down Expand Up @@ -585,6 +586,14 @@ impl LanguageServer for Backend {

Ok(None)
}
ExecuteCommandParams { command, .. } if *command == *"jump" => {
let jump_to = params.arguments.first().and_then(|val| val.as_str());
let settings = self
.bind_settings(|settings| Ok(settings.to_owned()))
.await?;
let root_dir = self.bind_vault(|vault| Ok(vault.root_dir().to_owned())).await?;
commands::jump(&self.client, &root_dir, &settings, jump_to).await
}
_ => Ok(None),
}
}
Expand Down

0 comments on commit 418c50b

Please sign in to comment.