fix(sessions): use custom lists of adjectives and nouns for generating session names (#2122)

* Create custom lists of adjectives and nouns for generating session names

* move word lists to const slices

* add logic to retry name generation

* refactor

 - reuse the name generator
 - iterator instead of for loop

---------

Co-authored-by: Thomas Linford <linford.t@gmail.com>
This commit is contained in:
Kyle Sutherland-Cash 2023-07-18 18:12:51 +01:00 committed by GitHub
parent fa8ef2a973
commit e0bd311e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 170 additions and 3 deletions

View File

@ -2,7 +2,7 @@ use dialoguer::Confirm;
use std::{fs::File, io::prelude::*, path::PathBuf, process}; use std::{fs::File, io::prelude::*, path::PathBuf, process};
use crate::sessions::{ use crate::sessions::{
assert_session, assert_session_ne, get_active_session, get_sessions, assert_session, assert_session_ne, get_active_session, get_name_generator, get_sessions,
get_sessions_sorted_by_mtime, kill_session as kill_session_impl, match_session_name, get_sessions_sorted_by_mtime, kill_session as kill_session_impl, match_session_name,
print_sessions, print_sessions_with_index, session_exists, ActiveSession, SessionNameMatch, print_sessions, print_sessions_with_index, session_exists, ActiveSession, SessionNameMatch,
}; };
@ -93,7 +93,7 @@ pub(crate) fn start_server(path: PathBuf, debug: bool) {
} }
fn create_new_client() -> ClientInfo { fn create_new_client() -> ClientInfo {
ClientInfo::New(names::Generator::default().next().unwrap()) ClientInfo::New(generate_unique_session_name())
} }
fn find_indexed_session( fn find_indexed_session(
@ -446,7 +446,7 @@ pub(crate) fn start_client(opts: CliArgs) {
process::exit(0); process::exit(0);
} }
let session_name = names::Generator::default().next().unwrap(); let session_name = generate_unique_session_name();
start_client_plan(session_name.clone()); start_client_plan(session_name.clone());
start_client_impl( start_client_impl(
Box::new(os_input), Box::new(os_input),
@ -459,3 +459,22 @@ pub(crate) fn start_client(opts: CliArgs) {
} }
} }
} }
fn generate_unique_session_name() -> String {
let sessions = get_sessions();
let Ok(sessions) = sessions else {
eprintln!("Failed to list existing sessions: {:?}", sessions);
process::exit(1);
};
let name = get_name_generator()
.take(1000)
.find(|name| !sessions.contains(name));
if let Some(name) = name {
return name;
} else {
eprintln!("Failed to generate a unique session name, giving up");
process::exit(1);
}
}

View File

@ -219,3 +219,151 @@ pub(crate) fn assert_session_ne(name: &str) {
}; };
process::exit(1); process::exit(1);
} }
/// Create a new random name generator
///
/// Used to provide a memorable handle for a session when users don't specify a session name when the session is
/// created.
///
/// Uses the list of adjectives and nouns defined below, with the intention of avoiding unfortunate
/// and offensive combinations. Care should be taken when adding or removing to either list due to the birthday paradox/
/// hash collisions, e.g. with 4096 unique names, the likelihood of a collision in 10 session names is 1%.
pub(crate) fn get_name_generator() -> impl Iterator<Item = String> {
names::Generator::new(&ADJECTIVES, &NOUNS, names::Name::Plain)
}
const ADJECTIVES: &[&'static str] = &[
"adamant",
"adept",
"adventurous",
"arcadian",
"auspicious",
"awesome",
"blossoming",
"brave",
"charming",
"chatty",
"circular",
"considerate",
"cubic",
"curious",
"delighted",
"didactic",
"diligent",
"effulgent",
"erudite",
"excellent",
"exquisite",
"fabulous",
"fascinating",
"friendly",
"glowing",
"gracious",
"gregarious",
"hopeful",
"implacable",
"inventive",
"joyous",
"judicious",
"jumping",
"kind",
"likable",
"loyal",
"lucky",
"marvellous",
"mellifluous",
"nautical",
"oblong",
"outstanding",
"polished",
"polite",
"profound",
"quadratic",
"quiet",
"rectangular",
"remarkable",
"rusty",
"sensible",
"sincere",
"sparkling",
"splendid",
"stellar",
"tenacious",
"tremendous",
"triangular",
"undulating",
"unflappable",
"unique",
"verdant",
"vitreous",
"wise",
"zippy",
];
const NOUNS: &[&'static str] = &[
"aardvark",
"accordion",
"apple",
"apricot",
"bee",
"brachiosaur",
"cactus",
"capsicum",
"clarinet",
"cowbell",
"crab",
"cuckoo",
"cymbal",
"diplodocus",
"donkey",
"drum",
"duck",
"echidna",
"elephant",
"foxglove",
"galaxy",
"glockenspiel",
"goose",
"hill",
"horse",
"iguanadon",
"jellyfish",
"kangaroo",
"lake",
"lemon",
"lemur",
"magpie",
"megalodon",
"mountain",
"mouse",
"muskrat",
"newt",
"oboe",
"ocelot",
"orange",
"panda",
"peach",
"pepper",
"petunia",
"pheasant",
"piano",
"pigeon",
"platypus",
"quasar",
"rhinoceros",
"river",
"rustacean",
"salamander",
"sitar",
"stegosaurus",
"tambourine",
"tiger",
"tomato",
"triceratops",
"ukulele",
"viola",
"weasel",
"xylophone",
"yak",
"zebra",
];