Skip to content

Commit

Permalink
Merge pull request #95 from out-of-cheese-error/feat/nested_tags
Browse files Browse the repository at this point in the history
Feat/nested tags
  • Loading branch information
Ninjani authored Apr 25, 2021
2 parents c01bb2a + 2496113 commit a14fa71
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 9 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Added
- Nested tag support - "parent/child" tags used with the "Tag" hierarchy create nested folders.
- Nested tag support (Issue [#85](https://github.com/out-of-cheese-error/gooseberry/issues/85))
- `gooseberry config kb nested` and `nested_tag` config option to determine pattern to use for nesting tags.
- `parent<nested_tag>child` tags used with the "Tag" hierarchy create nested folders.
- Separate make and index commands, allow filtering annotations in both (
Issue [#90](https://github.com/out-of-cheese-error/gooseberry/issues/90))
- Better and more filtering options (Issue [#92](https://github.com/out-of-cheese-error/gooseberry/issues/92))
Expand Down
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ This demonstrates the interactive search functionality. `Enter` adds a new tag,
* [Page template](#page-template)
* [Grouping annotations into folders and pages](#grouping-annotations-into-folders-and-pages)
* [Sorting annotations within a page](#sorting-annotations-within-a-page)
* [Tags and nesting](#tags-and-nesting)
* [Index link template](#index-link-template)
* [Index filename](#index-filename)
* [Ignoring tags](#ignoring-tags)
Expand Down Expand Up @@ -371,14 +372,25 @@ The available options are:
* Created
* Updated

Multiple sort options can be combined in order of priority e.g. `sort = ["Tag", "Created"]` sorts by tags, then by the date of creation.
Multiple sort options can be combined in order of priority e.g. `sort = ["Tag", "Created"]` sorts by tags, then by the
date of creation.

#### Tags and nesting

`gooseberry config kb nested`

This defines the pattern to use for nesting tags. e.g. if `nested_tag = "/"` then a tag of "parent/child" combined
with `hierarchy = ["Tag"]` would create a "parent" folder with a "child" file inside it.

Commas (",") and semicolons (";") should not be used inside tags as they are used as separators by Gooseberry.

#### Index link template

`gooseberry config kb link`

This configures the index file, which generally contains links to all other pages in the generated knowledge base
(unless `hierarchy=[]` in which case all annotations are rendered on the index page). The template controls how each of these links are rendered.
(unless `hierarchy=[]` in which case all annotations are rendered on the index page). The template controls how each of
these links are rendered.

Available keys:

Expand Down
18 changes: 18 additions & 0 deletions src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::gooseberry::knowledge_base::{
};
use crate::{utils, NAME};

pub static DEFAULT_NESTED_TAG: &str = "/";
pub static DEFAULT_ANNOTATION_TEMPLATE: &str = r#"
### {{id}}
Expand Down Expand Up @@ -98,6 +99,8 @@ pub struct GooseberryConfig {
pub(crate) sort: Option<Vec<OrderBy>>,
/// Define tags to ignore
pub(crate) ignore_tags: Option<Vec<String>>,
/// Define nested tag pattern
pub(crate) nested_tag: Option<String>,
}

/// Main project directory, cross-platform
Expand All @@ -123,6 +126,7 @@ impl Default for GooseberryConfig {
hierarchy: None,
sort: None,
ignore_tags: None,
nested_tag: None,
};
config.make_dirs().unwrap();
config
Expand All @@ -146,12 +150,14 @@ kb_dir = '<knowledge-base folder>'
hierarchy = ['Tag']
sort = ['Created']
ignore_tags = []
nested_tag = {}
annotation_template = '''{}'''
page_template = '''{}'''
index_link_template = '''{}'''
index_name = '{}'
file_extension = '{}'
"#,
DEFAULT_NESTED_TAG,
DEFAULT_ANNOTATION_TEMPLATE,
DEFAULT_PAGE_TEMPLATE,
DEFAULT_INDEX_LINK_TEMPLATE,
Expand Down Expand Up @@ -299,6 +305,7 @@ file_extension = '{}'
self.set_page_template()?;
self.set_index_link_template()?;
self.set_index_name()?;
self.set_nested_tag()?;
self.set_file_extension()?;
self.set_hierarchy()?;
self.set_sort()?;
Expand Down Expand Up @@ -727,6 +734,17 @@ file_extension = '{}'
Ok(())
}

pub fn set_nested_tag(&mut self) -> color_eyre::Result<()> {
self.nested_tag = Some(utils::user_input(
"What pattern should gooseberry use to define nested tags",
Some(self.nested_tag.as_deref().unwrap_or(DEFAULT_NESTED_TAG)),
true,
false,
)?);
self.store()?;
Ok(())
}

pub fn set_file_extension(&mut self) -> color_eyre::Result<()> {
self.file_extension = Some(utils::user_input(
"What extension should gooseberry use for wiki files",
Expand Down
3 changes: 3 additions & 0 deletions src/gooseberry/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ pub enum KbConfigCommand {
Sort,
/// Set which tags to ignore
Ignore,
/// Set string defining nested tags (e.g "/" => parent/child)
Nest,
}

impl ConfigCommand {
Expand Down Expand Up @@ -295,6 +297,7 @@ impl ConfigCommand {
KbConfigCommand::Page => config.set_page_template()?,
KbConfigCommand::Link => config.set_index_link_template()?,
KbConfigCommand::Index => config.set_index_name()?,
KbConfigCommand::Nest => config.set_nested_tag()?,
KbConfigCommand::Extension => config.set_file_extension()?,
KbConfigCommand::Hierarchy => config.set_hierarchy()?,
KbConfigCommand::Sort => config.set_sort()?,
Expand Down
15 changes: 10 additions & 5 deletions src/gooseberry/knowledge_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ pub struct PageTemplate {
fn group_annotations_by_order(
order: OrderBy,
annotations: Vec<AnnotationTemplate>,
nested_tag: Option<&String>,
) -> HashMap<String, Vec<AnnotationTemplate>> {
let mut order_to_annotations = HashMap::new();
match order {
Expand All @@ -173,7 +174,10 @@ fn group_annotations_by_order(
.push(annotation);
} else {
for tag in &annotation.annotation.tags {
let tag = tag.replace("/", path_separator);
let mut tag = tag.to_owned();
if let Some(nested_tag) = nested_tag {
tag = tag.replace(nested_tag, path_separator);
}
order_to_annotations
.entry(tag)
.or_insert_with(Vec::new)
Expand Down Expand Up @@ -290,7 +294,6 @@ impl Gooseberry {
self.make_book(annotations, &kb_dir, make, index).await?;
Ok(())
}

/// Write markdown files for wiki
async fn make_book(
&self,
Expand Down Expand Up @@ -380,9 +383,11 @@ impl Gooseberry {
if make && !folder.exists() {
fs::create_dir(&folder)?;
}
for (new_folder, annotations) in
group_annotations_by_order(order[depth], inner_annotations)
{
for (new_folder, annotations) in group_annotations_by_order(
order[depth],
inner_annotations,
self.config.nested_tag.as_ref(),
) {
(recurse_folder.f)(
recurse_folder,
annotations,
Expand Down
28 changes: 27 additions & 1 deletion tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ hypothesis_group = '{}'
kb_dir = '{}'
hierarchy = ['Tag']
sort = ['Created']
nested_tag = ' : '
annotation_template = '''{}'''
page_template = '''{}'''
index_link_template = '''{}'''
Expand Down Expand Up @@ -448,6 +449,22 @@ async fn make() -> color_eyre::Result<()> {
.tags
.contains(&"test tag5".to_owned()));

// add a nested tag
thread::sleep(duration);
let mut cmd = Command::cargo_bin("gooseberry")?;
cmd.env("GOOSEBERRY_CONFIG", &test_data.config_file)
.arg("tag")
.arg("--tags=test_tag")
.arg("test_tag6 : test_tag7")
.assert()
.success();
assert!(test_data
.hypothesis_client
.fetch_annotation(&test_data.annotations[0].id)
.await?
.tags
.contains(&"test_tag6 : test_tag7".to_owned()));

// make
thread::sleep(duration);
let mut cmd = Command::cargo_bin("gooseberry")?;
Expand Down Expand Up @@ -491,10 +508,19 @@ async fn make() -> color_eyre::Result<()> {
.exists());

// check all tag files
assert!(["test_tag", "test_tag1", "test_tag2", "test tag5"]
assert!(["test_tag", "test_tag1", "test_tag2", "test tag5",]
.iter()
.all(|t| file_names.contains(&format!("{}.md", t))));

// check nested tags
assert!(file_names.contains("test_tag6"));
assert!(test_data
.temp_dir
.path()
.join("kb")
.join("test_tag6")
.join("test_tag7.md")
.exists());
test_data.clear().await?;
Ok(())
}

0 comments on commit a14fa71

Please sign in to comment.