Skip to content

Commit

Permalink
cli: Always print help to stdout and support json for explicit help
Browse files Browse the repository at this point in the history
  • Loading branch information
bbb651 committed Jan 13, 2025
1 parent 6e41220 commit 0266b11
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 7 deletions.
12 changes: 10 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub enum Sub {
/// Communicate with the running niri instance.
Msg {
#[command(subcommand)]
msg: Msg,
msg: Option<SubcommandOrHelp<Msg>>,
/// Format output as JSON.
#[arg(short, long)]
json: bool,
Expand Down Expand Up @@ -75,7 +75,7 @@ pub enum Msg {
/// Perform an action.
Action {
#[command(subcommand)]
action: Action,
action: Option<SubcommandOrHelp<Action>>,
},
/// Change output configuration temporarily.
///
Expand All @@ -99,3 +99,11 @@ pub enum Msg {
/// Request an error from the running niri instance.
RequestError,
}

#[derive(Debug, Subcommand)]
#[command(disable_help_subcommand(true))]
pub enum SubcommandOrHelp<T: Subcommand> {
#[command(flatten)]
Subcommand(T),
Help,
}
7 changes: 5 additions & 2 deletions src/ipc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use niri_ipc::{
};
use serde_json::json;

use crate::cli::Msg;
use crate::cli::{Msg, SubcommandOrHelp};
use crate::utils::version;

pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Expand All @@ -19,7 +19,10 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Msg::Outputs => Request::Outputs,
Msg::FocusedWindow => Request::FocusedWindow,
Msg::FocusedOutput => Request::FocusedOutput,
Msg::Action { action } => Request::Action(action.clone()),
Msg::Action {
action: Some(SubcommandOrHelp::Subcommand(action)),
} => Request::Action(action.clone()),
Msg::Action { action: _ } => unreachable!(),
Msg::Output { output, action } => Request::Output {
output: output.clone(),
action: action.clone(),
Expand Down
83 changes: 80 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use std::path::PathBuf;
use std::process::Command;
use std::{env, mem};

use clap::Parser;
use clap::{CommandFactory, Parser};
use directories::ProjectDirs;
use niri::cli::{Cli, Sub};
use niri::cli::{Cli, Msg, Sub, SubcommandOrHelp};
#[cfg(feature = "dbus")]
use niri::dbus;
use niri::ipc::client::handle_msg;
Expand All @@ -26,6 +26,7 @@ use niri_config::Config;
use niri_ipc::socket::SOCKET_PATH_ENV;
use portable_atomic::Ordering;
use sd_notify::NotifyState;
use serde::Serialize;
use smithay::reexports::calloop::EventLoop;
use smithay::reexports::wayland_server::Display;
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -66,6 +67,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.init();

let cli = Cli::parse();
let mut command = Cli::command();

if cli.session {
// If we're starting as a session, assume that the intention is to start on a TTY. Remove
Expand Down Expand Up @@ -100,7 +102,82 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
info!("config is valid");
return Ok(());
}
Sub::Msg { msg, json } => {
Sub::Msg { msg: None, .. } => {
let subcommand = command.find_subcommand_mut("msg").unwrap();
subcommand.print_help().unwrap();
return Ok(());
}
Sub::Msg {
msg: Some(SubcommandOrHelp::Help),
json,
} => {
let subcommand = command.find_subcommand_mut("msg").unwrap();
if json {
#[derive(Serialize)]
struct ActionJson<'a> {
name: &'a str,
description: Option<String>,
}
let actions = subcommand
.get_subcommands()
.map(|action| ActionJson {
name: action.get_name(),
description: action.get_about().map(|about| format!("{about}")),
})
.collect::<Vec<_>>();
serde_json::to_writer(std::io::stdout(), &actions).unwrap();
} else {
subcommand.print_help().unwrap();
}
return Ok(());
}
Sub::Msg {
msg: Some(SubcommandOrHelp::Subcommand(Msg::Action { action: None, .. })),
..
} => {
let subcommand = command
.find_subcommand_mut("msg")
.unwrap()
.find_subcommand_mut("action")
.unwrap();
subcommand.print_help().unwrap();
return Ok(());
}
Sub::Msg {
msg:
Some(SubcommandOrHelp::Subcommand(Msg::Action {
action: Some(SubcommandOrHelp::Help),
})),
json,
} => {
let subcommand = command
.find_subcommand_mut("msg")
.unwrap()
.find_subcommand_mut("action")
.unwrap();
if json {
#[derive(Serialize)]
struct ActionJson<'a> {
name: &'a str,
description: Option<String>,
}
let actions = subcommand
.get_subcommands()
.map(|action| ActionJson {
name: action.get_name(),
description: action.get_about().map(|about| format!("{about}")),
})
.collect::<Vec<_>>();
serde_json::to_writer(std::io::stdout(), &actions).unwrap();
} else {
subcommand.print_help().unwrap();
}
return Ok(());
}
Sub::Msg {
msg: Some(SubcommandOrHelp::Subcommand(msg)),
json,
} => {
handle_msg(msg, json)?;
return Ok(());
}
Expand Down

0 comments on commit 0266b11

Please sign in to comment.