fixed capitalization issue
This commit is contained in:
parent
99e3eba54a
commit
673013f1fb
@ -2,6 +2,11 @@
|
||||
|
||||
`motd` is a command line utility which outputs a (semi) intelligible, randomly generated message to your standard output.
|
||||
|
||||
```
|
||||
❯ motd -t "$HOME is where the {noun} is."
|
||||
/home/admin is where the dragon is.
|
||||
```
|
||||
|
||||
## Build and Install
|
||||
##### Requirements
|
||||
`git`, `rust`/`rustup`/`cargo`
|
||||
@ -22,7 +27,7 @@ You may remove the cloned directory.
|
||||
|
||||
`motd` is best when customized with your own word pools and templates.
|
||||
|
||||
`motd` will look for a `$HOME/.motdrc`, `$XDG_CONFIG_HOME/.motdrc`, or `$XDG_CONFIG_HOME/motd/motdrc` file and use the settings there as defaults when running `motd` with no flags. If somehow `motd` is configured in a way that would result in an empty word list, it will fallback to the built in defaults.
|
||||
Run `motd -h` to view all options. `motd` will look for a `$HOME/.motdrc`, `$XDG_CONFIG_HOME/.motdrc`, or `$XDG_CONFIG_HOME/motd/motdrc` file and use the settings there as defaults when running `motd` with no flags. If somehow `motd` is configured in a way that would result in an empty word list, it will fallback to the built in defaults.
|
||||
|
||||
```
|
||||
# Example motdrc
|
||||
@ -86,7 +91,7 @@ motd -p adverbs > $XDG_CONFIG_HOME/motd/adverbs
|
||||
motd -p locations > $XDG_CONFIG_HOME/motd/locations
|
||||
```
|
||||
Words are separated by line, meaning you can have multiple words treated as a single unit.\
|
||||
Re-defining a word will not add an additional entry to the word pool.
|
||||
Re-defining a word will not add an additional entry to the word pool.\
|
||||
Lines beginning with a `!` are actively removed from their respective word pool.\
|
||||
Lines beginning with a `#` are ignored as comments.
|
||||
Lines with the format `$()` can be `bash` expressions which are evaluated at runtime.\
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::cli::RcArgs;
|
||||
use crate::words::WordList;
|
||||
use crate::words::{WordType, WORD_TYPES};
|
||||
use crate::words::{WORD_TYPES, WordType};
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
@ -27,7 +27,8 @@ impl Config {
|
||||
let mut templates = Vec::new();
|
||||
let mut template_exclusions = Vec::new();
|
||||
for word_type in WORD_TYPES {
|
||||
let (word_list, exclusion_list) = load_word_list_with_exclusions(&config_dir.join(word_type.name()));
|
||||
let (word_list, exclusion_list) =
|
||||
load_word_list_with_exclusions(&config_dir.join(word_type.name()));
|
||||
if !word_list.is_empty() {
|
||||
match word_type {
|
||||
WordType::Adjective => words.adjectives = Some(word_list),
|
||||
@ -86,21 +87,21 @@ fn load_word_list_with_exclusions(path: &PathBuf) -> (Vec<String>, Vec<String>)
|
||||
let mut words = Vec::new();
|
||||
|
||||
for line in lines {
|
||||
if line.starts_with('!') {
|
||||
// Remove the '!' prefix and add to exclusions
|
||||
exclusions.push(line[1..].to_string());
|
||||
if let Some(stripped_line) = line.strip_prefix('!') {
|
||||
exclusions.push(stripped_line.to_string());
|
||||
} else {
|
||||
words.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out any words that are in the exclusion list
|
||||
let filtered_words = words.into_iter()
|
||||
let filtered_words = words
|
||||
.into_iter()
|
||||
.filter(|word| !exclusions.contains(word))
|
||||
.collect();
|
||||
|
||||
(filtered_words, exclusions)
|
||||
},
|
||||
}
|
||||
Err(_) => (Vec::new(), Vec::new()),
|
||||
}
|
||||
}
|
||||
@ -122,7 +123,7 @@ fn expand_env_vars(text: &str) -> String {
|
||||
Some(v) => v.as_str(),
|
||||
None => return "".to_string(),
|
||||
};
|
||||
env::var(var_name).unwrap_or_else(|_| format!("${{{}}}", var_name))
|
||||
env::var(var_name).unwrap_or_else(|_| format!("${{{var_name}}}"))
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
@ -150,10 +151,10 @@ fn execute_bash_command(command: &str) -> String {
|
||||
if output.status.success() {
|
||||
String::from_utf8_lossy(&output.stdout).trim().to_string()
|
||||
} else {
|
||||
format!("$({})", command)
|
||||
format!("$({command})")
|
||||
}
|
||||
}
|
||||
Err(_) => format!("$({})", command),
|
||||
Err(_) => format!("$({command})"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +176,7 @@ fn is_recursive_command(command: &str) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(command_name) = token.split('/').last() {
|
||||
if let Some(command_name) = token.split('/').next_back() {
|
||||
if command_name == program_name {
|
||||
return true;
|
||||
}
|
||||
@ -191,16 +192,22 @@ pub fn load_rc_file() -> RcArgs {
|
||||
for path in rc_locations {
|
||||
if path.exists() {
|
||||
match fs::read_to_string(&path) {
|
||||
Ok(content) => {
|
||||
match toml::from_str::<RcArgs>(&content) {
|
||||
Ok(content) => match toml::from_str::<RcArgs>(&content) {
|
||||
Ok(rc_args) => return rc_args,
|
||||
Err(e) => {
|
||||
eprintln!("Warning: Failed to parse RC file '{}': {}", path.display(), e);
|
||||
}
|
||||
}
|
||||
eprintln!(
|
||||
"Warning: Failed to parse RC file '{}': {}",
|
||||
path.display(),
|
||||
e
|
||||
);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Warning: Failed to read RC file '{}': {}", path.display(), e);
|
||||
eprintln!(
|
||||
"Warning: Failed to read RC file '{}': {}",
|
||||
path.display(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,7 +234,12 @@ fn get_rc_locations() -> Vec<PathBuf> {
|
||||
locations.push(PathBuf::from(xdg_config).join("motd").join("motdrc"));
|
||||
} else if let Ok(home) = env::var("HOME") {
|
||||
// Fallback to ~/.config/motd/motdrc if XDG_CONFIG_HOME is not set
|
||||
locations.push(PathBuf::from(home).join(".config").join("motd").join("motdrc"));
|
||||
locations.push(
|
||||
PathBuf::from(home)
|
||||
.join(".config")
|
||||
.join("motd")
|
||||
.join("motdrc"),
|
||||
);
|
||||
}
|
||||
|
||||
locations
|
||||
|
||||
@ -27,8 +27,7 @@ impl fmt::Display for GeneratorError {
|
||||
),
|
||||
GeneratorError::CutOffExceeded { attempts, cut_off } => write!(
|
||||
f,
|
||||
"Could not generate a message within {} characters after {} attempts.",
|
||||
cut_off, attempts
|
||||
"Could not generate a message within {cut_off} characters after {attempts} attempts.",
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -95,7 +94,13 @@ pub fn generate_message(arg_words: WordList, args: Args) -> Result<String, Gener
|
||||
};
|
||||
(
|
||||
word_type,
|
||||
build_word_list(defaults, config_words, custom_words, exclusions, args.replace),
|
||||
build_word_list(
|
||||
defaults,
|
||||
config_words,
|
||||
custom_words,
|
||||
exclusions,
|
||||
args.replace,
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@ -155,7 +160,7 @@ pub fn generate_message(arg_words: WordList, args: Args) -> Result<String, Gener
|
||||
if attempts >= MAX_CUTOFF_ATTEMPTS {
|
||||
return Err(GeneratorError::CutOffExceeded {
|
||||
attempts,
|
||||
cut_off: cut_off_len
|
||||
cut_off: cut_off_len,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
21
src/main.rs
21
src/main.rs
@ -36,38 +36,37 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
match word_type.to_lowercase().as_str() {
|
||||
"adjectives" | "adjective" => {
|
||||
for adj in adjectives::ADJECTIVES {
|
||||
println!("{}", adj);
|
||||
println!("{adj}");
|
||||
}
|
||||
}
|
||||
"nouns" | "noun" => {
|
||||
for noun in nouns::NOUNS {
|
||||
println!("{}", noun);
|
||||
println!("{noun}");
|
||||
}
|
||||
}
|
||||
"verbs" | "verb" => {
|
||||
for verb in verbs::VERBS {
|
||||
println!("{}", verb);
|
||||
println!("{verb}");
|
||||
}
|
||||
}
|
||||
"adverbs" | "adverb" => {
|
||||
for adverb in adverbs::ADVERBS {
|
||||
println!("{}", adverb);
|
||||
println!("{adverb}");
|
||||
}
|
||||
}
|
||||
"locations" | "location" => {
|
||||
for location in locations::LOCATIONS {
|
||||
println!("{}", location);
|
||||
println!("{location}");
|
||||
}
|
||||
}
|
||||
"templates" | "template" => {
|
||||
for template in TEMPLATES {
|
||||
println!("{}", template);
|
||||
println!("{template}");
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
eprintln!(
|
||||
"Unknown word type: {}. Valid types are: adjectives, nouns, verbs, adverbs, locations, templates",
|
||||
word_type
|
||||
"Unknown word type: {word_type}. Valid types are: adjectives, nouns, verbs, adverbs, locations, templates",
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
@ -104,13 +103,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let message = generate_message(word_list, args)?;
|
||||
match output {
|
||||
Some(output_path) => {
|
||||
std::fs::write(&output_path, format!("{}\n", message)).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to write to file '{}': {}", output_path, e);
|
||||
std::fs::write(&output_path, format!("{message}\n")).unwrap_or_else(|e| {
|
||||
eprintln!("Failed to write to file '{output_path}': {e}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
}
|
||||
None => {
|
||||
println!("{}", message);
|
||||
println!("{message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -49,11 +49,11 @@ pub fn capitalize_sentences(text: &str, uppercase: bool, lowercase: bool) -> Str
|
||||
if capitalize_next && ch.is_alphabetic() {
|
||||
result.push(ch.to_uppercase().next().unwrap_or(ch));
|
||||
capitalize_next = false;
|
||||
} else if matches!(ch, ' ') {
|
||||
result.push(ch);
|
||||
} else {
|
||||
result.push(ch);
|
||||
if matches!(ch, '.' | '!' | '?') {
|
||||
capitalize_next = true;
|
||||
}
|
||||
capitalize_next = matches!(ch, '.' | '!' | '?');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user