You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: user_actions.rs
    path of file: ./repos/spyglass/crates/shared/src/config
    
    the code of the file until where you have to start completion: use diff::Diff;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use crate::accelerator;
use crate::keyboard::{KeyCode, ModifiersState};
use crate::response::SearchResult;

use super::{Tag, UserAction};

// Defines context specific actions. A context specific action
// is a list of actions that are only valid when the document selected
// matches the defined context.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Diff)]
pub struct ContextActions {
    // Defines what context must be matched for the actions to be valid
    pub context: ContextFilter,
    // The list of actions for this context
    pub actions: Vec<UserActionDefinition>,
}

impl ContextActions {
    // Helper method used to identify if the context contains an actions that should
    // be triggered by the passed in keyboard combination. Note this method does not
    // check to see if the context is valid, just if the key combination matches.
    pub fn contains_trigger(&self, modifiers: &ModifiersState, key: &KeyCode, os: &str) -> bool {
        for action in &self.actions {
            if action.is_triggered(modifiers, key, os) {
                return true;
            }
        }
        false
    }

    // Helper method used to access the action that should be triggered by the passed
    // in key combination. Note this method does not check to see if the context is valid.
    pub fn get_triggered_action(
        &self,
        modifiers: &ModifiersState,
        key: &KeyCode,
        os: &str,
    ) -> Option<UserActionDefinition> {
        for action in &self.actions {
            if action.is_triggered(modifiers, key, os) {
                return Some(action.clone());
            }
        }
        None
    }

    // Helper method used to identify if the context actions are valid based on the
    // passed in search result
    pub fn is_applicable(&self, context: &SearchResult) -> bool {
        let mut current_tags = HashMap::new();
        for (tag, value) in &context.tags {
            current_tags
               
    
    pub fn is_applicable(&self, context: &SearchResult) -> bool {
        let mut current_tags = HashMap::new();
        for (tag, value) in &context.tags {
            current_tags
                .entry(tag.clone())
                .or_insert(Vec::new())
                .push(value.clone());
        }
        // Process exclude tag first to remove unwanted items
        if let Some(exclude_types) = &self.context.exclude_tag_type {
            for tag_type in exclude_types {
                if current_tags.contains_key(tag_type.as_str()) {
                    return false;
                }
            }
        }

        if let Some(exclude_tags) = &self.context.exclude_tag {
            for (tag, value) in exclude_tags {
                if let Some(current_vals) = current_tags.get(tag.as_str()) {
                    if current_vals.contains(value) {
                        return false;
                    }
                }
            }
        }

        let tags_configured = self.context.has_tag_type.is_some() | self.context.has_tag.is_some();
        let mut include: bool = !tags_configured;
        if let Some(tags) = &self.context.has_tag_type {
            for tag in tags {
                if current_tags.contains_key(tag.as_str()) {
                    // The current context has a tag type we are
                    // looking for, set to true and break out of
                    // the loop
                    include |= true;
                    break;
                }
            }
        }

        if !include {
            if let Some(tags) = &self.context.has_tag {
                for (tag, value) in tags {
                    if let Some(current_vals) = current_tags.get(tag.as_str()) {
                        if current_vals.contains(value) {
                            // The current context has a tag we are
                            // looking for, set to true and break out of
                            // the loop
                            include |= true;
                            break;
                        }
                    }
                }
            }
        }

        if let Some(urls) = &self.context.url_like {
            let mut has_url = false;
            for url in urls {
                if url.eq(&context.url) {
                    has_url = true;
                    break;
                }
            }
            // We have urls to check so the context must match
            // one of the urls and any tags that were
            // previously defined
            include &= has_url;
        }
        include
    }