Skip to content

Commit

Permalink
Introduce PluginAction
Browse files Browse the repository at this point in the history
  • Loading branch information
liuchengxu committed Aug 11, 2023
1 parent cde0c3e commit 17183b4
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 86 deletions.
12 changes: 6 additions & 6 deletions crates/maple_core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl Default for LogConfig {

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct HighlightCursorWordConfig {
pub struct CursorWordHighlighterConfig {
/// Whether to enable this plugin.
pub enable: bool,
/// Whether to ignore the comment line
Expand All @@ -112,7 +112,7 @@ pub struct HighlightCursorWordConfig {
pub ignore_files: String,
}

impl Default for HighlightCursorWordConfig {
impl Default for CursorWordHighlighterConfig {
fn default() -> Self {
Self {
enable: false,
Expand All @@ -124,7 +124,7 @@ impl Default for HighlightCursorWordConfig {

#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct MarkdownTocConfig {
pub struct MarkdownPluginConfig {
/// Whether to enable this plugin.
pub enable: bool,
}
Expand All @@ -139,8 +139,8 @@ pub struct CtagsPluginConfig {
#[derive(Serialize, Deserialize, Debug, Default)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct PluginConfig {
pub highlight_cursor_word: HighlightCursorWordConfig,
pub markdown_toc: MarkdownTocConfig,
pub cursor_word_highlighter: CursorWordHighlighterConfig,
pub markdown: MarkdownPluginConfig,
pub ctags: CtagsPluginConfig,
}

Expand Down Expand Up @@ -260,7 +260,7 @@ mod tests {
[matcher]
tiebreak = "score,-begin,-end,-length"
[plugin.highlight-cursor-word]
[plugin.cursor-word-highlighter]
enable = true
[provider.debounce]
Expand Down
43 changes: 37 additions & 6 deletions crates/maple_core/src/stdio_server/input.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::stdio_server::plugin::{MarkdownPlugin, PluginId, SystemPlugin};
use crate::stdio_server::provider::ProviderId;
use crate::stdio_server::service::ProviderSessionId;
use rpc::{Params, RpcNotification};
Expand All @@ -10,6 +11,7 @@ pub type AutocmdEvent = (AutocmdEventType, Params);
#[derive(Debug, Clone)]
pub enum PluginEvent {
Autocmd(AutocmdEvent),
Action(PluginAction),
}

impl PluginEvent {
Expand All @@ -19,6 +21,7 @@ impl PluginEvent {
Self::Autocmd((autocmd_event_type, _)) => {
matches!(autocmd_event_type, AutocmdEventType::CursorMoved)
}
_ => false,
}
}
}
Expand Down Expand Up @@ -73,12 +76,43 @@ pub enum AutocmdEventType {
BufWinLeave,
}

pub type Action = (PluginId, PluginAction);

#[derive(Debug, Clone)]
pub struct Action {
pub command: String,
pub struct PluginAction {
pub action: String,
pub params: Params,
}

impl PluginAction {
fn empty() -> Self {
Self {
action: Default::default(),
params: Params::None,
}
}
}

impl From<RpcNotification> for PluginAction {
fn from(notification: RpcNotification) -> Self {
Self {
action: notification.method,
params: notification.params,
}
}
}

fn parse_action(notification: RpcNotification) -> Action {
let action = notification.method.as_str();
if SystemPlugin::ACTIONS.contains(&action) {
(PluginId::System, notification.into())
} else if MarkdownPlugin::ACTIONS.contains(&action) {
(PluginId::Markdown, notification.into())
} else {
(PluginId::Unknown, PluginAction::empty())
}
}

#[derive(Debug)]
pub enum Event {
NewProvider(Params),
Expand Down Expand Up @@ -114,10 +148,7 @@ impl Event {
"BufWritePost" => Self::Autocmd((AutocmdEventType::BufWritePost, notification.params)),
"BufWinEnter" => Self::Autocmd((AutocmdEventType::BufWinEnter, notification.params)),
"BufWinLeave" => Self::Autocmd((AutocmdEventType::BufWinLeave, notification.params)),
_ => Self::Action(Action {
command: notification.method,
params: notification.params,
}),
_ => Self::Action(parse_action(notification)),
}
}
}
Expand Down
84 changes: 26 additions & 58 deletions crates/maple_core/src/stdio_server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ mod vim;

pub use self::input::InputHistory;
use self::input::{Event, PluginEvent, ProviderEvent};
use self::plugin::{ClapPlugin, CtagsPlugin, CursorWordHighlighter};
use self::plugin::{
ClapPlugin, CtagsPlugin, CursorWordHighlighter, MarkdownPlugin, PluginId, SystemPlugin,
};
use self::provider::{create_provider, Context};
use self::service::ServiceManager;
use self::vim::initialize_syntax_map;
pub use self::vim::{Vim, VimProgressor};
use crate::stdio_server::input::Action;
use anyhow::{anyhow, Result};
use parking_lot::Mutex;
use rpc::{RpcClient, RpcNotification, RpcRequest, VimMessage};
Expand Down Expand Up @@ -89,13 +90,27 @@ impl Client {
/// Creates a new instnace of [`Client`].
fn new(vim: Vim) -> Self {
let mut service_manager = ServiceManager::default();
if crate::config::config().plugin.ctags.enable {
service_manager
.new_plugin(Box::new(CtagsPlugin::new(vim.clone())) as Box<dyn ClapPlugin>);
service_manager.new_plugin(
PluginId::System,
Box::new(SystemPlugin::new(vim.clone())) as Box<dyn ClapPlugin>,
);
let plugin = &crate::config::config().plugin;
if plugin.ctags.enable {
service_manager.new_plugin(
PluginId::Ctags,
Box::new(CtagsPlugin::new(vim.clone())) as Box<dyn ClapPlugin>,
);
}
if plugin.markdown.enable {
service_manager.new_plugin(
PluginId::Markdown,
Box::new(MarkdownPlugin::new(vim.clone())) as Box<dyn ClapPlugin>,
);
}
if crate::config::config().plugin.highlight_cursor_word.enable {
if plugin.cursor_word_highlighter.enable {
service_manager.new_plugin(
Box::new(CursorWordHighlighter::new(vim.clone())) as Box<dyn ClapPlugin>
PluginId::CursorWordHighlighter,
Box::new(CursorWordHighlighter::new(vim.clone())) as Box<dyn ClapPlugin>,
);
}
Self {
Expand Down Expand Up @@ -226,58 +241,11 @@ impl Client {
.lock()
.notify_plugins(PluginEvent::Autocmd(autocmd_event));
}
Event::Action(action) => self.handle_action(action).await?,
}

Ok(())
}

async fn handle_action(&self, action: Action) -> Result<()> {
match action.command.as_str() {
"note_recent_files" => {
let bufnr: Vec<usize> = action.params.parse()?;
let bufnr = bufnr
.first()
.ok_or(anyhow!("bufnr not found in `note_recent_file`"))?;
let file_path: String = self.vim.expand(format!("#{bufnr}:p")).await?;
handler::messages::note_recent_file(file_path)?
}
"open-config" => {
let config_file = crate::config::config_file();
self.vim
.exec("execute", format!("edit {}", config_file.display()))?;
}
"generate-toc" => {
let curlnum = self.vim.line(".").await?;
let file = self.vim.current_buffer_path().await?;
let shiftwidth = self.vim.getbufvar("", "&shiftwidth").await?;
let mut toc = plugin::generate_toc(file, curlnum, shiftwidth)?;
let prev_line = self.vim.curbufline(curlnum - 1).await?;
if !prev_line.map(|line| line.is_empty()).unwrap_or(false) {
toc.push_front(Default::default());
}
self.vim
.exec("append_and_write", json!([curlnum - 1, toc]))?;
}
"update-toc" => {
let file = self.vim.current_buffer_path().await?;
let bufnr = self.vim.bufnr("").await?;
if let Some((start, end)) = plugin::find_toc_range(&file)? {
let shiftwidth = self.vim.getbufvar("", "&shiftwidth").await?;
// TODO: skip update if the new doc is the same as the old one.
let new_toc = plugin::generate_toc(file, start + 1, shiftwidth)?;
self.vim.deletebufline(bufnr, start + 1, end + 1).await?;
self.vim.exec("append_and_write", json!([start, new_toc]))?;
}
}
"delete-toc" => {
let file = self.vim.current_buffer_path().await?;
let bufnr = self.vim.bufnr("").await?;
if let Some((start, end)) = plugin::find_toc_range(file)? {
self.vim.deletebufline(bufnr, start + 1, end + 1).await?;
}
Event::Action((plugin_id, plugin_action)) => {
self.service_manager_mutex
.lock()
.notify_plugin(plugin_id, PluginEvent::Action(plugin_action));
}
_ => return Err(anyhow!("Unknown action: {action:?}")),
}

Ok(())
Expand Down
4 changes: 3 additions & 1 deletion crates/maple_core/src/stdio_server/plugin/ctags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ impl ClapPlugin for CtagsPlugin {
async fn on_plugin_event(&mut self, plugin_event: PluginEvent) -> Result<()> {
use AutocmdEventType::{BufDelete, BufEnter, BufWritePost, CursorMoved};

let PluginEvent::Autocmd(autocmd_event) = plugin_event;
let PluginEvent::Autocmd(autocmd_event) = plugin_event else {
return Ok(());
};

let (event_type, params) = autocmd_event;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl CursorWordHighlighter {
pub fn new(vim: Vim) -> Self {
let (ignore_extensions, ignore_file_names): (Vec<_>, Vec<_>) = crate::config::config()
.plugin
.highlight_cursor_word
.cursor_word_highlighter
.ignore_files
.split(',')
.partition(|s| s.starts_with("*."));
Expand Down Expand Up @@ -155,7 +155,7 @@ impl CursorWordHighlighter {

if crate::config::config()
.plugin
.highlight_cursor_word
.cursor_word_highlighter
.ignore_comment_line
{
if let Some(ext) = source_file.extension().and_then(|s| s.to_str()) {
Expand Down Expand Up @@ -219,7 +219,9 @@ impl ClapPlugin for CursorWordHighlighter {
async fn on_plugin_event(&mut self, plugin_event: PluginEvent) -> Result<()> {
use AutocmdEventType::{CursorMoved, InsertEnter};

let PluginEvent::Autocmd(autocmd_event) = plugin_event;
let PluginEvent::Autocmd(autocmd_event) = plugin_event else {
return Ok(());
};

let (event_type, _params) = autocmd_event;

Expand Down
69 changes: 69 additions & 0 deletions crates/maple_core/src/stdio_server/plugin/markdown_toc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use crate::stdio_server::input::{PluginAction, PluginEvent};
use crate::stdio_server::plugin::ClapPlugin;
use crate::stdio_server::vim::Vim;
use anyhow::{anyhow, Result};
use once_cell::sync::Lazy;
use percent_encoding::{percent_encode, CONTROLS};
use regex::Regex;
use serde_json::json;
use std::collections::VecDeque;
use std::path::Path;
use std::str::FromStr;
Expand Down Expand Up @@ -192,6 +197,70 @@ pub fn find_toc_range(input_file: impl AsRef<Path>) -> std::io::Result<Option<(u
Ok(None)
}

#[derive(Debug, Clone)]
pub struct MarkdownPlugin {
vim: Vim,
}

impl MarkdownPlugin {
const GENERATE_TOC: &'static str = "markdown/generate-toc";
const UPDATE_TOC: &'static str = "markdown/update-toc";
const DELETE_TOC: &'static str = "markdown/delete-toc";

pub const ACTIONS: &[&'static str] = &[Self::GENERATE_TOC, Self::UPDATE_TOC, Self::DELETE_TOC];

pub fn new(vim: Vim) -> Self {
Self { vim }
}
}

#[async_trait::async_trait]
impl ClapPlugin for MarkdownPlugin {
async fn on_plugin_event(&mut self, plugin_event: PluginEvent) -> Result<()> {
match plugin_event {
PluginEvent::Autocmd(_) => Ok(()),
PluginEvent::Action(plugin_action) => {
let PluginAction { action, params: _ } = plugin_action;
match action.as_str() {
Self::GENERATE_TOC => {
let curlnum = self.vim.line(".").await?;
let file = self.vim.current_buffer_path().await?;
let shiftwidth = self.vim.getbufvar("", "&shiftwidth").await?;
let mut toc = generate_toc(file, curlnum, shiftwidth)?;
let prev_line = self.vim.curbufline(curlnum - 1).await?;
if !prev_line.map(|line| line.is_empty()).unwrap_or(false) {
toc.push_front(Default::default());
}
self.vim
.exec("append_and_write", json!([curlnum - 1, toc]))?;
}
Self::UPDATE_TOC => {
let file = self.vim.current_buffer_path().await?;
let bufnr = self.vim.bufnr("").await?;
if let Some((start, end)) = find_toc_range(&file)? {
let shiftwidth = self.vim.getbufvar("", "&shiftwidth").await?;
// TODO: skip update if the new doc is the same as the old one.
let new_toc = generate_toc(file, start + 1, shiftwidth)?;
self.vim.deletebufline(bufnr, start + 1, end + 1).await?;
self.vim.exec("append_and_write", json!([start, new_toc]))?;
}
}
Self::DELETE_TOC => {
let file = self.vim.current_buffer_path().await?;
let bufnr = self.vim.bufnr("").await?;
if let Some((start, end)) = find_toc_range(file)? {
self.vim.deletebufline(bufnr, start + 1, end + 1).await?;
}
}
unknown_action => return Err(anyhow!("Unknown action: {unknown_action:?}")),
}

Ok(())
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading

0 comments on commit 17183b4

Please sign in to comment.