NotePlan / plugins

The main NotePlan repository, which contains the source code for all NotePlan plugins. If a release entry has been created, it will be available for installation from within NotePlan application.
MIT License
167 stars 58 forks source link

Quick Capture - append date to added task #72

Open brokosz opened 3 years ago

brokosz commented 3 years ago

Describe the bug Not sure if this could be parsed appended text or needs to be a new configurable feature - I tried to append the date using {{date({locale: 'sv-SE', dateStyle: 'short'})}} but it didn't parse. Goal would be to have the added inbox task look like - [ ] buy milk - 2021-09-03 09:04

jgclark commented 3 years ago

This triggers an architecture alert for me. Namely: is this particular request just one example of a wider need to be able to include or trigger these sorts of "extension function calls" (to coin a phrase)?

We currently have two forms of substitution:

(BTW, I'm still really not keen on either syntax; the first is difficult to read, and the second makes documentation difficult. I really wish nmn had borrowed from Obsidian's syntax, as I recommended at the time.)

I've added ability to have pre-defined @mentions and #tags to the quick capture commands already (#57). It wouldn't take long to add another helper function to process extension function calls in any passed text, and use that to satisfy @brokosz's request.

But I wonder if there's a wider picture to consider first? For example I can imagine these new use cases:

  1. Allow user to type out an extension function calls in a note, and immediately process it, replacing the function call text
  2. Allow user to type out extension function call(s) in a note, and execute it via a new plugin command 'processExtensions', replacing the function call text
  3. Allow user to type out extension function call(s) in a note, and execute it via a new plugin command 'processExtensions', leaving the function call text in some way, so that it can be re-run later (to update lookups or calculations).

The latter is takes us close to advanced functionality in Obsidian that allows users to effectively make database-like queries, with the results embedded in the note. This could be a different way of addressing event lists, or lists of all notes with open tasks etc. etc. etc.

What do we think, @weyert @mikeerickson @dwertheimer @EduardMe ?

brokosz commented 3 years ago

Spot on, @jgclark - I made an assumption about function transclusion and I think it's the right way to go long term; seems like it would add to the flexibility of plugins but my concern would be up and downstream dependencies. I would think each plugin should be as atomic and idempotic as possible. So either there needs to be a base library of certain plugin functions as part of the NotePlan app bundle or each plugin developer would need to implement duplicative functions. I definitely don't know the right answer here.

jgclark commented 3 years ago

Thanks, @brokosz. I quite agree about keeping things as separate as possible. I see it was early June I raised #11 worrying about the linkage I was finding particularly as we add more "extension functions". We didn't resolve that then, nor at the first plugin-dev-meetup with Eduard.

mikeerickson commented 3 years ago

hey gang,

i have some thoughts on this and will be preparing a more verbose reply in the coming days. I have some household items to take care of this morning, but i will be back on computer this afternoon and i will provide with my thoughts šŸ˜Ž

mikeerickson commented 3 years ago

DISCLAIMER: This may go deeper than expected šŸ˜“

@jgclark Do you happen to have any reference material you can point me to on how Obsidian handles this type of situation? I am keen to implementing what they have done (based on your desires, I am sure it is a logical approach). I will give more context after I have reviewed this information (but again, I trust that your recommendation is a solid direction)

@brokosz I agree that it should be idempotent as it already a standard across the industry, thus no need to deviate from that whatsoever. With regards to a common set of libraries, this is something that I have thought about quite a bit. If we think in terms of writing C++ type code, we could have standard libraries (stdlib) that we would import in ALL plugin calls (no need to worry about bloated plugins, as they will be tree shaken accordingly at build time). This way, we do have to replicate code, just import the library and boom (we are already doing this in large part with the common helpers so this would not be a big mind shift.


NotePlan Standard Library

In general, I think we should create a standard library stdlib which would be an isolated JavaScript library (or libraries if need be) so that it can evolve as we realize more and more what types of functions should be available (this is a similar approach used by VSCode and their extension development, see below for an example).

I do think however, that we need to be a bit more explicit with versioning and a single entry point or default export so that we keep a proper CHANGELOG for all the commands and reference to specific version when addressing an issue.

import np from ā€˜./lib/noteplanā€™
ā€¦

const config = np.getConfig(ā€¦)

Or using standard destructuing

import { getConfig } from ā€˜./lib/noteplanā€™
ā€¦

const = getConfig(ā€¦)

VSCode Extension Example

This is the standard extension.js header which in this case imports an npm package (another angle we could consider and would make versioning and maintaining that much easier (but that can come at a later time after our library API stabilizes).


// const values = config.get('configurations');
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below

const vscode = require('vscode');

Conclusion

OK, that is enough to nibble on for the time being, and more discussions will occur, but I think we are headed in the right direction, and the consensus seems we all want some ā€œstandardsā€, and this will evolve. I will give my strong vote to having a standard library (something like /lib/noteplan.js or an npm module down the road.

I am wide open to suggestions, just sharing some of the approaches I have done in my ā€œday jobā€ as we face these types of situations on a regular basis with all of our development groups (we have an average of 40+ developers). We maintain a dozen or so libraries, which are used across all of our applications, so some of it may be overkill for what we are trying to accomplish.

jgclark commented 3 years ago

I've enjoyed munching on that, @mikeerickson, and happy to head this way.

On the specifics of Obsidian, I admit that I've not used it extensively, but in particular it's the Templater extension/plugin that I was hoping we could learn from.

Here's a simple case, cribbed from their getting started:

The following template file, that is using Templater template syntax:

---
creation date: <% tp.file.creation_date() %>
modification date: <% tp.file.last_modified_date("dddd Do MMMM YYYY HH:mm:ss") %>
---

<< [[<% tp.date.now("YYYY-MM-DD", -1) %>]] | [[<% tp.date.now("YYYY-MM-DD", 1) %>]] >>

# <% tp.file.title %>

<% tp.web.daily_quote() %>

Will produce the following result when inserted:


---
creation date: 2021-01-07 17:20
modification date: Thursday 7th January 2021 17:20:43
---

<< [[2021-04-08]] | [[2021-04-10]] >>

Test Test

Do the best you can until you know better. Then when you know better, do better. — Maya Angelou


You can immediately see the similarities. I liked that it:
- has a fairly readable syntax
- has namespacing for functions, to help manage growth
- already includes the ability to embed JavaScript directly (though naturally that's an advanced concept that would need great care)

I've not attempted to build plugins in this system, so I don't in detail what its standards are, other than seeing they hold to CommonJS which we're not.

NB: This is related to #11.

mikeerickson commented 3 years ago

@jgclark Yea, this is definitely a nice plugin and I think we could provide something very similar for NotePlan, while maintaining the current variable syntax already in use ( or we could move to the same templating engine used by Templater eta if we want maintain consistency with those who may come from Obsidian

It is really just a matter of using {{ }} versus <% %>

From reading the example from Templater plugin, we could implement the same sort of templates using GitHub - janl/mustache.js: Minimal templating with {{mustaches}} in JavaScript

If I would take the example Templater template you supplied, it could be formatted as such using Mustache (some of this is pseudo code)


const Mustache = require('mustache')

const mustacheTemplate = new Mustache()

const { format } = require('date-fns')

const dailyQuote = (/* whereever we are getting quotes */}

// format dateTime using optional user defined format
// uses `format` from `date-fns`

const formatDateTime = (formatStr = "yyyy-mm-dd HH:ss") => {
  return format(formatStr)
}

const mergeData = {
  file: {
    title: 'Hello World',
    creation_date: function(formatStr = null) {
      return formatDateTime(formatStr)
    },
    last_modified_date: function(formatStr = null) {
      return formatDateTime(formatStr)
    }
  },
  date: {
    now: function(formatStr = null) {
     return formatDateTime(formatStr)
    }
  }
  web: {
    daily_quote: function() {
     return dailyQuote()
    }
  }
}

const templateData = /* read from NotePlan template */

const result = mustacheTemplate.render(templateData, mergeData)

Template Objects

Example Template Contents

The following example could use the standard NotePlan Template (using the same object syntax as existing templates)


ļæ¼
creation date: {{ file.creation_date() }}
modification date: {{ file.last_modified_date("dddd Do MMMM YYYY HH:mm:ss") }}
ļæ¼

<< [[ {{ date.now("YYYY-MM-DD", -1) }} ]] | [[ {{ date.now("YYYY-MM-DD", 1) }} ]] >>

 {{ file.title }}

{{ web.daily_quote() }}
mikeerickson commented 3 years ago

@jgclark Sorry this is multiple replies, writing this on iPad is sometimes difficult :-)

OK, so we could then provide a series of namespaces objects which users could then use in their templates (objects with or without namespace as necessary)

title (variable) 
daily_quote (function)
date.today (function)
file.create_date (function)
file.modified_date (function)

Note: My example was CommonJS format, but could just as easily been in ES6 format

EduardMe commented 3 years ago

Sorry for not participating too much in the plugin channels these days. Iā€™m again deep into NotePlan coding.

However, I like the suggested templating ā€œlanguageā€.

Some thoughts from my side:

dwertheimer commented 3 years ago

Eduard, this is interesting. I shipped a plugin over the weekend called /qtn which allows you to create a quick note from a template with {{templateTags}} in the title. It would not be hard to create a plugin even now to do much of this. Something like:

BTW, I don't want to derail the discussion of the templating engine, which would be amazing.

On Tue, Sep 07, 2021 at 7:35 AM, Eduard Metzger @.***> wrote:

Sorry for not participating too much in the plugin channels these days. Iā€™m again deep into NotePlan coding.

However, I like the suggested templating ā€œlanguageā€.

Some thoughts from my side:

  • I could add a standard library to NotePlan shipped with the bundle, if that helps (maybe one to process templates). Only problem is that updating it would be a pain.
  • For the Meeting Notes feature, I wanted to get right away into templating. Means we got an event in the right sidebar and now we want to create a meeting note for that. Instead of taking one fixed version, I thought of using templates directly, so you can change it as you wish. For example, if you donā€™t want to have the attendees listed, then remove the template text. So, whatever we arrive at, I would like to use it later and integrate also in the main code. Or meeting notes could be also possibly a plugin in itself, just called from a context menu.

ā€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/NotePlan/plugins/issues/72#issuecomment-914359113, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACEI6VAFSOTCBABGU6CYJETUAYPKPANCNFSM5DL577JA .

EduardMe commented 3 years ago

Very cool idea, that would be almost all we need for that feature! Iā€™ll add later some proper ā€œlinkageā€ to it. Plan is that NotePlan check for an x-callback-url in the notes field of the event and then displays a note icon, so the user can directly jump into the note from the event. The plugin could add this as well.

jgclark commented 3 years ago

Just a quick update, @brokosz, to say that I haven't forgotten about your original feature request here. Since the architectural conversation it spawned here, in #11 and in our first GH 'discussion', @mikeerickson is now underway with #89 which will implement a richer templating language for plugins.

My hope is that this will mean it's a simple configuration change to add dates in the way you want, without requiring specific plugin coding. So please hold on, and I hope to use it within a week or so as a useful test case.

dwertheimer commented 1 year ago

@jgclark what's your thinking about this one? can it be closed?