Repository: sharkdp/bat
File: src/assets/build_assets.rs (Rust)

Code before:
    dependencies.sort();
    dependencies.dedup();

    dependencies
}

fn dependencies_from_pattern(pattern: &Pattern) -> Vec<OtherSyntax> {
    match *pattern {
        Pattern::Match(MatchPattern {
            operation: MatchOperation::Push(ref context_references),
            ..
        }) => context_references
            .iter()
            .map(dependency_from_context_reference)
            .collect(),
        Pattern::Include(ref context_reference) => {
            vec![dependency_from_context_reference(context_reference)]
        }
        _ => vec![],
    }
    .into_iter()
    .flatten()
    .collect()
}

/// Removes any subscope from the scope.
///
/// When we track dependencies between syntaxes, we do not want to take
/// subscopes into account, because that interfers with our deduplication of
/// dependencies.
///
/// For example, if a syntax includes another syntax like this:
/// ```yaml
///   - include: scope:source.c++#unique-variables
/// ```
/// we only want to track the dependency on the main scope, i.e. `source.c++`.
fn without_subscope(scope: Scope) -> Scope {
    if let Some(without_subscope) = scope.build_string().split('#').next() {
        Scope::new(without_subscope).expect("extracting main scope must never fail")
    } else {
        scope
    }
}

fn dependency_from_context_reference(context_reference: &ContextReference) -> Option<OtherSyntax> {
    match &context_reference {
        ContextReference::File { ref name, .. } => Some(OtherSyntax::ByName(name.clone())),
        ContextReference::ByScope { ref scope, .. } => {
            Some(OtherSyntax::ByScope(without_subscope(*scope)))
        }
        _ => None,

Review comment (suggestion):
It may be clearer to use syntect terminology here. Maybe, "Removes any context name from the syntax reference"? And then to rename "subscope" elsewhere to "context" (or "subcontext" - without a `#something`, `#main` is implied) 

Code after:
            operation: MatchOperation::Push(ref context_references),
            ..
        }) => context_references
            .iter()
            .map(dependency_from_context_reference)
            .collect(),
        Pattern::Include(ref context_reference) => {
            vec![dependency_from_context_reference(context_reference)]
        }
        _ => vec![],
    }
    .into_iter()
    .flatten()
    .collect()
}

/// To generate a Graphviz dot file of syntax dependencies, do this:
/// ```bash
/// sudo apt install graphviz
/// BAT_SYNTAX_DEPENDENCIES_TO_GRAPHVIZ_DOT_FILE=/tmp/bat-syntax-dependencies.dot cargo run -- cache  --build --source assets --blank --target /tmp
/// dot /tmp/bat-syntax-dependencies.dot -Tpng -o /tmp/bat-syntax-dependencies.png
/// open /tmp/bat-syntax-dependencies.png
/// ```
fn maybe_write_syntax_dependencies_to_graphviz_dot_file(
    other_syntax_lookup: &OtherSyntaxLookup,
    syntax_to_dependencies: &SyntaxToDependencies,
) {
    if let Ok(dot_file_path) = std::env::var("BAT_SYNTAX_DEPENDENCIES_TO_GRAPHVIZ_DOT_FILE") {
        graphviz_utils::try_syntax_dependencies_to_graphviz_dot_file(
            other_syntax_lookup,
            syntax_to_dependencies,
            &dot_file_path,
        );
    }
}

/// Removes any context name from the syntax reference.
///
/// When we track dependencies between syntaxes, we are not interested in
/// dependencies on specific contexts inside other syntaxes. We only care about
/// the dependency on the syntax itself.
///
/// For example, if a syntax includes another syntax like this:
/// ```yaml
///   - include: scope:source.c++#unique-variables
/// ```
/// we only want to track the dependency on `source.c++`.
fn remove_explicit_context(scope: Scope) -> Scope {
    if let Some(without_context) = scope.build_string().split('#').next() {
        Scope::new(without_context).expect("removing context reference must never fail")
    } else {