~evan-hoose/SSSSS

ref: 1c864b1bdf031d4d810fb77ad2d1de45d96d2a1a SSSSS/s5-render.rs -rw-r--r-- 4.6 KiB
1c864b1bEvan On branch master 1 year, 2 months ago
                                                                                
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
use std::ffi::OsStr;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

fn main() {
    //This is the path to the file that we use as the document header.
    let document_header = fs::canonicalize("./document-header.html").unwrap();
    //use the absolute path for the current directory
    render(fs::canonicalize("./").unwrap(), document_header);
}

//render() will descend through the directory structure, rendering *.md to
//index.html as it goes.
//
//Didn't think I needed to say this, but I apparently forgot.
//
//THIS CODE USES RECURSION.
//
//IT WON'T WORK IF YOU PUT IT IN main(). Stupid.
fn render(directory: PathBuf,mut document_header: PathBuf) {
    
    //iterate over files in the current directory. We call clone on directory
    //so that we can use it again while testing for new header files.
    for name in fs::read_dir(directory.clone()).unwrap() {
        //Check if there is a file called document-header.html in the current
        //directory. If so, use it instead of the one at the top.
        //Subdirectories will inherit the new document-header.
        //
        //This functionality is so that tabbing can be implemented 
        //automatically. See README.md at https://git.sr.ht/~evan-hoose/sssss
        //for more details/usage warnings.
        for file in fs::read_dir(directory.clone()).unwrap() {
            //do this here so we don't have to do it every time below.
            let file = file.unwrap();
            let file_path = PathBuf::from(file.path());
            //Create a PathBuf of the file name of file_path. This calls clone 
            //so that we can just set document_header to file_path if the name 
            //matches.
            let file_name = &file_path.file_name();
            if Some(OsStr::new("document-header.html")) == *file_name {
                document_header = file_path;
            }
        }

        //returns a pathbuf for whatever file we are on
        let path = PathBuf::from(name.unwrap().path());
        //Let us find the metadata for path, so that we can later test if it's
        //a directory or some other kind of file.
        let file_metadata = fs::metadata(path.as_path()).unwrap();
        let file_type = file_metadata.file_type();

        //If it's a dir, continue down. Otherwise, if it's an md file, render
        //it to html, while using the headers and footers at the top.
        //
        //Also, skip the .git directory. It breaks the attempts to look at file
        //metadata. Yes, I really should just write error handling. However,
        //I'm stupid and can't figure it out.
        if file_type.is_dir() && path.clone().as_os_str() != OsStr::new(".git") {
            render(path, document_header.clone()) //If the path is a dir, continue down.
        } else {
            //If it's not a dir, it must be a file
            if path.extension() == Some(OsStr::new("md")) {
                //leads to index.html in the same directory as path
                //We declare it here instead of above, because why use it before we
                //need it.
                let mut write_path = path.clone();
                write_path.set_file_name("index.html");
                let markdown_path = path.as_path();

                //Shell magic. shell() takes an &str and executes it as if it
                //were being run in the systems /bin/sh. May make it work for
                //Windows some day, but I don't care that much.

                //cat ./html-header.html > $write_path
                let append_html_header =
                    format!("cat ./html-header.html > {}", write_path.display());
                shell(&append_html_header);
                //cat ./document-header.html >> $write_path
                let append_doc_header =
                    format!("cat {} >> {}", document_header.display(), write_path.display());
                shell(&append_doc_header);
                //markdown $markdown_path >> $write_path
                let append_markdown = format!(
                    "markdown {} >> {}",
                    markdown_path.display(),
                    write_path.display()
                );
                shell(&append_markdown);
                //cat ./document-footer.html >> $write_path
                let append_footer =
                    format!("cat ./document-footer.html >> {}", write_path.display());
                shell(&append_footer);
            }
        }
    } //This is where the for loop ends
}

fn shell(command: &str) {
    let _status = Command::new("/bin/sh")
        .arg("-c")
        .arg(&command)
        .status()
        .expect("Unable to execute shell");

}