Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there any way to template new wiki pages? #46

Closed
Corey-Keller opened this issue Dec 27, 2019 · 11 comments
Closed

Is there any way to template new wiki pages? #46

Corey-Keller opened this issue Dec 27, 2019 · 11 comments

Comments

@Corey-Keller
Copy link

It's very possible that this is already a feature, and I just don't realize it, but is there any way to set up the default for new pages? For example, I turn the text "Example Page Here" into a link, and open it.

Observed behavior: empty document

Expected behavior: A document starting with a level 1 heading containing the name of the link, and maybe a few new lines. Ideally, it would all be configurable beyond that, but that seems like a solid minimal default.

@lervag
Copy link
Owner

lervag commented Dec 30, 2019

Hi! Sorry for the delayed response; I've been mostly away from my computer during the Christmas break.

Thanks for raising the issue and giving a good description of what you want. This is not possible at the moment, but it should be a relatively simple feature to implement, and I'll look into it with the new year.

Do you have an idea of how you would want to configure such a feature? I could think of some alternatives, e.g.:

" String based template
let g:wiki_template_new = '# {pagename}'

" Function based template
let g:wiki_template_new = 'MyTemplate'

function! MyTemplate()
  return join([
    \ '# ' . expand('%:h'),
    \ '',
    \ 'Some text here.',
    \], "\n") . "\n"
endfunction

I think I prefer the last method, but it might be too complicated for a lot of people. If I implemented the function based feature, then I could also implement the string based version on top of it afterwards.

@Corey-Keller
Copy link
Author

Corey-Keller commented Jan 2, 2020

I would think a file-based method would be best actually. the var would point to a file that would have (for example):

# {pagetitle}
last modified: {moddatetime}

IfSection[## {pagesection}

]

And it would read that and transform the variables appropriately: {pagetitle} is auto-filled from the link description (if created that way and not blank), {moddatetime} is the date and time the file was last modified in e.g. %Y-%m-%d %H:%M:%S format, and {pagesection} is in an "IfSection" block due to being optional. It would only be created for links with sections like "README.md#Section Two" for example.

This is all hasty pseudo-code of course, but it lays out an idea of what I think would work best for sure. Gives the control of the function method, with almost no changes from normal markdown.

EDIT: A suggested default value for the file would be ['./.wikitemplate', '/.wikitemplate']. This would first look for a template in the current folder ./ and fall back to the template at the root, /. The reasoning is that I have several common types of pages:

  • Work plans (how to do a repeatable process)
  • Issues (with "Problem" and "Solution" sections)
  • KnowledgeBase (information on a given subject)

@lervag
Copy link
Owner

lervag commented Jan 2, 2020

Ok, we could use a file based template. But to avoid a lot of future issues, I would want to make a good specification first. Here is a first draft:

Option
We need a single option: g:wiki_page_templates = [list of paths], where the paths are either relative to the current wiki page or to the root, /. That is, an absolute path will always be rooted at the wiki root.

Template format
The template format should be generally free, except that it should allow some variable expansions, e.g. {varname}, as well as function expansions, e.g. {{MyVimFunction}}. The following variables should be allowed:

  • {pagetitle} - Parsed from original link (the base part).
  • {pagetarget} - Parsed from original link (the anchor part).
  • {date} - The current date (%Y-%m-%d)
  • {time} - The current time (%H:%M:%S)

The function expansions allow one to easily write something like your IfSection block with some simple vimscript. The function should take one context input that contains the above mentioned variables (a dictionary), and it should return a list of lines to output.

Example
Your example should be possible with something like the following configuration:

g:wiki_page_templates = ['.wikitemplate', '/.wikitemplate']

function! WikiTemplateSection(ctx) abort
  if !empty(a:ctx.pagetarget)
    return [
      \ '## ' . a:ctx.pagetarget,
      \ '',
      \]
  else
    return []
  endif
endfunction

The template:

# {pagetitle}
created: {date} {time}

{{WikiTemplateSection}}

I'll update the specification based on the discussion, and when we agree I'll begin to implement it. The most crucial thing is to decide on a good structure. If we do that well, then it will be easy to improve and extend the feature in the future if necessary.

@gauteh
Copy link

gauteh commented Jan 5, 2020

I've used snippets (e.g. Ultisnips) with dates and other types of information to quickly load a template for new journal entries and reference-"cards" for academic papers. In that case you open a new file, type a couple of chars e.g. dia for diary and hit C-j to load the template with the date of the day.

From [filetype].snippets file:

## Diary
snippet diary "Diary entry" b
# `!v strftime('%Y-%m-%d')`

work: `!v strftime('%H:%M')`$1 -

## log
  * $2

endsnippet

@lervag
Copy link
Owner

lervag commented Jan 7, 2020

I think @gauteh has a point here: Templates like what you ask for, @Corey-Keller, could easily be implemented as snippets with e.g. Ultisnips. This would have the benefit of relying on a well tested plugin which may be used for many things. One may also use automatically expanded snippets, e.g. say a snippet where ::note would expand to most of what you asked for in your original post.

I'm curious, @Corey-Keller, do you still think the template feature would be interesting, given that one could quite easily use snippets for this?

@Corey-Keller
Copy link
Author

Yes, it is still useful. For a couple of reasons:

  1. Activating that snippet still requires manual action (dia for diary and hit C-j or ::note) instead of automatically happening whenever a nonexistent wiki page is opened.
  2. That snippet would have to grab the page Description somehow, which would require determining the type of link (markdown, or wiki) and grabbing the text in the [ ]'s before the ( )' (if md) or the text after the | inside the [[ ]] (if wiki), with a fallback to the link name if it is empty. And then check the link for a # and if found, conditionally add a subsection.

From a user standpoint that's a LOT more difficult than making a file with a few template sections in it.

@lervag
Copy link
Owner

lervag commented Jan 12, 2020

Great, thanks for providing some good arguments for your case, in particular I think the number 2 is important.

So, I would still like feedback on my proposal for the specification of this feature, see my earlier comment. If you think it is already acceptable, then I'll try to implement it when I get the time.

@Corey-Keller
Copy link
Author

Corey-Keller commented Jan 13, 2020

I have an example to make sure that I understand the proposed spec. If I have:

[The Taco Truck](the-taco-truck/index#menu)

The sections would be:

{pagetitle} = "The Taco Truck"
{pagetarget} = "Menu" ( or "menu" but I assume that it would use Title Case due to being a section heading)

Is that correct? If so, that seems to be a good solution.

Although, if the description is empty, how should the title be decided? It's obvious if the link is my-page.md that the title should be my-page but how would it be grabbed from the link above, or a link like my-workplans/how-to-build-a-printer#verification.

This is kind of a separate request, but it would be good to have {modifieddate} and {modifiedtime} that auto updates on save, just like you'd be able to see on an actual wiki.

@lervag
Copy link
Owner

lervag commented Feb 9, 2020

Sorry for taking so long! It's been a very busy month!

... Is that correct?

I would say pagetitle is Index. Perhaps this example should be treated differently, though. That is, pages with path /something/index.wiki, Something might be a more suitable title. But for general paths /something/name.wiki, I would say the title should be Name.

But these are all details that we may settle and improve on later. Regarding case styles, I think we could allow for a modifier to define case style. I also think we should keep the case of the original text by default. I suggest we allow something like this:

{{FunctionName Argument1 Argument2 ...}}

This will be replaced with the result of

FunctionName(Argument1, Argument2, ...)

Now you could ensure case title by defining a function CaseTitle that takes a single string argument. In your template, you would write:

# {{CaseTitle pagetitle}}

Perhaps some common functions should be available, e.g. wiki#template#case_title.

I'll begin to work on this when there is time.

@gauteh
Copy link

gauteh commented Apr 21, 2020

Hi, I've started using the following to get a very simple template going for my journal entries (separate file for each day):

  au BufNewFile ~/.wiki/journal/*.md put! =strftime('# %Y-%d-%m') | call append(2, '') | norm G

@lervag
Copy link
Owner

lervag commented Jun 21, 2020

Again, sorry for the delay. At least, now I have started. I've typed out the specification in the docs. I would be very happy to get some feedback/comments, see #83 for details.

As I've opened a PR for resolving this issue, I think it is convenient to close the issue and continue the discussion in the PR thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants