I don't think there is already a plugin for that

If folders could automatically apply their name as a tag to the notes they contain, I would be quite happy.

1 Like

I agree, that would be a cool plug-in! Although, you might be able to achieve this with Auto Classifier. It uses ChatGPT to suggest tags for your notes. Probably not as convenient, but it might work. I would test it out, but I’ve unfortunately reached my the end of my OpenAI API free trial.

Also, you might want to consider posting this in Plugin ideas instead of help, it seems like a more fitting category.

What are you using to create your files? Templater? Some other plugin? Manually?

It shouldn’t be that hard to write a template to insert the folder as tag into the frontmatter, but the method could vary avoiding to how you create your files.

I did post this in the “feature request” forum initially, but it got transferred here…

Holroy, I create new notes two ways, with quickadd and templater, or manually. Also the thing is, I’d like the folder to tag their notes, but I’d also like this tag to change if I change the note to a different folder.

I want my folder tree to be represented in the graph view.

It sounds like you might like the Waypoint plugin.

Say you have a a bunch of folder notes, a note that’s something like the home page of its folder. With the waypoint plugin, you can generate a list of files and subfolders inside the current folder in the folder note.

So now, with the links to everything in the folder, they will show up in the graph view, with the folder note representing the folder. And if subfolders also contain similar folder notes, then you’ll have a 100% accurate view of your vault as if your folders had become tags.

And the waypoint plugin also updates the links automatically, so all you have to do is add it to the note and you’re all set.

1 Like

Also, all you have to do is type %% Waypoint%% in the note for the links to generate, so it’s fully integrateable with templater. I just started using Quickadd, so I’m not 100% sure yet, but it could probably work with that, too.

Yeah, I thought about creating a note like that for each folder, I’m not so surprised that something exists in these lines. Thanks for to input, I’ll look into it.

I have manually imported all of my Evernote notes to Obsidian (hundreds) and I’m slowly creating tags and links as I revisit them. But it’s not the same thing as starting fresh with obsidian.

I love it though, the transition between the two information systems is actually very interesting to do, and I’m coming up with ways to manage my info.

I know there are a lot of methods out there, but I don’t want to look at them, I want to craft my own because the process itself is happening within my brain and that is irreplaceable.

I’ll almost certainly probably come up with things that are already out there, but it is not always completely useless to “reinvent the wheel”. It’s all about the process and act of creativity. And then you truly understand the thing cause you made it from scratch.

Anyways, enjoy the sun!

1 Like

So, first of all, although this post presents a solution, I would strongly advise not to do this, as it will take a toll on the file system and it causes various race conditions when run. With that being said, lets present a potential handling of this issue.

In the following I’m assuming that every file where you want to tag the folder triggers the dv.view() script described below. This script will then be run every time a dataview query is run in that file. Aka either when you open the note, or a given delay after you last changed the file. If you move the non-opened file, nothing will happen until you actually open the file, but then the query will run and update the tags.

In pseudo-code the script does the following:

  • Check whether there is a prevFolder field indicating the previous folder when the query was run the last time
  • Check current folder, and store in newFolder
  • If they differ, trigger a delayed response (1 second) to change the frontmatter of the current file. The delayed response is needed in an attempt to avoid race condition on changing the file. The frontmatter is changed as follows:
    • Check if there is any tag or tags defined in the frontmatter, and store which tagKey is in use
    • Check if the tag is a single value, and do:
      • If equal to prevFolder we’ve got the only value, so replace it
      • Else, push newFolder and the old tag onto the tag list
    • or else if it’s an array, manipulate the array to remove prevFolder and add newFolder
  • Finally, store the new prevFolder, so that we know what to remove on the next run
The full script
let curr = dv.current()
/* 
// An attempt to counter 
// https://github.com/blacksmithgu/obsidian-dataview/issues/584
let retry = 3
while (retry && !curr) {
  await new Promise(r => setTimeout(r, 700))
  curr = dv.current()
  console.log(retry)
  retry = retry - 1
} */

if ( curr ) {
  const filename = curr.file.path  
  const prevFolder = curr.prevFolder
  const folderParts = filename.split("/")

  // console.log("\n\n\nNew run", filename, prevFolder)
  
  if ( folderParts.length > 1) {
    const newFolder = folderParts[ folderParts.length - 2 ]
  
    const theFile = await app.vault.getAbstractFileByPath(filename)
    if ( newFolder != prevFolder ) {
      await setTimeout( async () => {
        await app.fileManager.processFrontMatter(theFile, (fm) => {
          // console.log(fm)
          const tagKey = Object.keys(fm).filter( t => t.toLowerCase() == "tags" || t.toLowerCase() == "tag" )
          if ( tagKey) {
            let tags = fm[tagKey]
            if (typeof(tags) == "string") {
              if ( tags == prevFolder ) 
                fm[tagKey] = newFolder
              else
                fm[tagKey] = [ tags, newFolder ]
            } else {
              // console.log("prev", prevFolder, " new", newFolder)
              // console.log("Pre ", tags)
              tags = Object.values(tags).filter(t => t != prevFolder && t != newFolder )
              // console.log("tags ", tags)
              fm[tagKey] = [newFolder, ...tags]
              // console.log("Post ", fm[tagKey])
            }
          } else
            fm["Tags"] = newFolder
          fm["prevFolder"] = newFolder
        })
      },  1000)
    } 
  }
} else {
  console.warn("dv.current() not found. Yet. Note must be reloaded")
}

The script above needs to be stored somewhere, like _js/folderTag.js (note the file extension), and in every file you want this functionality you need to do:

```dataviewjs
await dv.view("_js/folderTag.js")
```

Caveats with this solution:

  • It’s only updating when the query is run, so if you move files which are not open, they don’t update until the file is opened
  • If you move a file which is open, then there is a bug in Dataview leaving dv.current() with a null value, causing nothing to happen
  • Race conditions can occur if there are multiple queries, and the timing is off between changes done by other queries, and dataview queries, and the delayed triggering of the frontmatter change by this script

In summary, although this does seem to work, I’m not sure if I would rely on it in a production environment. As such, this is more a proof of concept. If it fails to update, you can re-open the file (or rebuild the view, aka triggering the query again), to get it to open.

I’m also not entirely sure I caught all variants related to how to define tags, and handle those in a safe and robust way. My somewhat simple test, does however work and shift the tag around to match the current folder of the note.

2 Likes

That is awesome my friend.

It reminds me that coding is yet another thing I need to learn. I swear I will need to live two hundred years old if I must learn everything I need for every project I want to do.

I don’t have the brain real estate to start coding right now, XD

I’m sure I can understand all this if I read it very carefully, and in the meantime, thank you for making it easy to integrate without the knowledge. But I’m still not sure where to put the scripts, either the full script or the one that each individual file will need.

Your post is crystal clear though, and you seem to have put some considerable work into that. I’m just a complete newbie. I guess I can just look for .js files and I might understand everything then.

Thank you for the help, this community is truly fantastic.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.