Skip to content

Commit 42c19e7

Browse files
Refactor and reorganize primary djls crate (#136)
1 parent ec141b7 commit 42c19e7

File tree

5 files changed

+97
-97
lines changed

5 files changed

+97
-97
lines changed

crates/djls/src/args.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use clap::Parser;
2+
3+
#[derive(Parser, Debug, Clone)]
4+
pub struct Args {
5+
/// Do not print any output.
6+
#[arg(global = true, long, short, conflicts_with = "verbose")]
7+
pub quiet: bool,
8+
9+
/// Use verbose output.
10+
#[arg(global = true, action = clap::ArgAction::Count, long, short, conflicts_with = "quiet")]
11+
pub verbose: u8,
12+
}

crates/djls/src/cli.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use crate::args::Args;
2+
use crate::commands::{Command, DjlsCommand};
3+
use anyhow::Result;
4+
use clap::Parser;
5+
use std::process::ExitCode;
6+
7+
/// Main CLI structure that defines the command-line interface
8+
#[derive(Parser)]
9+
#[command(name = "djls")]
10+
#[command(version, about)]
11+
pub struct Cli {
12+
#[command(subcommand)]
13+
pub command: DjlsCommand,
14+
15+
#[command(flatten)]
16+
pub args: Args,
17+
}
18+
19+
/// Parse CLI arguments and execute the chosen command
20+
pub async fn run(args: Vec<String>) -> Result<ExitCode> {
21+
let cli = Cli::try_parse_from(args).unwrap_or_else(|e| {
22+
e.exit();
23+
});
24+
25+
match &cli.command {
26+
DjlsCommand::Serve(cmd) => cmd.execute(&cli.args).await,
27+
}
28+
}

crates/djls/src/commands.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
use clap::{Parser, ValueEnum};
1+
pub mod serve;
22

3-
#[derive(Debug, Parser)]
4-
pub struct Serve {
5-
#[arg(short, long, default_value_t = ConnectionType::Stdio, value_enum)]
6-
connection_type: ConnectionType,
3+
use crate::args::Args;
4+
use anyhow::Result;
5+
use clap::Subcommand;
6+
use std::process::ExitCode;
7+
8+
pub trait Command {
9+
async fn execute(&self, args: &Args) -> Result<ExitCode>;
710
}
811

9-
#[derive(Clone, Debug, ValueEnum)]
10-
enum ConnectionType {
11-
Stdio,
12-
Tcp,
12+
#[derive(Debug, Subcommand)]
13+
pub enum DjlsCommand {
14+
/// Start the LSP server
15+
Serve(self::serve::Serve),
1316
}

crates/djls/src/commands/serve.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use crate::args::Args;
2+
use crate::commands::Command;
3+
use anyhow::Result;
4+
use clap::{Parser, ValueEnum};
5+
use std::process::ExitCode;
6+
7+
#[derive(Debug, Parser)]
8+
pub struct Serve {
9+
#[arg(short, long, default_value_t = ConnectionType::Stdio, value_enum)]
10+
connection_type: ConnectionType,
11+
}
12+
13+
#[derive(Clone, Debug, ValueEnum)]
14+
enum ConnectionType {
15+
Stdio,
16+
Tcp,
17+
}
18+
19+
impl Command for Serve {
20+
async fn execute(&self, _args: &Args) -> Result<ExitCode> {
21+
djls_server::serve().await?;
22+
Ok(ExitCode::SUCCESS)
23+
}
24+
}

crates/djls/src/lib.rs

Lines changed: 21 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,12 @@
1+
mod args;
2+
mod cli;
13
mod commands;
24

3-
use crate::commands::Serve;
4-
use anyhow::Result;
5-
use clap::{Parser, Subcommand};
65
use pyo3::prelude::*;
76
use std::env;
87
use std::process::ExitCode;
98

10-
#[derive(Parser)]
11-
#[command(name = "djls")]
12-
#[command(version, about, long_about = None)]
13-
pub struct Cli {
14-
#[command(subcommand)]
15-
command: Command,
16-
17-
#[command(flatten)]
18-
args: Args,
19-
}
20-
21-
#[derive(Debug, Subcommand)]
22-
enum Command {
23-
/// Start the LSP server
24-
Serve(Serve),
25-
}
26-
27-
#[derive(Parser)]
28-
pub struct Args {
29-
#[command(flatten)]
30-
global: GlobalArgs,
31-
}
32-
33-
#[derive(Parser, Debug, Clone)]
34-
struct GlobalArgs {
35-
/// Do not print any output.
36-
#[arg(global = true, long, short, conflicts_with = "verbose")]
37-
pub quiet: bool,
38-
39-
/// Use verbose output.
40-
#[arg(global = true, action = clap::ArgAction::Count, long, short, conflicts_with = "quiet")]
41-
pub verbose: u8,
42-
}
9+
pub use cli::Cli;
4310

4411
#[pyfunction]
4512
fn entrypoint(_py: Python) -> PyResult<()> {
@@ -48,62 +15,28 @@ fn entrypoint(_py: Python) -> PyResult<()> {
4815
.chain(env::args().skip(2))
4916
.collect();
5017

51-
let runtime = tokio::runtime::Runtime::new().unwrap();
52-
let local = tokio::task::LocalSet::new();
53-
local.block_on(&runtime, async move {
54-
tokio::select! {
55-
// The main CLI program
56-
result = main(args) => {
57-
match result {
58-
Ok(code) => {
59-
if code != ExitCode::SUCCESS {
60-
std::process::exit(1);
61-
}
62-
Ok::<(), PyErr>(())
63-
}
64-
Err(e) => {
65-
eprintln!("Error: {}", e);
66-
if let Some(source) = e.source() {
67-
eprintln!("Caused by: {}", source);
68-
}
69-
std::process::exit(1);
70-
}
71-
}
72-
}
73-
// Ctrl+C handling
74-
_ = tokio::signal::ctrl_c() => {
75-
println!("\nReceived Ctrl+C, shutting down...");
76-
// Cleanup code here if needed
77-
std::process::exit(130); // Standard Ctrl+C exit code
18+
let runtime = tokio::runtime::Builder::new_multi_thread()
19+
.enable_all()
20+
.build()
21+
.unwrap();
22+
23+
let result = runtime.block_on(cli::run(args));
24+
25+
match result {
26+
Ok(code) => {
27+
if code != ExitCode::SUCCESS {
28+
std::process::exit(1);
7829
}
79-
// SIGTERM handling (Unix only)
80-
_ = async {
81-
#[cfg(unix)]
82-
{
83-
use tokio::signal::unix::{signal, SignalKind};
84-
let mut term = signal(SignalKind::terminate()).unwrap();
85-
term.recv().await;
86-
}
87-
} => {
88-
println!("\nReceived termination signal, shutting down...");
89-
std::process::exit(143); // Standard SIGTERM exit code
30+
Ok(())
31+
}
32+
Err(e) => {
33+
eprintln!("Error: {}", e);
34+
if let Some(source) = e.source() {
35+
eprintln!("Caused by: {}", source);
9036
}
37+
std::process::exit(1);
9138
}
92-
})?;
93-
94-
Ok(())
95-
}
96-
97-
async fn main(args: Vec<String>) -> Result<ExitCode> {
98-
let cli = Cli::try_parse_from(args).unwrap_or_else(|e| {
99-
e.exit();
100-
});
101-
102-
match cli.command {
103-
Command::Serve(_serve) => djls_server::serve().await?,
10439
}
105-
106-
Ok(ExitCode::SUCCESS)
10740
}
10841

10942
#[pymodule]

0 commit comments

Comments
 (0)