diff --git a/RELEASING.md b/RELEASING.md index 6eb868ce..16cb4e24 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -14,6 +14,9 @@ Update version numbers: $ vim Cargo.toml $ cargo update -p tealdeer +For release 1.7.0: Remove this note and uncomment warning in +`docs/src/usage_custom_pages.md`. + Update docs: $ cargo run -- --help > docs/src/usage.txt diff --git a/docs/src/usage_custom_pages.md b/docs/src/usage_custom_pages.md index d3d1e81a..87344d7d 100644 --- a/docs/src/usage_custom_pages.md +++ b/docs/src/usage_custom_pages.md @@ -1,5 +1,16 @@ # Custom Pages and Patches + + Tealdeer allows creating new custom pages, overriding existing pages as well as extending existing pages. @@ -15,28 +26,28 @@ file](config_directories.html). To document internal command line tools, or if you want to replace an existing tldr page with one that's better suited for you, place a file with the name -`.page` in the custom pages directory. When calling `tldr `, +`.page.md` in the custom pages directory. When calling `tldr `, your custom page will be shown instead of the upstream version in the cache. Path: - $CUSTOM_PAGES_DIR/.page + $CUSTOM_PAGES_DIR/.page.md Example: - ~/.local/share/tealdeer/pages/ufw.page + ~/.local/share/tealdeer/pages/ufw.page.md ## Custom Patches Sometimes you don't want to fully replace an existing upstream page, but just want to extend it with your own examples that you frequently need. In this -case, use a file called `.patch`, it will be appended to existing +case, use a file called `.patch.md`, it will be appended to existing pages. Path: - $CUSTOM_PAGES_DIR/.patch + $CUSTOM_PAGES_DIR/.patch.md Example: - ~/.local/share/tealdeer/pages/ufw.patch + ~/.local/share/tealdeer/pages/ufw.patch.md diff --git a/src/cache.rs b/src/cache.rs index aa64f5ed..48be75e8 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -13,7 +13,7 @@ use reqwest::{blocking::Client, Proxy}; use walkdir::{DirEntry, WalkDir}; use zip::ZipArchive; -use crate::types::PlatformType; +use crate::{types::PlatformType, utils::print_warning}; pub static TLDR_PAGES_DIR: &str = "tldr-pages"; static TLDR_OLD_PAGES_DIR: &str = "tldr-master"; @@ -21,6 +21,7 @@ static TLDR_OLD_PAGES_DIR: &str = "tldr-master"; #[derive(Debug)] pub struct Cache { cache_dir: PathBuf, + enable_styles: bool, } #[derive(Debug)] @@ -85,12 +86,13 @@ pub enum CacheFreshness { } impl Cache { - pub fn new

(cache_dir: P) -> Self + pub fn new

(cache_dir: P, enable_styles: bool) -> Self where P: Into, { Self { cache_dir: cache_dir.into(), + enable_styles, } } @@ -232,7 +234,7 @@ impl Cache { .find(|path| path.exists() && path.is_file()) } - /// Look up custom patch (.patch). If it exists, store it in a variable. + /// Look up custom patch (.patch.md). If it exists, store it in a variable. fn find_patch(patch_name: &str, custom_pages_dir: Option<&Path>) -> Option { custom_pages_dir .map(|custom_dir| custom_dir.join(patch_name)) @@ -248,8 +250,8 @@ impl Cache { platforms: &[PlatformType], ) -> Option { let page_filename = format!("{name}.md"); - let patch_filename = format!("{name}.patch"); - let custom_filename = format!("{name}.page"); + let patch_filename = format!("{name}.patch.md"); + let custom_filename = format!("{name}.page.md"); // Determine directory paths let pages_dir = self.pages_dir(); @@ -264,8 +266,11 @@ impl Cache { }) .collect(); - // Look up custom page (.page). If it exists, return it directly + // Look up custom page (.page.md). If it exists, return it directly if let Some(config_dir) = custom_pages_dir { + // TODO: Remove this check 1 year after version 1.7.0 was released + self.check_for_old_custom_pages(config_dir); + let custom_page = config_dir.join(custom_filename); if custom_page.exists() && custom_page.is_file() { return Some(PageLookupResult::with_page(custom_page)); @@ -326,6 +331,15 @@ impl Cache { .map(str::to_string) }; + let to_stem_custom = |entry: DirEntry| -> Option { + entry + .path() + .file_name() + .and_then(OsStr::to_str) + .and_then(|s| s.strip_suffix(".page.md")) + .map(str::to_string) + }; + // Recursively walk through common and (if applicable) platform specific directory let mut pages = WalkDir::new(platforms_dir) .min_depth(1) // Skip root directory @@ -344,8 +358,12 @@ impl Cache { if let Some(custom_pages_dir) = custom_pages_dir { let is_page = |entry: &DirEntry| -> bool { - let extension = entry.path().extension().unwrap_or_default(); - entry.file_type().is_file() && extension == "page" + entry.file_type().is_file() + && entry + .path() + .file_name() + .and_then(OsStr::to_str) + .map_or(false, |file_name| file_name.ends_with(".page.md")) }; let custom_pages = WalkDir::new(custom_pages_dir) @@ -354,7 +372,7 @@ impl Cache { .into_iter() .filter_entry(is_page) .filter_map(Result::ok) - .filter_map(to_stem); + .filter_map(to_stem_custom); pages.extend(custom_pages); } @@ -395,6 +413,39 @@ impl Cache { Ok(true) } + + /// Check for old custom pages (without .md suffix) and print a warning. + fn check_for_old_custom_pages(&self, custom_pages_dir: &Path) { + let old_custom_pages_exist = WalkDir::new(custom_pages_dir) + .min_depth(1) + .max_depth(1) + .into_iter() + .filter_entry(|entry| entry.file_type().is_file()) + .any(|entry| { + if let Ok(entry) = entry { + let extension = entry.path().extension(); + if let Some(extension) = extension { + extension == "page" || extension == "patch" + } else { + false + } + } else { + false + } + }); + if old_custom_pages_exist { + print_warning( + self.enable_styles, + &format!( + "Custom pages using the old naming convention were found in {}.\n\ + Please rename them to follow the new convention:\n\ + - `.page` → `.page.md`\n\ + - `.patch` → `.patch.md`", + custom_pages_dir.display() + ), + ); + } + } } /// Unit Tests for cache module @@ -411,8 +462,8 @@ mod tests { fn test_reader_with_patch() { // Write test files let dir = tempfile::tempdir().unwrap(); - let page_path = dir.path().join("test.page"); - let patch_path = dir.path().join("test.patch"); + let page_path = dir.path().join("test.page.md"); + let patch_path = dir.path().join("test.patch.md"); { let mut f1 = File::create(&page_path).unwrap(); f1.write_all(b"Hello\n").unwrap(); @@ -435,7 +486,7 @@ mod tests { fn test_reader_without_patch() { // Write test file let dir = tempfile::tempdir().unwrap(); - let page_path = dir.path().join("test.page"); + let page_path = dir.path().join("test.page.md"); { let mut f = File::create(&page_path).unwrap(); f.write_all(b"Hello\n").unwrap(); diff --git a/src/main.rs b/src/main.rs index 15110e64..66da7a1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -301,7 +301,7 @@ fn main() { } // Instantiate cache. This will not yet create the cache directory! - let cache = Cache::new(&config.directories.cache_dir.path); + let cache = Cache::new(&config.directories.cache_dir.path, enable_styles); // Clear cache, pass through if args.clear_cache { diff --git a/tests/inkscape-v2.patch b/tests/inkscape-v2.patch.md similarity index 100% rename from tests/inkscape-v2.patch rename to tests/inkscape-v2.patch.md diff --git a/tests/lib.rs b/tests/lib.rs index 0afac46d..fa8d19c7 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -84,7 +84,7 @@ impl TestEnv { fn add_page_entry(&self, name: &str, contents: &str) { let dir = self.custom_pages_dir.path(); create_dir_all(dir).unwrap(); - let mut file = File::create(dir.join(format!("{name}.page"))).unwrap(); + let mut file = File::create(dir.join(format!("{name}.page.md"))).unwrap(); file.write_all(contents.as_bytes()).unwrap(); } @@ -92,7 +92,7 @@ impl TestEnv { fn add_patch_entry(&self, name: &str, contents: &str) { let dir = self.custom_pages_dir.path(); create_dir_all(dir).unwrap(); - let mut file = File::create(dir.join(format!("{name}.patch"))).unwrap(); + let mut file = File::create(dir.join(format!("{name}.patch.md"))).unwrap(); file.write_all(contents.as_bytes()).unwrap(); } @@ -798,7 +798,7 @@ fn test_autoupdate_cache() { check_cache_updated(false); } -/// End-end test to ensure .page files overwrite pages in cache_dir +/// End-end test to ensure .page.md files overwrite pages in cache_dir #[test] fn test_custom_page_overwrites() { let testenv = TestEnv::new(); @@ -811,7 +811,7 @@ fn test_custom_page_overwrites() { // Add file that should be ignored to the cache dir testenv.add_entry("inkscape-v2", ""); - // Add .page file to custome_pages_dir + // Add .page.md file to custom_pages_dir testenv.add_page_entry("inkscape-v2", include_str!("inkscape-v2.md")); // Load expected output @@ -825,7 +825,7 @@ fn test_custom_page_overwrites() { .stdout(diff(expected)); } -/// End-End test to ensure that .patch files are appended to pages in the cache_dir +/// End-End test to ensure that .patch.md files are appended to pages in the cache_dir #[test] fn test_custom_patch_appends_to_common() { let testenv = TestEnv::new(); @@ -838,8 +838,8 @@ fn test_custom_patch_appends_to_common() { // Add page to the cache dir testenv.add_entry("inkscape-v2", include_str!("inkscape-v2.md")); - // Add .page file to custome_pages_dir - testenv.add_patch_entry("inkscape-v2", include_str!("inkscape-v2.patch")); + // Add .page.md file to custom_pages_dir + testenv.add_patch_entry("inkscape-v2", include_str!("inkscape-v2.patch.md")); // Load expected output let expected = include_str!("inkscape-patched-no-color.expected"); @@ -852,7 +852,7 @@ fn test_custom_patch_appends_to_common() { .stdout(diff(expected)); } -/// End-End test to ensure that .patch files are not appended to .page files in the custom_pages_dir +/// End-End test to ensure that .patch.md files are not appended to .page.md files in the custom_pages_dir /// Maybe this interaction should change but I put this test here for the coverage #[test] fn test_custom_patch_does_not_append_to_custom() { @@ -868,8 +868,8 @@ fn test_custom_patch_does_not_append_to_custom() { // Add page to the cache dir testenv.add_page_entry("inkscape-v2", include_str!("inkscape-v2.md")); - // Add .page file to custome_pages_dir - testenv.add_patch_entry("inkscape-v2", include_str!("inkscape-v2.patch")); + // Add .page.md file to custom_pages_dir + testenv.add_patch_entry("inkscape-v2", include_str!("inkscape-v2.patch.md")); // Load expected output let expected = include_str!("inkscape-default-no-color.expected");