added function to wrap debug messages in an echo command

implemented formatted printing of stack and bookmarks
This commit is contained in:
2024-12-15 00:35:09 +01:00
parent c27089124e
commit 77cd64dd60
9 changed files with 234 additions and 95 deletions
+2
View File
@@ -5,5 +5,7 @@ edition = "2021"
[dependencies]
clap = { version = "4.5.0", features = ["derive"] }
dirs = "5.0.1"
serde = { version = "1.0.216", features = [ "std", "derive" ] }
sysinfo = "0.32.0"
toml = "0.8.19"
+3 -4
View File
@@ -1,3 +1,6 @@
#![allow(dead_code)]
#![allow(non_camel_case_types)]
use clap::{Args, Parser, Subcommand};
use std::path::PathBuf;
@@ -15,7 +18,6 @@ pub struct Arguments {
}
#[derive(Debug, Clone, Subcommand)]
#[allow(non_camel_case_types)]
pub enum Action {
/// navigate to path and add current path to the stack
push(PushArgs),
@@ -55,7 +57,6 @@ pub struct PopArgs {
}
#[derive(Debug, Clone, Subcommand)]
#[allow(non_camel_case_types)]
pub enum PopAction {
/// pop all entries and move to first entry in stack
all,
@@ -77,7 +78,6 @@ pub struct StackArgs {
}
#[derive(Debug, Clone, Subcommand)]
#[allow(non_camel_case_types)]
pub enum StackAction {
/// clear stack
clear(EmptyArgs),
@@ -94,7 +94,6 @@ pub struct BookmarkArgs {
}
#[derive(Debug, Clone, Subcommand)]
#[allow(non_camel_case_types)]
pub enum BookmarkAction {
/// list all bookmarks
list(EmptyArgs),
+54 -17
View File
@@ -9,7 +9,9 @@ use std::io::{Error, Result};
use std::path::PathBuf;
use std::str::FromStr;
use crate::{RESET_SEQ, STYLES};
use crate::make_padding_string;
use super::{apply_format, config::*};
#[derive(Debug, Clone)]
pub struct Bookmarks {
@@ -80,23 +82,15 @@ impl Bookmarks {
Ok(())
}
/// writes the bookmarks file
fn write_bookmark_file(&self) -> Result<()> {
let mut file_content = String::new();
for (mark, path) in self.bookmarks.iter() {
file_content.push_str(&format!("{}={}\n", mark, path.to_str().unwrap()));
/// returns path of bookmark if it exists
pub fn get_path_by_name(&mut self, name: &str) -> Result<PathBuf> {
match self.bookmarks.get(name) {
Some(value) => Ok(value.to_owned()),
None => Err(Error::other(format!(
"-- bookmark with name `{}` does not exist",
name
))),
}
let mut path = self.conf_dir.clone();
path.push(Self::BOOKMARK_FILE_NAME);
fs::write(path, file_content)?;
Ok(())
}
/// returns a mutable reference to self.bookmarks
pub fn get_bookmarks(&mut self) -> &mut HashMap<String, PathBuf> {
&mut self.bookmarks
}
/// adds a key/value pair to bookmarks and writes the bookmarks file
@@ -124,4 +118,47 @@ impl Bookmarks {
}
Ok(())
}
/// formats and prints bookmarks to string
pub fn to_formatted_string(&self, config: &Settings) -> Result<String> {
let mut buffer = String::new();
if self.bookmarks.is_empty() {
buffer.push_str("-- there are no bookmarks defined");
} else {
let max_name_len = match self.bookmarks.keys().map(String::len).max() {
Some(value) => value,
None => return Err(Error::other("-- failed to determine maximum bookmark name length")),
};
for (mark, path) in &self.bookmarks {
let padding = make_padding_string(max_name_len - mark.len());
let name = apply_format(mark, &config.styles.bookmarks_name);
let separator = apply_format(
&config.format.bookmarks_separator,
&config.styles.bookmarks_seperator,
);
let path = apply_format(path.to_str().unwrap(), &config.styles.bookmarks_path);
if config.format.align_separators {
buffer.push_str(&format!("{}{}{}{}\n", name, padding, separator, path));
} else {
buffer.push_str(&format!("{}{}{}{}\n", name, separator, padding, path));
}
}
}
Ok(buffer)
}
/// writes the bookmarks file
fn write_bookmark_file(&self) -> Result<()> {
let mut file_content = String::new();
for (mark, path) in self.bookmarks.iter() {
file_content.push_str(&format!("{}={}\n", mark, path.to_str().unwrap()));
}
let mut path = self.conf_dir.clone();
path.push(Self::BOOKMARK_FILE_NAME);
fs::write(path, file_content)?;
Ok(())
}
}
+105 -41
View File
@@ -1,54 +1,54 @@
#![allow(dead_code)]
//! handle the config file and bookmarks stored
//! in said config file
use crate::format::*;
use dirs::config_dir;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io::{Error, Result};
use std::path::PathBuf;
use std::env::var;
use std::fs;
use std::str::FromStr;
use toml::{from_str, Table};
use crate::{RESET_SEQ, STYLES};
#[derive(Debug, Clone)]
pub struct Config {
conf_dir: PathBuf,
conf_file: PathBuf,
pub settings: Settings,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct Settings {
pub general: GeneralSettings,
pub format: FormatSettings,
pub styles: StyleSettings,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct GeneralSettings {
pub show_stack_on_push: bool,
pub show_stack_on_pop: bool,
pub show_stack_on_bookmark: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct FormatSettings {
pub stack_separator: String,
pub bookmarks_separator: String,
pub align_separators: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
#[serde(default)]
pub struct StyleSettings {
pub stack_number: String,
pub stack_separator: String,
pub stack_path: String,
pub bookmarks_key: String,
pub bookmarks_name: String,
pub bookmarks_seperator: String,
pub bookmarks_path: String,
pub reset: String,
}
impl Config {
@@ -57,7 +57,7 @@ impl Config {
/// generates and populates a new instance of Config
pub fn new() -> Result<Self> {
let mut config = Config {
conf_dir: PathBuf::new(),
conf_file: PathBuf::new(),
settings: Settings {
general: GeneralSettings {
show_stack_on_push: false,
@@ -65,47 +65,111 @@ impl Config {
show_stack_on_bookmark: false,
},
format: FormatSettings {
bookmarks_separator: " - ".to_owned(),
stack_separator: " - ".to_owned(),
bookmarks_separator: String::new(),
stack_separator: String::new(),
align_separators: false,
},
styles: StyleSettings {
stack_number: "".to_owned(),
stack_separator: "".to_owned(),
stack_path: "".to_owned(),
bookmarks_key: "".to_owned(),
bookmarks_seperator: "".to_owned(),
bookmarks_path: "".to_owned(),
reset: RESET_SEQ.to_owned(),
stack_number: String::new(),
stack_separator: String::new(),
stack_path: String::new(),
bookmarks_name: String::new(),
bookmarks_seperator: String::new(),
bookmarks_path: String::new(),
},
},
};
// get home directory path
let home_dir = match var("HOME") {
Ok(value) => value,
Err(error) => return Err(Error::other(error.to_string())),
// get configuration directory
config.conf_file = match config_dir() {
Some(value) => value,
None => {
return Err(Error::other(
"-- failed to retrieve configuration directory",
))
}
};
// create PathBuf object from home dir path
config.conf_dir = match PathBuf::from_str(&home_dir) {
Ok(value) => value,
Err(error) => return Err(Error::other(error.to_string())),
};
// expand home directory path to get configuration directory path
config.build_config()?;
// expand path to configuration file
config
.conf_file
.push(format!("navigate/{}", Self::CONFIG_FILE_NAME));
// parse configuration file and populate config struct
config.build_settings()?;
config.set_default_settings()?;
config.write_config_file()?;
Ok(config)
}
/// formats and prints config to string
pub fn to_formatted_string(&self) -> Result<String> {
let mut buffer = String::new();
buffer = format!("{:#?}", self.settings);
Ok(buffer)
}
/// write configuration file to save changed settings
pub fn write_config_file(&self) -> Result<()> {
let conf_str = match toml::to_string(&self.settings) {
Ok(value) => value,
Err(error) => return Err(Error::other(error.to_string())),
};
fs::write(self.conf_file.clone(), conf_str)
}
/// reads and parses the configuration file
fn build_config(&mut self) -> Result<()> {
let config_file = match fs::read_to_string(&self.conf_dir) {
fn build_settings(&mut self) -> Result<()> {
if !self.conf_file.is_file() {
return Ok(());
}
let config_str = match fs::read_to_string(&self.conf_file) {
Ok(value) => value,
Err(error) => return Err(error),
};
let conf_table = match config_file.parse::<Table>() {
self.settings = match toml::from_str(&config_str) {
Ok(value) => value,
Err(error) => return Err(Error::other(error.to_string())),
};
Ok(())
}
/// sets defaults for settings not found in the configuration file
fn set_default_settings(&mut self) -> Result<()> {
let default_separator = " - ".to_owned();
let default_number_color =
generate_style_sequence(None, Some(COLORS.fg.default), Some(COLORS.bg.default));
let default_separator_color =
generate_style_sequence(None, Some(COLORS.fg.cyan), Some(COLORS.bg.default));
let default_path_color =
generate_style_sequence(None, Some(COLORS.fg.default), Some(COLORS.bg.default));
if self.settings.format.stack_separator.is_empty() {
self.settings.format.stack_separator = default_separator.clone();
}
if self.settings.format.bookmarks_separator.is_empty() {
self.settings.format.bookmarks_separator = default_separator.clone();
}
if self.settings.styles.stack_number.is_empty() {
self.settings.styles.stack_number = default_number_color.clone();
}
if self.settings.styles.stack_separator.is_empty() {
self.settings.styles.stack_separator = default_separator_color.clone();
}
if self.settings.styles.stack_path.is_empty() {
self.settings.styles.stack_path = default_path_color.clone();
}
if self.settings.styles.bookmarks_name.is_empty() {
self.settings.styles.bookmarks_name = default_number_color.clone();
}
if self.settings.styles.bookmarks_seperator.is_empty() {
self.settings.styles.bookmarks_seperator = default_separator_color.clone();
}
if self.settings.styles.bookmarks_path.is_empty() {
self.settings.styles.bookmarks_path = default_path_color.clone();
}
Ok(())
}
}
+4
View File
@@ -0,0 +1,4 @@
pub fn debug_print(string: &str) {
println!("echo '{}' && ", string);
}
+15 -2
View File
@@ -1,3 +1,5 @@
#![allow(dead_code)]
pub const ESC: &str = "\x1B";
pub const PREFIX: &str = "\x1B[";
pub const RESET_ARG: &str = "0";
@@ -105,6 +107,11 @@ pub enum ColorContext {
Background,
}
/// prepends input with style string and appends the reset sequence at the end
pub fn apply_format(input: &str, style: &str) -> String {
format!("{}{}{}", style, input, RESET_SEQ)
}
/// generates a common style sequence of format
/// `\x1B[<styles>;<foreground-color>;<background-color>m`
/// all elements are optional, if none is supplied the function returns an error
@@ -131,7 +138,7 @@ pub fn generate_style_sequence(
}
// panic if no arguments provided since this is a programming mistake
// which should not
// which should not
if arguments.is_empty() {
panic!("no arguments provided to 'generate_style_sequence()'");
}
@@ -157,7 +164,7 @@ pub fn generate_256color_sequence(context: ColorContext, color: u8) -> String {
/// generates a rgb color sequence
/// **note**: not all terminal emulators support rgb colors
///
///
/// rgb sequences are built the same as 256 color sequences:
/// `\x1B[<context>;2;<r>;<g>;<b>m`
/// where *context* is either '38' or '48' for foreground and background respectively
@@ -174,3 +181,9 @@ pub fn generate_rgb_sequence(context: ColorContext, red: u8, green: u8, blue: u8
sequence.push_str(&format!("{red};{green};{blue}m"));
sequence
}
/// generates a padding string for numbers in a list
pub fn make_padding_string(len: usize) -> String {
// determine padding needed to align the paths
String::from_utf8(vec![b' '; len]).unwrap()
}
+16 -13
View File
@@ -3,6 +3,7 @@ mod format;
mod config;
mod bookmarks;
mod stack;
mod debug;
use arguments::*;
use clap::Parser;
@@ -54,6 +55,7 @@ fn main() -> Result<()> {
Action::pop(pop_args) => handle_pop(&pop_args, &config, &mut stack),
Action::stack(stack_args) => handle_stack(&stack_args, &config, &mut stack),
Action::bookmark(bookmark_args) => handle_bookmark(&bookmark_args, &config, &mut bookmarks, &mut stack),
// Action::config(config_args) => handle_config(&config_args, &config),
};
if res.is_err() {
@@ -108,11 +110,11 @@ fn handle_pop(args: &PopArgs, _config: &Config, stack: &mut Stack) -> Result<()>
fn handle_stack(args: &StackArgs, config: &Config, stack: &mut Stack) -> Result<()> {
if args.stack_action.is_some() {
match args.stack_action.clone().unwrap() {
StackAction::clear(_) => return stack.clear_stack(config),
StackAction::clear(_) => return stack.clear_stack(&config.settings),
}
}
// retrieve stack
let output: String = stack.to_string(None)?;
let output: String = stack.to_formatted_string(&config.settings)?;
print!("echo '{}'", output);
Ok(())
}
@@ -125,12 +127,9 @@ fn handle_bookmark(args: &BookmarkArgs, config: &Config, bookmarks: &mut Bookmar
BookmarkAction::add(args) => add_bookmarks(args, config, bookmarks)?,
BookmarkAction::remove(args) => remove_bookmarks(args, config, bookmarks)?,
};
} else if args.name.is_some() {
let path = match bookmarks.get_bookmarks().get(args.name.as_ref().unwrap()) {
Some(value) => value,
None => return Err(Error::other("-- requested bookmark does not exist")),
};
push_path(path, stack)?;
} else if args.name.is_some() { // handle `change to bookmark`
let path = bookmarks.get_path_by_name(args.name.as_ref().unwrap())?;
push_path(&path, stack)?;
} else {
return Err(Error::other(
"-- provide either a `subcommand` or a `bookmark name`",
@@ -139,12 +138,16 @@ fn handle_bookmark(args: &BookmarkArgs, config: &Config, bookmarks: &mut Bookmar
Ok(())
}
// fn handle_config(args: &ConfigArgs, config: &Config) -> Result<()> {
// match args {
// ConfigAction::show => println!("echo '{}'", config.to_formatted_string()),
// }
// Ok(())
// }
fn list_bookmarks(config: &Config, bookmarks: &mut Bookmarks) -> Result<()> {
let mut buffer = String::new();
for (mark, path) in bookmarks.get_bookmarks() {
buffer.push_str(&format!("{} : {}\n", mark, path.to_str().unwrap()));
}
println!("echo '{}'", buffer);
let output = bookmarks.to_formatted_string(&config.settings)?;
println!("echo '{}'", output);
Ok(())
}
+32 -15
View File
@@ -1,4 +1,5 @@
use super::config::*;
#![allow(dead_code)]
use std::fs;
use std::fs::File;
use std::io::{Error, Result};
@@ -6,6 +7,10 @@ use std::path::{Path, PathBuf};
use std::str::FromStr;
use sysinfo::{Pid, System};
use crate::make_padding_string;
use super::{apply_format, config::*};
#[derive(Debug, Clone)]
pub struct Stack {
pid: u32,
@@ -25,25 +30,37 @@ impl Stack {
Ok(stack)
}
// return stack
pub fn to_string(&self, _settings: Option<Settings>) -> Result<String> {
// formats and prints stack to string
pub fn to_formatted_string(&self, config: &Settings) -> Result<String> {
let mut buffer: String = "".to_string();
if self.stack.is_empty() {
return Err(Error::other("-- the stack is empty"));
buffer.push_str("-- the stack is empty");
} else {
// print stack to string
let max_num_len = self.stack.len().to_string().len();
for (n, item) in self.stack.iter().rev().enumerate() {
let padding = make_padding_string(max_num_len - n.to_string().len());
let number = apply_format(&n.to_string(), &config.styles.stack_number);
let separator = apply_format(
&config.format.stack_separator,
&config.styles.stack_separator,
);
let path = apply_format(item.to_str().unwrap(), &config.styles.stack_path);
if config.format.align_separators {
buffer.push_str(&format!("{}{}{}{}\n", number, padding, separator, path));
} else {
buffer.push_str(&format!("{}{}{}{}\n", number, separator, padding, path));
}
}
}
// print stack to string
let mut output: String = "".to_string();
for (n, item) in self.stack.iter().rev().enumerate() {
output.push_str(&format!("'{} - {}'\n", n, item.to_str().unwrap()));
}
Ok(output)
Ok(buffer)
}
/// clear stack by deleting the associated stack file
pub fn clear_stack(&mut self, _config: &Config) -> Result<()> {
pub fn clear_stack(&mut self, config: &Settings) -> Result<()> {
fs::remove_file(self.path.clone())?;
print!(
"echo stack cleared successfully.'"
);
print!("echo 'stack cleared successfully.'");
Ok(())
}
@@ -172,4 +189,4 @@ impl Stack {
Ok(())
}
} // end `impl database`
}
+3 -3
View File
@@ -5,8 +5,8 @@
- [x] drop stack
- [ ] config file
- [ ] dedup stack option
- [ ] parse config file
- [ ] apply config
- [ ] parse config file -- partially done, handling of colors to be fixed
- [ ] apply config -- partially done
- [ ] colored output > make it configurable through config file
- [ ] setting for separator string when displaying stack/bookmarks
- [x] setting for separator string when displaying stack/bookmarks
- [x] bookmarks