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

YAML Headlines #929

Open
bepolymathe opened this Issue Jun 4, 2018 · 37 comments

Comments

Projects
None yet
3 participants
@bepolymathe

bepolymathe commented Jun 4, 2018

Hello to both of you @pbek and @Maboroshy It's been a long time since I've been through this ;-)

I find the idea of YALM header integration excellent in order to export with Pandoc more customized.

The problem is that the script only works if the document starts like this: 


tags: tag1 tag2 multi_word_tag
...

But Qownnotes uses the first line to give the title to the document in the list of notes. Would it be possible to allow to choose the first title ( #) or the field "title" of YALM rather than the first line to give the title. On a more complete document it would look like:


title: Title in YALM for futur export with Pandoc
subtitle:
author:
date: 30 may 2018
lang: en
toc: no
abstract:
tags: first second etc
...

Title 1

Title 2

Lorem ipsum...

What do you think of that ?

@pbek

This comment has been minimized.

Owner

pbek commented Jun 4, 2018

You can turn off that the first line has to be the filename in the settings.

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 4, 2018

Yes, but in this case, you have to rename the files one by one...

@pbek

This comment has been minimized.

Owner

pbek commented Jun 4, 2018

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 4, 2018

I'm +1 for @bepolymathe request. And I have another use case for it.

My case is that Epsilon Notes and some other markdown editors can't handle spaces in file names well. So if I use file names as note names I should rename my notes to something like multi_word_name.md. With some help from Epsilon Notes preprocessor I could make it compatible with QON's format to note links for a flat folder structure. But that looks ugly in the note list.

If there'd be some hook that asks for each note name to fill note list I could make it replace _ by spaces or get YAML headline from note text. All app logic stay the same except note list item's title and maybe window title.

Having more control over note list item appearance can open the door to some experiments like note YAML/tags/content changing color/text of note list items, and by text changes order of notes could be changed too. Something like this feature of Wikidpad.

For example I had some script that pinned notes to the top of the list by renaming a note file so it would start from some special symbol. Using such hook it can be done on the note content level, without messing with file system.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

If there'd be some hook that asks for each note name to fill note list

I'll put that on my list.

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 5, 2018

That's great news ! This would really make QON my default text editor for scientifics articles ;-)

@pbek pbek changed the title from YALM Headlines to YAML Headlines Jun 5, 2018

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

There are some troubles with this. One of them is that the list of files will not (and should not) be redrawn every time a note is edited (editing could lead to a possible note name change with this hook)...

pbek added a commit that referenced this issue Jun 5, 2018

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

18.06.1

  • added a new scripting hook handleNoteNameHook(note) that is called when the
    note name is determined for a note
    (for #929)
    • take a look at the
      handleNoteNameHook documentation
      for more information
    • the user interface will currently not be updated when the note text (that
      could result in a note name change with the new hook) is stored
@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

I hope there are not too many side effects, I already had to take care of some things... Please use and test the new hook and report back...

@pbek pbek added this to the 18.06.1 milestone Jun 5, 2018

pbek added a commit that referenced this issue Jun 5, 2018

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

There now is a new release, could you please test it and report if it works for you?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 5, 2018

Works as expected for me, even with enabled file name as note name. By the way could you clarify why it's bad with this hook.
I've tested to _ and YAML title scripts and implemented auto-refresh with onNoteStored hook.

I quickly found out that this new hook should be paired with one to handle note renaming by UI like the one for in-text tagging. Without one renaming is absolutely nontransparent.

Also it would be cool to have more attributes of note list item to control, like text colour and icon.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

By the way could you clarify why it's bad with this hook.

too many things might still rely on the note name and I had to go through some hoops to kill the performance for everyone that doesn't use this hook (because of extensive hook checking)

Also it would be cool to have more attributes of note list item to control, like text colour and icon.

I'm not sure yet, might be complicated

@pbek

This comment has been minimized.

Owner

pbek commented Jun 5, 2018

I first want to see a script that uses the hook...

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 5, 2018

Here is my dirty scratch one:

import QtQml 2.0
import com.qownnotes.noteapi 1.0

QtObject {
        
    function getNoteYAML(note) {
        const noteText = note.noteText

        if (noteText.substring(0, 4) == '---\n') {
            var yamlEndIndex = noteText.indexOf('\n...\n')
        
            // If there's no proper "..." YAML ending "---" is recognized as one
            if (yamlEndIndex == -1)
                yamlEndIndex = noteText.indexOf('\n---\n')
        
            if (yamlEndIndex != -1) 
                return noteText.substring(0, yamlEndIndex)
        }
    }
    
    function handleNoteNameHook(note) {
        const noteYaml = getNoteYAML(note)
        
        if (noteYaml == null)
            return ''
            
        return noteYaml.match(/^title: *(.*)/m)[1]
    }
    
    function onNoteStored(note) {
        mainWindow.buildNotesIndexAndLoadNoteDirectoryList(true, false)
    }
}

Refresh part should be much more than that, it will check if title actually changed before rebuilding.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 6, 2018

Refresh part should be much more than that, it will check if title actually changed before rebuilding.

yes, it will be something I have to do in QOwnNotes.
And doesn't we also have to take care of the headline in new notes?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 6, 2018

I thought about implementing refresh logic in a script but app code can do it better.

I haven't tested new notes yet.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 6, 2018

I thought about implementing refresh logic in a script but app code can do it better.

I'd rather only want to refresh that one item in the list then reloading and parsing all notes again...

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 6, 2018

For the new notes, it is true that the ideal choice (for the variety of uses) would be :

  • new empty note
  • new note with date in title (as currently)
  • new note with a Yalm insert from which the title is extracted (as in the script of @Maboroshy )

I need to go back to my script self-study to try to help you.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 6, 2018

@Maboroshy does filtering by tag and sub-folders still work with the new hook?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 6, 2018

Seems work.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 6, 2018

Nice

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

Currently I work with this simple "template" and I wonder how to combine the two? Or rather keep two scripts?


/**
 * This script is an example for creating custom actions, that can be invoked 
 * via menu entries and buttons
 */
QtObject {
    /**
     * Initializes the custom actions
     */
    function init() {
        // create a menu entry "Create new complex document" with a button and a freedesktop theme icon
        script.registerCustomAction("Document", "Create new complex document", "Document", "Document");
    }

    /**
     * This function is invoked when a custom action is triggered
     * in the menu or via button
     * 
     * @param identifier string the identifier defined in registerCustomAction
     */
    function customActionInvoked(identifier) {
        script.log("customActionInvoked - " + identifier);

        switch (identifier) {
            // create a new note with a custom content
            case "Document":
                var m = new Date();
                // create the headline
                var text = "---\ntitle:\nsubtile: \nauthor: \n - Name\ndate: \nlang: fr \ntoc: yes \nabstract: \ntags: \ncomment : >\n 		commentaire\n... \n\n";

                // create a new note
                script.createNote(text);
                break;
        }
    }
}
@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 10, 2018

You can but multiple functions into one QtObject. If some of these functions are scripting hooks all of them will work.

For example my script above has handleNoteNameHook and onNoteStored. They are two different hooks in one QtObject. Both of them work as expected.

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

Ok, i will try it. thanks

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

I tried adding your script to mine to test it. I have"[warning] Invalid version or not a cyphertext." in a mess...


/**
 * This script is an example for creating custom actions, that can be invoked 
 * via menu entries and buttons
 */
QtObject {
    /**
     * Initializes the custom actions
     */
    function init() {
        // create a menu entry "Create new complex document" with a button and a freedesktop theme icon
        script.registerCustomAction("Document", "Create new complex document", "Document", "Document");
    }

    /**
     * This function is invoked when a custom action is triggered
     * in the menu or via button
     * 
     * @param identifier string the identifier defined in registerCustomAction
     */
    function customActionInvoked(identifier) {
        script.log("customActionInvoked - " + identifier);

        switch (identifier) {
            // create a new note with a custom content
            case "Document":
                var m = new Date();
                // create the headline
                var text = "---\ntitle:\nsubtile: \nauthor: \n - Emmanuel Porte\ndate: \nlang: fr \ntoc: yes \nabstract: \ntags: \ncomment : >\n 		commentaire\n... \n\n";

                // create a new note
                script.createNote(text);
                break;
        }
    }

    function getNoteYAML(note) {
        const noteText = note.noteText

        if (noteText.substring(0, 4) == '---\n') {
            var yamlEndIndex = noteText.indexOf('\n...\n')
        
            // If there's no proper "..." YAML ending "---" is recognized as one
            if (yamlEndIndex == -1)
                yamlEndIndex = noteText.indexOf('\n---\n')
        
            if (yamlEndIndex != -1) 
                return noteText.substring(0, yamlEndIndex)
        }
    }
    
    function handleNoteNameHook(note) {
        const noteYaml = getNoteYAML(note)
        
        if (noteYaml == null)
            return ''
            
        return noteYaml.match(/^title: *(.*)/m)[1]
    }
    
    function onNoteStored(note) {
        mainWindow.buildNotesIndexAndLoadNoteDirectoryList(true, false)
    }
}
@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

One question. How is your "allow file name to differ from title" option set?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 10, 2018

There's a checkbox for that in "General" section of options.

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 10, 2018

Also my script is does not fully work. It's a scratch to test a hook, nothing more. I'll make something more complete when note renaming hook come.

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

Yeah, I know. But is it checked or not at for you to make it work?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 10, 2018

I have it checked all the time.

@bepolymathe

This comment has been minimized.

bepolymathe commented Jun 10, 2018

Ok thanks.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 17, 2018

I'll make something more complete when note renaming hook come.

@Maboroshy, are we talking about "altering the name in the note list" or actual modifying the filename of the note. By the way, isn't something bad happening when the user actually tries to rename the note in the note list if I alter the name there?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 17, 2018

As of now renaming note list item renames the file, showing new name in the list until note list rebuild.

I'm waiting for a hook for renaming note in the notes list. Something like one for renaming the tag, with oldName and newName. Then I could make the script that would put newName to YAML with or without altering file name. Renaming the file presumably can be done by handleNoteTextFileNameHook in the same script. Or it can be a part of a new renaming hook.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 18, 2018

Hm, so the user can't manually rename the file any more?

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 18, 2018

For now renaming note list item renames the file. But that doesn't change YAML title in note text. So YAML title come back on note list refresh. Note file keeps new name - the one input by user at renaming.

@pbek

This comment has been minimized.

Owner

pbek commented Jun 18, 2018

Currently the name in the note list was the filename of the note, I guess I will just disable note renaming if a hook to alter the name in the list is present.

@Maboroshy

This comment has been minimized.

Contributor

Maboroshy commented Jun 18, 2018

I agree. Since the hook is about control on note title, note file name should also be controlled by a script.

That makes such hook a third mode, besides note title as file name and as headline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment