Skip to content

Commit e932aea

Browse files
committed
refactoring into lib and bin
1 parent 85d4652 commit e932aea

File tree

3 files changed

+131
-122
lines changed

3 files changed

+131
-122
lines changed

example/.DS_Store

-6 KB
Binary file not shown.

src/docs.rs

Lines changed: 60 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -11,80 +11,13 @@ use nom::types::CompleteStr;
1111
use nom::*;
1212
use nom_locate::{position, LocatedSpan};
1313
use serde::{Deserialize, Serialize};
14-
use std::{collections::HashMap, env, fs, fs::File, path::Path, process::exit};
15-
16-
/// "Main" of bashdoc
17-
pub mod runners {
18-
use super::*;
19-
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
20-
use std::{sync::mpsc::channel, time::Duration};
21-
22-
/// Given the arguments received via CLI from clap, setup and run with requested delimiters, file or directory, etc.
23-
pub fn generate<'a>(matches: &'a ArgMatches<'a>) {
24-
let delims = match matches.subcommand() {
25-
("override", Some(sub_m)) => Delimiters::override_delims(sub_m),
26-
_ => Delimiters::get_delims(),
27-
};
28-
let all_em = start(
29-
&Path::new(matches.value_of("INPUT").expect("directory glob not found")),
30-
delims,
31-
);
32-
if matches.is_present("json") {
33-
write_json(&all_em, matches.value_of("json").unwrap());
34-
} else if matches.is_present("location") {
35-
to_html(
36-
&all_em,
37-
matches.value_of("location"),
38-
matches.value_of("template"),
39-
);
40-
} else {
41-
for doc in &all_em {
42-
if matches.is_present("color") {
43-
printer(doc, true);
44-
} else {
45-
printer(doc, false);
46-
}
47-
}
48-
}
49-
}
50-
51-
/// Given a request to watch files, Call `generate` on file write.
52-
pub fn watcher<'a>(matches: &'a ArgMatches<'a>) {
53-
generate(matches);
54-
let (tx, rx) = channel();
55-
let mut watcher: RecommendedWatcher = match Watcher::new(tx, Duration::from_secs(2)) {
56-
Ok(d) => d,
57-
Err(_) => {
58-
println!("Provided path is invalid");
59-
exit(1);
60-
}
61-
};
62-
let path: String = if cfg!(windows) {
63-
String::from(matches.value_of("INPUT").unwrap())
64-
} else {
65-
matches
66-
.value_of("INPUT")
67-
.unwrap()
68-
.replace("~", home_dir().unwrap().to_str().unwrap())
69-
};
70-
watcher.watch(&path, RecursiveMode::Recursive).unwrap();
71-
println!("Watching for changes in {}...", path);
72-
loop {
73-
match rx.recv() {
74-
Ok(event) => {
75-
generate(&matches);
76-
if let DebouncedEvent::Write(e) = event {
77-
println!(
78-
"Bashdoc updated to match changes to {}.",
79-
e.as_path().file_name().unwrap().to_str().unwrap()
80-
);
81-
}
82-
}
83-
Err(e) => println!("watch error: {:?}", e),
84-
}
85-
}
86-
}
87-
}
14+
use std::{
15+
collections::HashMap,
16+
env, fs,
17+
fs::File,
18+
path::{Path, PathBuf},
19+
process::exit,
20+
};
8821

8922
/// Functions and declarations for general Key,Value Pair
9023
mod kv {
@@ -272,27 +205,18 @@ mod docfile {
272205
/// and adds every line to a `Vec` until the end delimiter.
273206
///
274207
/// A final `Vec` of the collected comment strings is returned.
275-
pub fn get_strings_from_file<'a>(p: &Path, delims: Delimiters) -> Vec<Extracted<'a>> {
276-
let mut f = match File::open(&p) {
277-
Ok(m) => m,
278-
Err(_) => {
279-
println!("Provided path is invalid");
280-
exit(1);
281-
}
282-
};
283-
let mut buffer = String::new();
284-
f.read_to_string(&mut buffer).unwrap();
285-
let used = Box::leak(buffer.into_boxed_str());
286-
// println!("{:#?}", used);
287-
let result = parse_strings_from_file(Span::new(CompleteStr(used)), delims);
288-
// println!("{:#?}", result);
289-
match result {
290-
Ok(r) => r.1,
291-
Err(_) => {
292-
println!("Error parsing {}", p.display());
293-
exit(1);
294-
}
295-
}
208+
pub fn get_strings_from_file<'a>(
209+
p: &Path,
210+
delims: Delimiters,
211+
) -> Result<Vec<Extracted<'a>>, String> {
212+
let mut file = File::open(p).map_err(|e| e.to_string())?;
213+
let mut contents = String::new();
214+
file.read_to_string(&mut contents)
215+
.map_err(|e| e.to_string())?;
216+
let used = Box::leak(contents.into_boxed_str());
217+
let x = parse_strings_from_file(Span::new(CompleteStr(used)), delims)
218+
.map_err(|err| err.to_string())?;
219+
Ok(x.1)
296220
}
297221

298222
/// Given a `Vec<str>` make a `DocFile`
@@ -312,33 +236,49 @@ mod docfile {
312236
all_docs
313237
}
314238

315-
/// Given a file path and delimiters, generate a DocFile for all files requested.
316-
pub fn start(p: &Path, delims: Delimiters) -> Vec<DocFile> {
317-
if p.is_dir() || p.to_str().unwrap().contains('*') {
318-
let pth = if p.to_str().unwrap().contains('~') {
319-
home_dir().unwrap().join(p.strip_prefix("~").unwrap())
320-
} else {
321-
p.to_path_buf()
322-
};
323-
println!("{}", pth.display());
324-
let files: Vec<_> = glob(pth.to_str().unwrap())
239+
fn extract_all_paths(p: &str) -> Result<Vec<PathBuf>, String> {
240+
let as_path = Path::new(p);
241+
let pth = if p.contains('~') {
242+
home_dir().expect("Could not find home directory.").join(
243+
as_path
244+
.strip_prefix("~")
245+
.expect("Could not strip shortcut."),
246+
)
247+
} else {
248+
match as_path.canonicalize() {
249+
Ok(o) => o,
250+
Err(e) => {
251+
println!("{}", e.to_string());
252+
exit(1);
253+
}
254+
}
255+
};
256+
let files: Vec<_> = if p.contains('*') {
257+
glob(pth.to_str().unwrap())
325258
.unwrap()
326259
.filter_map(|x| x.ok())
327-
.collect();
328-
let every_doc: Vec<DocFile> = files
329-
.par_iter()
330-
.map(|entry| {
331-
let docs = get_strings_from_file(&entry, delims);
332-
generate_doc_file(&docs, &entry, delims)
333-
})
334-
.collect();
335-
every_doc
260+
.collect()
336261
} else {
337-
let docs = get_strings_from_file(&p.canonicalize().unwrap(), delims);
338-
let all_docs = generate_doc_file(&docs, &p, delims);
339-
let result = vec![all_docs];
340-
result
341-
}
262+
vec![pth]
263+
};
264+
Ok(files)
265+
}
266+
267+
/// Given a file path and delimiters, generate a DocFile for all files requested.
268+
pub fn start(p: &str, delims: Delimiters) -> Result<Vec<DocFile>, String> {
269+
let x: Vec<PathBuf> = extract_all_paths(p).map_err(|e| e.to_string())?;
270+
Ok(x.par_iter()
271+
.map(|entry| {
272+
let docs = match get_strings_from_file(&entry, delims) {
273+
Ok(o) => o,
274+
Err(e) => {
275+
println!("{}", e.to_string());
276+
exit(1);
277+
}
278+
};
279+
generate_doc_file(&docs, &entry, delims)
280+
})
281+
.collect())
342282
}
343283
}
344284

@@ -480,7 +420,7 @@ mod outputs {
480420
}
481421

482422
/// Functions and declarations for generating/overriding delimiters
483-
mod delims {
423+
pub mod delims {
484424
use super::*;
485425
use std::io::prelude::*;
486426
/// Represents the necessary delimiters for a `bashdoc`

src/main.rs

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@
107107
//! - v0.4.11 - support for overriding global `.bashdocrc` within a directory.
108108
//! - v0.4.12 - descriptors can be split on ':' or whitespace
109109
mod docs;
110-
use crate::docs::runners::*;
111-
use clap::{load_yaml, App};
110+
use crate::docs::delims::override_delims;
111+
use clap::{load_yaml, App, ArgMatches};
112+
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
113+
use std::{sync::mpsc::channel, time::Duration};
112114

113115
fn main() {
114116
let yaml = load_yaml!("../cli.yml");
@@ -119,3 +121,70 @@ fn main() {
119121
generate(&matches);
120122
}
121123
}
124+
125+
/// Given the arguments received via CLI from clap, setup and run with requested delimiters, file or directory, etc.
126+
pub fn generate<'a>(matches: &'a ArgMatches<'a>) {
127+
let delims = match matches.subcommand() {
128+
("override", Some(sub_m)) => override_delims(sub_m),
129+
_ => Delimiters::get_delims(),
130+
};
131+
let all_em = start(
132+
matches.value_of("INPUT").expect("directory glob not found"),
133+
delims,
134+
)
135+
.unwrap();
136+
if matches.is_present("json") {
137+
write_json(&all_em, matches.value_of("json").unwrap());
138+
} else if matches.is_present("location") {
139+
to_html(
140+
&all_em,
141+
matches.value_of("location"),
142+
matches.value_of("template"),
143+
);
144+
} else {
145+
for doc in &all_em {
146+
if matches.is_present("color") {
147+
printer(doc, true);
148+
} else {
149+
printer(doc, false);
150+
}
151+
}
152+
}
153+
}
154+
155+
/// Given a request to watch files, Call `generate` on file write.
156+
pub fn watcher<'a>(matches: &'a ArgMatches<'a>) {
157+
generate(matches);
158+
let (tx, rx) = channel();
159+
let mut watcher: RecommendedWatcher = match Watcher::new(tx, Duration::from_secs(2)) {
160+
Ok(d) => d,
161+
Err(_) => {
162+
println!("Provided path is invalid");
163+
exit(1);
164+
}
165+
};
166+
let path: String = if cfg!(windows) {
167+
String::from(matches.value_of("INPUT").unwrap())
168+
} else {
169+
matches
170+
.value_of("INPUT")
171+
.unwrap()
172+
.replace("~", home_dir().unwrap().to_str().unwrap())
173+
};
174+
watcher.watch(&path, RecursiveMode::Recursive).unwrap();
175+
println!("Watching for changes in {}...", path);
176+
loop {
177+
match rx.recv() {
178+
Ok(event) => {
179+
generate(&matches);
180+
if let DebouncedEvent::Write(e) = event {
181+
println!(
182+
"Bashdoc updated to match changes to {}.",
183+
e.as_path().file_name().unwrap().to_str().unwrap()
184+
);
185+
}
186+
}
187+
Err(e) => println!("watch error: {:?}", e),
188+
}
189+
}
190+
}

0 commit comments

Comments
 (0)