use crate::{
ScopeIdentity, ScopeSelection, WikiError, indexer, scope as wiki_scope, search, session, store,
};
pub(crate) const DEFAULT_PROJECT_ID: &str = "current";
pub(crate) fn indexed_store_for_selection(
selection: &ScopeSelection,
) -> Result<
(
wiki_scope::ResolvedScope,
ScopeIdentity,
search::SearchScope,
store::MemoryWikiStore,
),
WikiError,
> {
let resolved = resolve_selection_context(selection)?;
let mut store = store::MemoryWikiStore::default();
if resolved.scope.root().is_dir() {
indexer::index_vault(resolved.scope.root(), &mut store)?;
}
Ok((
resolved.scope,
resolved.output_scope,
resolved.search_scope,
store,
))
}
pub(crate) struct ResolvedSelectionContext {
pub(crate) scope: wiki_scope::ResolvedScope,
pub(crate) output_scope: ScopeIdentity,
pub(crate) search_scope: search::SearchScope,
}
pub(crate) fn resolve_selection_context(
selection: &ScopeSelection,
) -> Result<ResolvedSelectionContext, WikiError> {
let scope = resolve_command_scope(selection)?;
let output_scope = resolved_scope_identity(&scope);
let search_scope = search_scope_for_resolved(&scope);
Ok(ResolvedSelectionContext {
scope,
output_scope,
search_scope,
})
}
pub(crate) fn search_scope_for_resolved(scope: &wiki_scope::ResolvedScope) -> search::SearchScope {
match topic_project_precedence(scope.topic_name(), scope.project_id()) {
ScopePrecedence::Topic(topic) => search::SearchScope::topic(topic),
ScopePrecedence::Project(project_id) => search::SearchScope::project(project_id),
ScopePrecedence::DefaultProject => search::SearchScope::project(DEFAULT_PROJECT_ID),
}
}
pub(crate) fn store_scope_for_search(scope: &search::SearchScope) -> store::WikiStoreScope {
match scope {
search::SearchScope::Project { project_id } => store::WikiStoreScope::project(project_id),
search::SearchScope::Topic { topic } => store::WikiStoreScope::topic(topic),
}
}
pub(crate) fn resolve_command_scope(
selection: &ScopeSelection,
) -> Result<wiki_scope::ResolvedScope, WikiError> {
let cwd = std::env::current_dir().map_err(|error| WikiError::Io {
action: "read current directory",
path: None,
source: error,
})?;
wiki_scope::resolve(selection, &cwd)
}
pub(crate) fn research_scope_identity(scope: &session::ResearchScope) -> ScopeIdentity {
match scope {
session::ResearchScope::Project { project_id, .. } => {
ScopeIdentity::project(project_id.clone())
}
session::ResearchScope::Topic { name, .. } => ScopeIdentity::topic(name.clone()),
}
}
pub(crate) fn resolved_scope_identity(scope: &wiki_scope::ResolvedScope) -> ScopeIdentity {
match topic_project_precedence(scope.topic_name(), scope.project_id()) {
ScopePrecedence::Topic(topic) => ScopeIdentity::topic(topic),
ScopePrecedence::Project(project_id) => ScopeIdentity::project(project_id),
ScopePrecedence::DefaultProject => ScopeIdentity::project(DEFAULT_PROJECT_ID),
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ScopePrecedence<'a> {
Topic(&'a str),
Project(&'a str),
DefaultProject,
}
fn topic_project_precedence<'a>(
topic_name: Option<&'a str>,
project_id: Option<&'a str>,
) -> ScopePrecedence<'a> {
if let Some(topic) = topic_name {
return ScopePrecedence::Topic(topic);
}
if let Some(project_id) = project_id {
return ScopePrecedence::Project(project_id);
}
ScopePrecedence::DefaultProject
}