mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-15 19:28:00 +01:00
Read config from ~/.config/asciinema/config.toml
This commit is contained in:
112
Cargo.lock
generated
112
Cargo.lock
generated
@@ -17,6 +17,17 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.4"
|
||||
@@ -77,6 +88,7 @@ version = "3.0.0-alpha.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"config",
|
||||
"mio",
|
||||
"nix",
|
||||
"reqwest",
|
||||
@@ -102,6 +114,17 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@@ -223,6 +246,21 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "config"
|
||||
version = "0.13.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"pathdiff",
|
||||
"rust-ini",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
@@ -248,6 +286,12 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlv-list"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.33"
|
||||
@@ -405,6 +449,15 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
@@ -521,7 +574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -545,6 +598,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.149"
|
||||
@@ -585,6 +644,12 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
@@ -626,6 +691,16 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
@@ -657,6 +732,22 @@ version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.1"
|
||||
@@ -778,6 +869,16 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
@@ -1075,6 +1176,15 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
|
||||
@@ -23,3 +23,4 @@ signal-hook = "0.3.17"
|
||||
uuid = { version = "1.6.1", features = ["v4"] }
|
||||
reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "rustls-tls", "multipart", "gzip", "json"] }
|
||||
rustyline = "13.0.0"
|
||||
config = { version = "0.13.4", default-features = false, features = ["toml", "ini"] }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::util;
|
||||
use crate::{config::Config, util};
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::Args;
|
||||
use reqwest::Url;
|
||||
@@ -7,8 +7,8 @@ use reqwest::Url;
|
||||
pub struct Cli {}
|
||||
|
||||
impl Cli {
|
||||
pub fn run(self, server_url: &Option<String>) -> Result<()> {
|
||||
let auth_url = auth_url(server_url)?;
|
||||
pub fn run(self, config: &Config) -> Result<()> {
|
||||
let auth_url = auth_url(config.server_url())?;
|
||||
let server_hostname = auth_url.host().ok_or(anyhow!("invalid server URL"))?;
|
||||
|
||||
println!("Open the following URL in a web browser to authenticate this asciinema CLI with your {server_hostname} user account:\n");
|
||||
@@ -19,8 +19,8 @@ impl Cli {
|
||||
}
|
||||
}
|
||||
|
||||
fn auth_url(server_url: &Option<String>) -> Result<Url> {
|
||||
let mut url = util::get_server_url(server_url.as_ref())?;
|
||||
fn auth_url(server_url: Option<&String>) -> Result<Url> {
|
||||
let mut url = util::get_server_url(server_url)?;
|
||||
url.set_path(&format!("connect/{}", util::get_install_id()?));
|
||||
|
||||
Ok(url)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::config::Config;
|
||||
use crate::util;
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::Args;
|
||||
@@ -21,12 +22,12 @@ struct UploadResponse {
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
pub fn run(self, server_url: &Option<String>) -> Result<()> {
|
||||
pub fn run(self, config: &Config) -> Result<()> {
|
||||
let client = Client::new();
|
||||
let form = Form::new().file("asciicast", self.filename)?;
|
||||
|
||||
let response = client
|
||||
.post(api_url(server_url)?)
|
||||
.post(api_url(config.server_url())?)
|
||||
.multipart(form)
|
||||
.basic_auth(get_username(), Some(util::get_install_id()?))
|
||||
.header(header::USER_AGENT, build_user_agent())
|
||||
@@ -56,8 +57,8 @@ impl Cli {
|
||||
}
|
||||
}
|
||||
|
||||
fn api_url(server_url: &Option<String>) -> Result<Url> {
|
||||
let mut url = util::get_server_url(server_url.as_ref())?;
|
||||
fn api_url(server_url: Option<&String>) -> Result<Url> {
|
||||
let mut url = util::get_server_url(server_url)?;
|
||||
url.set_path("api/asciicasts");
|
||||
|
||||
Ok(url)
|
||||
|
||||
92
src/config.rs
Normal file
92
src/config.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Config {
|
||||
server: Server,
|
||||
api: Api,
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Server {
|
||||
url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Api {
|
||||
url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Cmd {
|
||||
rec: Rec,
|
||||
play: Play,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
#[allow(unused)]
|
||||
pub struct Rec {
|
||||
pub input: bool,
|
||||
pub command: Option<String>,
|
||||
pub env: String,
|
||||
pub idle_time_limit: Option<f64>,
|
||||
pub prefix_key: Option<String>,
|
||||
pub pause_key: String,
|
||||
pub add_marker_key: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(unused)]
|
||||
pub struct Play {
|
||||
pub speed: f64,
|
||||
pub idle_time_limit: Option<f64>,
|
||||
pub pause_key: String,
|
||||
pub step_key: String,
|
||||
pub next_marker_key: String,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new(server_url: Option<String>) -> Result<Self> {
|
||||
let user_config_file = home()?.join("config.toml");
|
||||
|
||||
let mut config = config::Config::builder()
|
||||
.set_default("server.url", None::<Option<String>>)?
|
||||
.set_default("api.url", None::<Option<String>>)?
|
||||
.set_default("cmd.rec.input", false)?
|
||||
.set_default("cmd.rec.env", "SHELL,TERM")?
|
||||
.set_default("cmd.rec.pause_key", "C-\\")?
|
||||
.set_default("cmd.play.speed", 1.0)?
|
||||
.set_default("cmd.play.pause_key", " ")?
|
||||
.set_default("cmd.play.step_key", ".")?
|
||||
.set_default("cmd.play.next_marker_key", "]")?
|
||||
.add_source(
|
||||
config::File::with_name(&user_config_file.to_string_lossy()).required(false),
|
||||
)
|
||||
.add_source(config::Environment::with_prefix("asciinema").separator("_"));
|
||||
|
||||
if let Some(url) = server_url {
|
||||
config = config.set_override("server.url", Some(url))?;
|
||||
}
|
||||
|
||||
Ok(config.build()?.try_deserialize()?)
|
||||
}
|
||||
|
||||
pub fn server_url(&self) -> Option<&String> {
|
||||
self.server.url.as_ref().or(self.api.url.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn home() -> Result<PathBuf> {
|
||||
env::var("ASCIINEMA_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.or(env::var("XDG_CONFIG_HOME").map(|home| Path::new(&home).join("asciinema")))
|
||||
.or(env::var("HOME").map(|home| Path::new(&home).join(".config").join("asciinema")))
|
||||
.map_err(|_| anyhow!("need $HOME or $XDG_CONFIG_HOME or $ASCIINEMA_CONFIG_HOME"))
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
mod cmd;
|
||||
mod config;
|
||||
mod format;
|
||||
mod locale;
|
||||
mod pty;
|
||||
mod recorder;
|
||||
mod util;
|
||||
use crate::config::Config;
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
@@ -40,13 +42,13 @@ enum Commands {
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
let server_url = &cli.server_url;
|
||||
let config = Config::new(cli.server_url.clone())?;
|
||||
|
||||
match cli.command {
|
||||
Commands::Record(record) => record.run(),
|
||||
Commands::Play(play) => play.run(),
|
||||
Commands::Cat(cat) => cat.run(),
|
||||
Commands::Upload(upload) => upload.run(server_url),
|
||||
Commands::Auth(auth) => auth.run(server_url),
|
||||
Commands::Upload(upload) => upload.run(&config),
|
||||
Commands::Auth(auth) => auth.run(&config),
|
||||
}
|
||||
}
|
||||
|
||||
24
src/util.rs
24
src/util.rs
@@ -1,3 +1,4 @@
|
||||
use crate::config;
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use reqwest::Url;
|
||||
use std::{env, fs, io::ErrorKind, path::Path, path::PathBuf};
|
||||
@@ -29,7 +30,7 @@ fn create_install_id() -> Result<String> {
|
||||
}
|
||||
|
||||
fn read_legacy_install_id() -> Result<Option<String>> {
|
||||
let path = config_home()?.join(INSTALL_ID_FILENAME);
|
||||
let path = config::home()?.join(INSTALL_ID_FILENAME);
|
||||
|
||||
match fs::read_to_string(path) {
|
||||
Ok(s) => Ok(Some(s.trim().to_string())),
|
||||
@@ -44,17 +45,14 @@ fn read_legacy_install_id() -> Result<Option<String>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_server_url<S: ToString>(server_url: Option<S>) -> Result<Url> {
|
||||
let mut url_opt = server_url
|
||||
.map(|s| s.to_string())
|
||||
.or(env::var("ASCIINEMA_SERVER_URL").ok())
|
||||
.or(env::var("ASCIINEMA_API_URL").ok());
|
||||
pub fn get_server_url(server_url: Option<&String>) -> Result<Url> {
|
||||
let mut url = server_url.cloned();
|
||||
|
||||
if url_opt.is_none() {
|
||||
url_opt = read_state_file(DEFAULT_SERVER_URL_FILENAME)?;
|
||||
if url.is_none() {
|
||||
url = read_state_file(DEFAULT_SERVER_URL_FILENAME)?;
|
||||
}
|
||||
|
||||
match url_opt {
|
||||
match url {
|
||||
Some(url) => Ok(Url::parse(&url)?),
|
||||
|
||||
None => {
|
||||
@@ -106,14 +104,6 @@ fn write_state_file(filename: &str, contents: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn config_home() -> Result<PathBuf> {
|
||||
env::var("ASCIINEMA_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.or(env::var("XDG_CONFIG_HOME").map(|home| Path::new(&home).join("asciinema")))
|
||||
.or(env::var("HOME").map(|home| Path::new(&home).join(".config").join("asciinema")))
|
||||
.map_err(|_| anyhow!("need $HOME or $XDG_CONFIG_HOME or $ASCIINEMA_CONFIG_HOME"))
|
||||
}
|
||||
|
||||
fn state_home() -> Result<PathBuf> {
|
||||
env::var("ASCIINEMA_STATE_HOME")
|
||||
.map(PathBuf::from)
|
||||
|
||||
Reference in New Issue
Block a user