Skip to content

Commit

Permalink
Change custom page files to use a .md extension (#322)
Browse files Browse the repository at this point in the history
* Change custom page files to use a `.md` extension.
* Add a breaking change warning to the documentation for the usage of custom pages.
* Add a temporary check for old custom pages to assist in the migration to the new naming convention.

Co-authored-by: Danilo Bargen <[email protected]>
  • Loading branch information
zedseven and dbrgn authored Feb 15, 2024
1 parent ad69985 commit 17c08f0
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 29 deletions.
3 changes: 3 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 17 additions & 6 deletions docs/src/usage_custom_pages.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Custom Pages and Patches

<!--
TODO: Uncomment when releasing 1.7.0.
> ⚠️ **Breaking change in version 1.7.0:** The file name extension for custom
> pages and patches was changed:
>
> - `<name>.page` → `<name>.page.md`
> - `<name>.patch` → `<name>.patch.md`
>
> If you have custom pages or patches, you need to rename them.
-->

Tealdeer allows creating new custom pages, overriding existing pages as well as
extending existing pages.

Expand All @@ -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
`<command>.page` in the custom pages directory. When calling `tldr <command>`,
`<command>.page.md` in the custom pages directory. When calling `tldr <command>`,
your custom page will be shown instead of the upstream version in the cache.

Path:

$CUSTOM_PAGES_DIR/<command>.page
$CUSTOM_PAGES_DIR/<command>.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 `<command>.patch`, it will be appended to existing
case, use a file called `<command>.patch.md`, it will be appended to existing
pages.

Path:

$CUSTOM_PAGES_DIR/<command>.patch
$CUSTOM_PAGES_DIR/<command>.patch.md

Example:

~/.local/share/tealdeer/pages/ufw.patch
~/.local/share/tealdeer/pages/ufw.patch.md
75 changes: 63 additions & 12 deletions src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ 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";

#[derive(Debug)]
pub struct Cache {
cache_dir: PathBuf,
enable_styles: bool,
}

#[derive(Debug)]
Expand Down Expand Up @@ -85,12 +86,13 @@ pub enum CacheFreshness {
}

impl Cache {
pub fn new<P>(cache_dir: P) -> Self
pub fn new<P>(cache_dir: P, enable_styles: bool) -> Self
where
P: Into<PathBuf>,
{
Self {
cache_dir: cache_dir.into(),
enable_styles,
}
}

Expand Down Expand Up @@ -232,7 +234,7 @@ impl Cache {
.find(|path| path.exists() && path.is_file())
}

/// Look up custom patch (<name>.patch). If it exists, store it in a variable.
/// Look up custom patch (<name>.patch.md). If it exists, store it in a variable.
fn find_patch(patch_name: &str, custom_pages_dir: Option<&Path>) -> Option<PathBuf> {
custom_pages_dir
.map(|custom_dir| custom_dir.join(patch_name))
Expand All @@ -248,8 +250,8 @@ impl Cache {
platforms: &[PlatformType],
) -> Option<PageLookupResult> {
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();
Expand All @@ -264,8 +266,11 @@ impl Cache {
})
.collect();

// Look up custom page (<name>.page). If it exists, return it directly
// Look up custom page (<name>.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));
Expand Down Expand Up @@ -326,6 +331,15 @@ impl Cache {
.map(str::to_string)
};

let to_stem_custom = |entry: DirEntry| -> Option<String> {
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
Expand All @@ -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)
Expand All @@ -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);
}
Expand Down Expand Up @@ -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\
- `<name>.page` → `<name>.page.md`\n\
- `<name>.patch` → `<name>.patch.md`",
custom_pages_dir.display()
),
);
}
}
}

/// Unit Tests for cache module
Expand All @@ -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();
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
File renamed without changes.
20 changes: 10 additions & 10 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ 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();
}

/// Add custom patch entry to the custom_pages_dir
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();
}

Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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();
Expand All @@ -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");
Expand All @@ -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() {
Expand All @@ -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");
Expand Down

0 comments on commit 17c08f0

Please sign in to comment.