1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use project;
use snippet;
use error::Error;
use error::Error::InternalError;

use std::process::Command;

use std::fs;
use std::path;
use std::fs::File;
use std::io::Write;

#[derive(Debug)]
pub enum OpCode {
    // For the add snippet command
    AddSnippet,
    // For listing snippets
    ListSnippets(bool),
    // For syncing snippets with the server
    SyncSnippets,
}


/// Find the snippets associated with the project
pub fn find_snippets(project: &project::Project) -> Result<Vec<fs::DirEntry>, Error> {

    // Crawl through directory that is set as project root
    let mut res: Vec<fs::DirEntry> = Vec::new();

    // Read the entries in the folder
    for snippet_location in project.locations.iter() {
        println!("Finding snippets in {},", &snippet_location.local.as_str());
        let entries = fs::read_dir(&snippet_location.local)?;

        // For each of the entries
        for e in entries {
            let dir_ent = e?;

            // Get the path
            let path = dir_ent.path();
            // Get the extension
            let ext_opt = path.extension();
            if let Some(ext) = ext_opt {
                if let Some(s) = ext.to_str() {
                    // Add to list if files match extension
                    if s == snippet_location.ext {
                        res.push(dir_ent);
                    }
                }
            }
        }
    }
    Ok(res)
}

/// Load snippets from the dir entries
pub fn load_snippets(dir_entries: &Vec<fs::DirEntry>, keywords: &Vec<String>) -> Result<Vec<snippet::Snippet>, Error>
{
    let mut result: Vec<snippet::Snippet> = Vec::new();
    let keyword_slice = keywords.as_slice();

    // Return snippets
    for entry in dir_entries {
        // Read the file name
        let filename = entry.path();
        // Read the tags
        let tags = snippet::read_tags(entry.path().to_str().unwrap())?;

        // If tag is in the snippet, or no tags are given
        if keyword_slice.len() == 0 || tags.iter().fold(false, |res, tag| (res || keyword_slice.contains(&tag))) {
            result.push(snippet::Snippet::new(filename.to_str().unwrap().to_string(), &tags));
        }
    }
    Ok(result)
}

//// Edit snippets
pub fn edit_snippet(program: &str, full_path: &path::Path) -> Result<(), Error>
{
    let _output = Command::new("vim").
        arg(&full_path).spawn()?.wait_with_output()?;

    Ok(())
}

//// Start the different operation modes
pub fn start_operation(code: &OpCode, project: &project::Project, keywords: Vec<String>, optional_filename: &str) -> Result<Vec<snippet::Snippet>, Error> {

    // Match on operation
    let result = match code {
        OpCode::AddSnippet => {
            // Create the full path
            let full_path = path::Path::new(&project.locations[0].local).join(optional_filename);
            // Create the file
            if full_path.exists() {
                return Err(InternalError("Snippet already exists".to_string()));
            }
            let mut file = File::create(&full_path)?;

            // Write the keywords to the file
            for keyword in &keywords {
                file.write(keyword.as_bytes())?;
                file.write(b",")?;
            }

            // Open vim on location
            edit_snippet("vim", &full_path);

            let snippet = snippet::Snippet::new(full_path.into_os_string().into_string().unwrap(), &keywords);
            Ok(vec![snippet])
        }

        // List snippets
        OpCode::ListSnippets(_) => {
            let files = find_snippets(&project)?;
            let snippets = load_snippets(&files, &keywords)?;

            Ok(snippets)
        }

        // Sync snippets
        OpCode::SyncSnippets => {
            println!("Sync all snippets");
            Ok(vec![])
        }
    };
    result
}