mirror of
https://github.com/denisidoro/navi
synced 2025-02-16 12:38:28 +00:00
Merge pull request #840 from zjp-CN/win
Fix multiple paths: define the platform-specific join separator
This commit is contained in:
commit
b560ba572e
18 changed files with 121 additions and 38 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
navi.log
|
||||||
|
|
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -244,6 +244,12 @@ dependencies = [
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dunce"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "edit"
|
name = "edit"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -412,9 +418,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
@ -455,6 +461,7 @@ dependencies = [
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"dns_common",
|
"dns_common",
|
||||||
"dns_common_derive",
|
"dns_common_derive",
|
||||||
|
"dunce",
|
||||||
"edit",
|
"edit",
|
||||||
"etcetera",
|
"etcetera",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|
|
@ -37,6 +37,9 @@ dns_common_derive = { version = "0.2.1" }
|
||||||
dns_common = { version = "0.2.1", default-features = false, features = ["yaml", "json"] }
|
dns_common = { version = "0.2.1", default-features = false, features = ["yaml", "json"] }
|
||||||
unicode-width = "0.1.10"
|
unicode-width = "0.1.10"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
dunce = "1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "navi"
|
name = "navi"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
|
@ -29,3 +29,9 @@ Run the following command to generate a config file with the default parameters:
|
||||||
```sh
|
```sh
|
||||||
navi info config-example > "$(navi info config-path)"
|
navi info config-example > "$(navi info config-path)"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
The log file will be created under the same directory where the config locates.
|
||||||
|
|
||||||
|
And you can use the `RUST_LOG` env to set the log level, e.g. `RUST_LOG=debug navi`.
|
||||||
|
|
|
@ -19,14 +19,17 @@ finder:
|
||||||
# overrides_var: --tac # equivalent to the --fzf-overrides-var option
|
# overrides_var: --tac # equivalent to the --fzf-overrides-var option
|
||||||
|
|
||||||
# cheats:
|
# cheats:
|
||||||
# paths:
|
# paths:
|
||||||
# - /path/to/some/dir
|
# - /path/to/some/dir # on unix-like os
|
||||||
# - /path/to/another/dir
|
# - F:\\path\\to\\dir # on Windows
|
||||||
# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option
|
# path: /path/to/some/dir # (DEPRECATED) equivalent to the --path option
|
||||||
|
|
||||||
# search:
|
# search:
|
||||||
# tags: git,!checkout # equivalent to the --tag-rules option
|
# tags: git,!checkout # equivalent to the --tag-rules option
|
||||||
|
|
||||||
shell:
|
shell:
|
||||||
command: bash # shell used for shell out. possible values: bash, zsh, dash, ...
|
# Shell used for shell out. Possible values: bash, zsh, dash, ...
|
||||||
|
# For Windows, use `cmd.exe` instead.
|
||||||
|
command: bash
|
||||||
|
|
||||||
# finder_command: bash # similar, but for fzf's internals
|
# finder_command: bash # similar, but for fzf's internals
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
extern crate navi;
|
extern crate navi;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use dns_common::prelude::*;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -24,6 +24,36 @@ impl FileAnIssue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> anyhow::Result<()> {
|
||||||
navi::handle().map_err(|e| FileAnIssue::new(e).into())
|
if let Err(err) = init_logger() {
|
||||||
|
// may need redir stderr to a file to show this log initialization error
|
||||||
|
eprintln!("failed to initialize logging: {err:?}");
|
||||||
|
}
|
||||||
|
navi::handle().map_err(|e| {
|
||||||
|
error!("{e:?}");
|
||||||
|
FileAnIssue::new(e).into()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_logger() -> anyhow::Result<()> {
|
||||||
|
const FILE_NAME: &str = "navi.log";
|
||||||
|
let mut file = navi::default_config_pathbuf()?;
|
||||||
|
file.set_file_name(FILE_NAME);
|
||||||
|
|
||||||
|
// If config path doesn't exist, navi won't log.
|
||||||
|
if file.parent().map(|p| !p.exists()).unwrap_or(true) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let writer = std::fs::File::create(&file).with_context(|| format!("{file:?} is not created"))?;
|
||||||
|
tracing::subscriber::set_global_default(
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_writer(writer)
|
||||||
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
||||||
|
.finish(),
|
||||||
|
)?;
|
||||||
|
debug!("tracing initialized");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,10 @@ fn prompt_finder(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let child = shell::out()
|
let mut cmd = shell::out();
|
||||||
.stdout(Stdio::piped())
|
cmd.stdout(Stdio::piped()).arg(suggestion_command);
|
||||||
.arg(suggestion_command)
|
debug!(cmd = ?cmd);
|
||||||
|
let child = cmd
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| ShellSpawnError::new(suggestion_command, e))?;
|
.map_err(|e| ShellSpawnError::new(suggestion_command, e))?;
|
||||||
|
|
||||||
|
@ -236,9 +237,10 @@ pub fn act(
|
||||||
clipboard::copy(interpolated_snippet)?;
|
clipboard::copy(interpolated_snippet)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
shell::out()
|
let mut cmd = shell::out();
|
||||||
.arg(&interpolated_snippet[..])
|
cmd.arg(&interpolated_snippet[..]);
|
||||||
.spawn()
|
debug!(cmd = ?cmd);
|
||||||
|
cmd.spawn()
|
||||||
.map_err(|e| ShellSpawnError::new(&interpolated_snippet[..], e))?
|
.map_err(|e| ShellSpawnError::new(&interpolated_snippet[..], e))?
|
||||||
.wait()
|
.wait()
|
||||||
.context("bash was not running")?;
|
.context("bash was not running")?;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::welcome;
|
||||||
pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
|
pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
|
||||||
let config = &CONFIG;
|
let config = &CONFIG;
|
||||||
let opts = FinderOpts::snippet_default();
|
let opts = FinderOpts::snippet_default();
|
||||||
|
debug!("opts = {opts:#?}");
|
||||||
// let fetcher = config.fetcher();
|
// let fetcher = config.fetcher();
|
||||||
|
|
||||||
let (raw_selection, (variables, files)) = config
|
let (raw_selection, (variables, files)) = config
|
||||||
|
@ -32,6 +33,7 @@ pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
|
||||||
})
|
})
|
||||||
.context("Failed getting selection and variables from finder")?;
|
.context("Failed getting selection and variables from finder")?;
|
||||||
|
|
||||||
|
debug!(raw_selection = ?raw_selection);
|
||||||
let extractions = deser::terminal::read(&raw_selection, config.best_match());
|
let extractions = deser::terminal::read(&raw_selection, config.best_match());
|
||||||
|
|
||||||
if extractions.is_err() {
|
if extractions.is_err() {
|
||||||
|
@ -44,7 +46,9 @@ pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_fetcher() -> Result<Box<dyn Fetcher>> {
|
pub fn get_fetcher() -> Result<Box<dyn Fetcher>> {
|
||||||
match CONFIG.source() {
|
let source = CONFIG.source();
|
||||||
|
debug!(source = ?source);
|
||||||
|
match source {
|
||||||
Source::Cheats(query) => {
|
Source::Cheats(query) => {
|
||||||
let lines = cheatsh::call(&query)?;
|
let lines = cheatsh::call(&query)?;
|
||||||
let fetcher = Box::new(StaticFetcher::new(lines));
|
let fetcher = Box::new(StaticFetcher::new(lines));
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::prelude::*;
|
||||||
pub fn handle() -> Result<()> {
|
pub fn handle() -> Result<()> {
|
||||||
use crate::config::Command::*;
|
use crate::config::Command::*;
|
||||||
|
|
||||||
|
debug!("CONFIG = {:#?}", &*CONFIG);
|
||||||
match CONFIG.cmd() {
|
match CONFIG.cmd() {
|
||||||
None => commands::core::main(),
|
None => commands::core::main(),
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,10 @@ impl Runnable for Input {
|
||||||
if !extra.is_empty() {
|
if !extra.is_empty() {
|
||||||
print!("");
|
print!("");
|
||||||
|
|
||||||
shell::out()
|
let mut cmd = shell::out();
|
||||||
.arg(extra)
|
cmd.arg(extra);
|
||||||
.spawn()
|
debug!(?cmd);
|
||||||
.map_err(|e| ShellSpawnError::new(extra, e))?
|
cmd.spawn().map_err(|e| ShellSpawnError::new(extra, e))?.wait()?;
|
||||||
.wait()?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,11 @@ fn follow_symlink(pathbuf: PathBuf) -> Result<PathBuf> {
|
||||||
|
|
||||||
fn exe_pathbuf() -> Result<PathBuf> {
|
fn exe_pathbuf() -> Result<PathBuf> {
|
||||||
let pathbuf = std::env::current_exe().context("Unable to acquire executable's path")?;
|
let pathbuf = std::env::current_exe().context("Unable to acquire executable's path")?;
|
||||||
|
|
||||||
|
#[cfg(target_family = "windows")]
|
||||||
|
let pathbuf = dunce::canonicalize(pathbuf)?;
|
||||||
|
|
||||||
|
debug!(current_exe = ?pathbuf);
|
||||||
follow_symlink(pathbuf)
|
follow_symlink(pathbuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ pub enum Command {
|
||||||
Info(commands::info::Input),
|
Info(commands::info::Input),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Source {
|
pub enum Source {
|
||||||
Filesystem(Option<String>),
|
Filesystem(Option<String>),
|
||||||
Tldr(String),
|
Tldr(String),
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::env_var;
|
||||||
use crate::finder::FinderChoice;
|
use crate::finder::FinderChoice;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct EnvConfig {
|
pub struct EnvConfig {
|
||||||
pub config_yaml: Option<String>,
|
pub config_yaml: Option<String>,
|
||||||
pub config_path: Option<String>,
|
pub config_path: Option<String>,
|
||||||
|
|
|
@ -12,6 +12,7 @@ use yaml::YamlConfig;
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref CONFIG: Config = Config::new();
|
pub static ref CONFIG: Config = Config::new();
|
||||||
}
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
yaml: YamlConfig,
|
yaml: YamlConfig,
|
||||||
clap: ClapConfig,
|
clap: ClapConfig,
|
||||||
|
@ -69,7 +70,7 @@ impl Config {
|
||||||
if p.is_empty() {
|
if p.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(p.join(":"))
|
Some(p.join(crate::filesystem::JOIN_SEPARATOR))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.or_else(|| self.yaml.cheats.path.clone())
|
.or_else(|| self.yaml.cheats.path.clone())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::prelude::*;
|
||||||
use crossterm::style::Color as TerminalColor;
|
use crossterm::style::Color as TerminalColor;
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Color(#[serde(deserialize_with = "color_deserialize")] TerminalColor);
|
pub struct Color(#[serde(deserialize_with = "color_deserialize")] TerminalColor);
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
|
@ -24,7 +24,7 @@ where
|
||||||
.map_err(|_| de::Error::custom(format!("Failed to deserialize color: {s}")))
|
.map_err(|_| de::Error::custom(format!("Failed to deserialize color: {s}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct ColorWidth {
|
pub struct ColorWidth {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
|
@ -32,7 +32,7 @@ pub struct ColorWidth {
|
||||||
pub min_width: u16,
|
pub min_width: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Style {
|
pub struct Style {
|
||||||
pub tag: ColorWidth,
|
pub tag: ColorWidth,
|
||||||
|
@ -40,7 +40,7 @@ pub struct Style {
|
||||||
pub snippet: ColorWidth,
|
pub snippet: ColorWidth,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Finder {
|
pub struct Finder {
|
||||||
#[serde(deserialize_with = "finder_deserialize")]
|
#[serde(deserialize_with = "finder_deserialize")]
|
||||||
|
@ -58,27 +58,27 @@ where
|
||||||
.map_err(|_| de::Error::custom(format!("Failed to deserialize finder: {s}")))
|
.map_err(|_| de::Error::custom(format!("Failed to deserialize finder: {s}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Cheats {
|
pub struct Cheats {
|
||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
pub paths: Vec<String>,
|
pub paths: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Search {
|
pub struct Search {
|
||||||
pub tags: Option<String>,
|
pub tags: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Shell {
|
pub struct Shell {
|
||||||
pub command: String,
|
pub command: String,
|
||||||
pub finder_command: Option<String>,
|
pub finder_command: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct YamlConfig {
|
pub struct YamlConfig {
|
||||||
pub style: Style,
|
pub style: Style,
|
||||||
|
|
|
@ -12,6 +12,13 @@ use std::path::MAIN_SEPARATOR;
|
||||||
|
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
/// Multiple paths are joint by a platform-specific separator.
|
||||||
|
/// FIXME: it's actually incorrect to assume a path doesn't containing this separator
|
||||||
|
#[cfg(target_family = "windows")]
|
||||||
|
pub const JOIN_SEPARATOR: &str = ";";
|
||||||
|
#[cfg(not(target_family = "windows"))]
|
||||||
|
pub const JOIN_SEPARATOR: &str = ":";
|
||||||
|
|
||||||
pub fn all_cheat_files(path: &Path) -> Vec<String> {
|
pub fn all_cheat_files(path: &Path) -> Vec<String> {
|
||||||
WalkDir::new(path)
|
WalkDir::new(path)
|
||||||
.follow_links(true)
|
.follow_links(true)
|
||||||
|
@ -23,7 +30,7 @@ pub fn all_cheat_files(path: &Path) -> Vec<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paths_from_path_param(env_var: &str) -> impl Iterator<Item = &str> {
|
fn paths_from_path_param(env_var: &str) -> impl Iterator<Item = &str> {
|
||||||
env_var.split(':').filter(|folder| folder != &"")
|
env_var.split(JOIN_SEPARATOR).filter(|folder| folder != &"")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compiled_default_path(path: Option<&str>) -> Option<PathBuf> {
|
fn compiled_default_path(path: Option<&str>) -> Option<PathBuf> {
|
||||||
|
@ -125,6 +132,7 @@ fn interpolate_paths(paths: String) -> String {
|
||||||
newtext
|
newtext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Fetcher {
|
pub struct Fetcher {
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
files: RefCell<Vec<String>>,
|
files: RefCell<Vec<String>>,
|
||||||
|
@ -165,7 +173,9 @@ impl fetcher::Fetcher for Fetcher {
|
||||||
None => folder.to_string(),
|
None => folder.to_string(),
|
||||||
};
|
};
|
||||||
let folder_pathbuf = PathBuf::from(interpolated_folder);
|
let folder_pathbuf = PathBuf::from(interpolated_folder);
|
||||||
for file in all_cheat_files(&folder_pathbuf) {
|
let cheat_files = all_cheat_files(&folder_pathbuf);
|
||||||
|
debug!("read cheat files in `{folder_pathbuf:?}`: {cheat_files:#?}");
|
||||||
|
for file in cheat_files {
|
||||||
self.files.borrow_mut().push(file.clone());
|
self.files.borrow_mut().push(file.clone());
|
||||||
let index = self.files.borrow().len() - 1;
|
let index = self.files.borrow().len() - 1;
|
||||||
let read_file_result = {
|
let read_file_result = {
|
||||||
|
@ -180,6 +190,7 @@ impl fetcher::Fetcher for Fetcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("FilesystemFetcher = {self:#?}");
|
||||||
Ok(found_something)
|
Ok(found_something)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,4 +291,12 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(expected, cheats.to_string_lossy().to_string())
|
assert_eq!(expected, cheats.to_string_lossy().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(target_family = "windows")]
|
||||||
|
fn multiple_paths() {
|
||||||
|
let p = r#"C:\Users\Administrator\AppData\Roaming\navi\config.yaml"#;
|
||||||
|
let paths = &[p; 2].join(JOIN_SEPARATOR);
|
||||||
|
assert_eq!(paths_from_path_param(paths).collect::<Vec<_>>(), [p; 2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,11 +152,13 @@ impl FinderChoice {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let child = command
|
command
|
||||||
.env("SHELL", CONFIG.finder_shell())
|
.env("SHELL", CONFIG.finder_shell())
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped());
|
||||||
.spawn();
|
debug!(cmd = ?command);
|
||||||
|
|
||||||
|
let child = command.spawn();
|
||||||
|
|
||||||
let mut child = match child {
|
let mut child = match child {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
// #[macro_use]
|
|
||||||
// extern crate anyhow;
|
|
||||||
|
|
||||||
mod clients;
|
mod clients;
|
||||||
mod commands;
|
mod commands;
|
||||||
|
@ -16,4 +14,4 @@ mod prelude;
|
||||||
mod structures;
|
mod structures;
|
||||||
mod welcome;
|
mod welcome;
|
||||||
|
|
||||||
pub use commands::handle;
|
pub use {commands::handle, filesystem::default_config_pathbuf};
|
||||||
|
|
Loading…
Add table
Reference in a new issue