Struct tpnote_lib::context::Context

source ·
pub struct Context {
    pub path: PathBuf,
    pub dir_path: PathBuf,
    pub root_path: PathBuf,
    /* private fields */
}
Expand description

Tiny wrapper around “Tera context” with some additional information.

Fields§

§path: PathBuf

First positional command line argument.

§dir_path: PathBuf

The directory (only) path corresponding to the first positional command line argument. The is our working directory and the directory where the note file is (will be) located.

§root_path: PathBuf

Contains the root directory of the current note. This is the first directory, that upwards from dir_path, contains a file named FILENAME_ROOT_PATH_MARKER. The root directory is used by Tp-Note’s viewer as base directory

Implementations§

A thin wrapper around tera::Context storing some additional information.

Constructor: path is the first positional command line parameter <path> (see man page). path must point to a directory or a file.

A copy of path is stored in self.ct as key TMPL_VAR_PATH. It directory path as key TMPL_VAR_DIR_PATH.

use std::path::Path;
use tpnote_lib::config::TMPL_VAR_DIR_PATH;
use tpnote_lib::config::TMPL_VAR_PATH;
use tpnote_lib::context::Context;
let mut context = Context::from(&Path::new("/path/to/mynote.md"));

assert_eq!(context.path, Path::new("/path/to/mynote.md"));
assert_eq!(context.dir_path, Path::new("/path/to/"));
assert_eq!(&context.get(TMPL_VAR_PATH).unwrap().to_string(),
            r#""/path/to/mynote.md""#);
assert_eq!(&context.get(TMPL_VAR_DIR_PATH).unwrap().to_string(),
            r#""/path/to""#);

Furthermore, the constructor captures Tp-Note’s environment and stores it as variables in a context collection. The variables are needed later to populate a context template and a filename template.

This function add the keys: TMPL_VAR_EXTENSION_DEFAULT, TMPL_VAR_USERNAME and TMPL_VAR_LANG.

use std::path::Path;
use tpnote_lib::context::Context;
use tpnote_lib::config::TMPL_VAR_EXTENSION_DEFAULT; // `extension_default`
use tpnote_lib::config::FILENAME_EXTENSION_DEFAULT; // usually `md`
let mut context = Context::from(&Path::new("/path/to/mynote.md"));

// For most platforms `context.get("extension_default")` is `md`
assert_eq!(&context.get(TMPL_VAR_EXTENSION_DEFAULT).unwrap().to_string(),
    &format!("\"{FILENAME_EXTENSION_DEFAULT}\""));
Examples found in repository?
src/workflow.rs (line 191)
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
pub fn synchronize_filename<T: Content>(path: &Path) -> Result<PathBuf, NoteError> {
    // Collect input data for templates.
    let context = Context::from(path);

    let content = <T>::open(path).unwrap_or_default();
    let n = synchronize::<T>(context, content)?;

    Ok(n.rendered_filename)
}

#[inline]
/// Create a new note by inserting `Tp-Note`'s environment in a template.
/// If the note to be created exists already, append a so called `copy_counter`
/// to the filename and try to save it again. In case this does not succeed either,
/// increment the `copy_counter` until a free filename is found.
/// The returned path points to the (new) note file on disk.
/// Depending on the context, Tp-Note chooses one `TemplateKind` to operate
/// (c.f. `tpnote_lib::template::TemplateKind::from()`).
/// The `tk-filter` allows to overwrite this choice, e.g. you may set
/// `TemplateKind::None` under certain circumstances. This way the caller
/// can inject command line parameters like `--no-filename-sync`.
/// If `html_export = Some((dir, local_link_kind))`, the function renders
/// the note's content into HTML and saves the `.html` file in the
/// directory `dir`. This optional HTML rendition is performed just before
/// returning and does not affect any above described operation.
///
/// Returns the note's new or existing filename in `<Note>.rendered_filename`.
///
///
/// ## Example with `TemplateKind::FromClipboard`
///
/// ```rust
/// use tpnote_lib::content::Content;
/// use tpnote_lib::content::ContentString;
/// use tpnote_lib::workflow::create_new_note_or_synchronize_filename;
/// use std::env::temp_dir;
/// use std::path::PathBuf;
/// use std::fs;
///
/// // Prepare test.
/// let notedir = temp_dir();
///
/// let clipboard = ContentString::from("my clipboard\n".to_string());
/// let stdin = ContentString::from("my stdin\n".to_string());
/// // This is the condition to choose: `TemplateKind::FromClipboard`:
/// assert!(clipboard.header().is_empty() && stdin.header().is_empty());
/// assert!(!clipboard.body().is_empty() || !stdin.body().is_empty());
/// let template_kind_filer = |tk|tk;
///
/// // Start test.
/// // You can plug in your own type (must impl. `Content`).
/// let n = create_new_note_or_synchronize_filename::<ContentString, _>(
///        &notedir, &clipboard, &stdin, template_kind_filer,
///        &None).unwrap();
/// // Check result.
/// assert!(n.as_os_str().to_str().unwrap()
///    .contains("my stdin-my clipboard--Note"));
/// assert!(n.is_file());
/// let raw_note = fs::read_to_string(n).unwrap();
///
/// #[cfg(not(target_family = "windows"))]
/// assert!(raw_note.starts_with(
///            "\u{feff}---\ntitle:      \"my stdin\\nmy clipboard\\n\""));
/// #[cfg(target_family = "windows")]
/// assert!(raw_note.starts_with(
///            "\u{feff}---\r\ntitle:      \"my stdin"));
/// ```
pub fn create_new_note_or_synchronize_filename<T, F>(
    path: &Path,
    clipboard: &T,
    stdin: &T,
    tk_filter: F,
    html_export: &Option<(PathBuf, LocalLinkKind)>,
) -> Result<PathBuf, NoteError>
where
    T: Content,
    F: Fn(TemplateKind) -> TemplateKind,
{
    // First, generate a new note (if it does not exist), then parse its front_matter
    // and finally rename the file, if it is not in sync with its front matter.

    // Collect input data for templates.
    let mut context = Context::from(path);
    context.insert_content(TMPL_VAR_CLIPBOARD, TMPL_VAR_CLIPBOARD_HEADER, clipboard)?;
    context.insert_content(TMPL_VAR_STDIN, TMPL_VAR_STDIN_HEADER, stdin)?;

    // `template_king` will tell us what to do.
    let (template_kind, content) = TemplateKind::from::<T>(path, clipboard, stdin);
    let template_kind = tk_filter(template_kind);

    let n = match template_kind {
        TemplateKind::New
        | TemplateKind::FromClipboardYaml
        | TemplateKind::FromClipboard
        | TemplateKind::AnnotateFile => {
            // CREATE A NEW NOTE WITH `TMPL_NEW_CONTENT` TEMPLATE
            let mut n = Note::from_content_template(context, template_kind)?;
            n.render_filename(template_kind)?;
            // Check if the filename is not taken already
            n.set_next_unused_rendered_filename()?;
            n.save()?;
            n
        }

        TemplateKind::FromTextFile => {
            let mut n = Note::from_text_file(context, content.unwrap(), template_kind)?;
            // Render filename.
            n.render_filename(template_kind)?;

            // Save new note.
            let context_path = n.context.path.clone();
            n.set_next_unused_rendered_filename_or(&context_path)?;
            n.save_and_delete_from(&context_path)?;
            n
        }
        TemplateKind::SyncFilename => synchronize(context, content.unwrap())?,
        TemplateKind::None => Note::from_text_file(context, content.unwrap(), template_kind)?,
    };

    // Export HTML rendition, if wanted.
    if let Some((dir, local_link_kind)) = html_export {
        n.export_html(
            &LIB_CFG.read().unwrap().tmpl_html.exporter,
            dir,
            *local_link_kind,
        )?;
    }

    // If no new filename was rendered, return the old one.
    let mut n = n;
    if n.rendered_filename == PathBuf::new() {
        n.rendered_filename = n.context.path.clone();
    }

    Ok(n.rendered_filename)
}

Inserts clipboard or stdin data into the context. The data may contain some copied text with or without a YAML header. The latter usually carries front matter variable. These are added separately via insert_front_matter(). The input data below is registered with the key name given by tmpl_var. Typical names are "clipboard" or "stdin". If the below input contains a valid YAML header, it will be registered in the context with the key name given by tmpl_var_header. This string is typically one of clipboard_header or std_header. The raw data that will be inserted into the context.

use std::path::Path;
use tpnote_lib::context::Context;
use tpnote_lib::content::Content;
use tpnote_lib::content::ContentString;
let mut context = Context::from(&Path::new("/path/to/mynote.md"));

context.insert_content("clipboard", "clipboard_header",
     &ContentString::from(String::from("Data from clipboard.")));
assert_eq!(&context.get("clipboard").unwrap().to_string(),
    "\"Data from clipboard.\"");

context.insert_content("stdin", "stdin_header",
     &ContentString::from("---\ntitle: \"My Stdin.\"\n---\nbody".to_string()));
assert_eq!(&context.get("stdin").unwrap().to_string(),
    r#""body""#);
assert_eq!(&context.get("stdin_header").unwrap().to_string(),
    r#""title: \"My Stdin.\"""#);
// "fm_title" is dynamically generated from the header variable "title".
assert_eq!(&context.get("fm_title").unwrap().to_string(),
    r#""My Stdin.""#);
Examples found in repository?
src/workflow.rs (line 272)
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
pub fn create_new_note_or_synchronize_filename<T, F>(
    path: &Path,
    clipboard: &T,
    stdin: &T,
    tk_filter: F,
    html_export: &Option<(PathBuf, LocalLinkKind)>,
) -> Result<PathBuf, NoteError>
where
    T: Content,
    F: Fn(TemplateKind) -> TemplateKind,
{
    // First, generate a new note (if it does not exist), then parse its front_matter
    // and finally rename the file, if it is not in sync with its front matter.

    // Collect input data for templates.
    let mut context = Context::from(path);
    context.insert_content(TMPL_VAR_CLIPBOARD, TMPL_VAR_CLIPBOARD_HEADER, clipboard)?;
    context.insert_content(TMPL_VAR_STDIN, TMPL_VAR_STDIN_HEADER, stdin)?;

    // `template_king` will tell us what to do.
    let (template_kind, content) = TemplateKind::from::<T>(path, clipboard, stdin);
    let template_kind = tk_filter(template_kind);

    let n = match template_kind {
        TemplateKind::New
        | TemplateKind::FromClipboardYaml
        | TemplateKind::FromClipboard
        | TemplateKind::AnnotateFile => {
            // CREATE A NEW NOTE WITH `TMPL_NEW_CONTENT` TEMPLATE
            let mut n = Note::from_content_template(context, template_kind)?;
            n.render_filename(template_kind)?;
            // Check if the filename is not taken already
            n.set_next_unused_rendered_filename()?;
            n.save()?;
            n
        }

        TemplateKind::FromTextFile => {
            let mut n = Note::from_text_file(context, content.unwrap(), template_kind)?;
            // Render filename.
            n.render_filename(template_kind)?;

            // Save new note.
            let context_path = n.context.path.clone();
            n.set_next_unused_rendered_filename_or(&context_path)?;
            n.save_and_delete_from(&context_path)?;
            n
        }
        TemplateKind::SyncFilename => synchronize(context, content.unwrap())?,
        TemplateKind::None => Note::from_text_file(context, content.unwrap(), template_kind)?,
    };

    // Export HTML rendition, if wanted.
    if let Some((dir, local_link_kind)) = html_export {
        n.export_html(
            &LIB_CFG.read().unwrap().tmpl_html.exporter,
            dir,
            *local_link_kind,
        )?;
    }

    // If no new filename was rendered, return the old one.
    let mut n = n;
    if n.rendered_filename == PathBuf::new() {
        n.rendered_filename = n.context.path.clone();
    }

    Ok(n.rendered_filename)
}

Methods from Deref<Target = Context>§

Converts the val parameter to Value and insert it into the context.

Panics if the serialization fails.

let mut context = tera::Context::new();
context.insert("number_users", &42);

Converts the val parameter to Value and insert it into the context.

Returns an error if the serialization fails.

let mut context = Context::new();
// user is an instance of a struct implementing `Serialize`
if let Err(_) = context.try_insert("number_users", &user) {
    // Serialization failed
}

Appends the data of the source parameter to self, overwriting existing keys. The source context will be dropped.

let mut target = Context::new();
target.insert("a", &1);
target.insert("b", &2);
let mut source = Context::new();
source.insert("b", &3);
source.insert("d", &4);
target.extend(source);

Returns the value at a given key index.

Remove a key from the context, returning the value at the key if the key was previously inserted into the context.

Checks if a value exists at a specific index.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more

Auto-dereference for convenient access to tera::Context.

The resulting type after dereferencing.
Dereferences the value.

Auto-dereference for convenient access to tera::Context.

Mutably dereferences the value.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.