QuickAdd Macro: Showing a list of files to Capture automatically

I wanted to use QuickAdd to capture ideas to multiple notes to multiple different notes

Unfortunately with the Capture choice, I needed to manually write out the files in a wild way in order to list them the way I wanted. This was that horror:

Luckily, I’ve been poking around with JS and managed to create a macro to list files the way I needed without manually doing a lot of work.


Search Criteria JS File

This is the file that takes some information on what to look for.

module.exports = (params) => {
    
    //Brainstorm Notes
    params.variables.fileType = { 
        folder: "31 Stories/Stories",
        folderExclude: "!!Test", 
        filename: "Brainstorm" 
    };
}
  • folder is the location it’s looking for the notes from the root of the vault (don’t include your vault name in the whole path).
  • folderExclude is the name of a folder that you’re excluding
  • filename is the name of the files that you’re search for

Another example of this type of file:

module.exports = (params) => { 

    //Reference Notes
    params.variables.fileType = {
        folder: "50 Nebula", 
        //folderExclude: "", 
        // There's no folder to exclude so I commented it out
        filename:"Ref" 
    };
}

fileFilter JS File

This is the file that filters the files and displays then in the quickswitcher suggester:

module.exports = async function listFiles(params) {
    // Grab fileType variables
    const fileType = params.variables.fileType;
    const folder = fileType.folder;
    const folderExclude = fileType.folderExclude;
    const filename = fileType.filename;



    // Search for files that match fileType parameters
    const files = params.app.vault.getMarkdownFiles()
        .filter(file => file.path.match(folder))
        .filter(file => { 
            //Check if folderExclude field exists
            if (folderExclude) { return !file.path.match(folderExclude) }
            else { return file }
        })
        .filter(file => file.basename.match(filename))

        //Sort by File Name
        .sort((a,b) => a.basename.localeCompare(b.basename))
        //Sort by Folder
        .sort((a,b) => a.parent.path.localeCompare(b.parent.path))
        //This was to show file outside of inner folder on top 
        //then sort the files in the inner folder



    // Display files to select
    const notesDisplay = await params.quickAddApi.suggester(
        (files) => files.basename,
        files
    );

    // Pass selected note's path to notes variable
    params.variables = { notes: notesDisplay.path };
}

Setup

  1. Save all these files somewhere inside your vault as .js files.
  2. Open QuickAdd > Manage Macros > Add Macro > User Scripts
    Obsidian_yzbqQVVzTE
  3. Select your search criteria js files and then add the fileFilter js file
    Obsidian_F1GBzwvTA9
  4. Create a Capture choice inside the macro
  5. Add these to your capture choice’s field for File Name: {{VALUE:notes}}
  6. Change any other settings in the capture macro to your preferred setup
  7. Go back to the regular QuickAdd settings menu and add a Macro choice
    Obsidian_8nEQFHnp6u
  8. Title it whatever you’d like and toggle the lightning to either hotkey or use the command prompt to trigger it.

That’s it! Now it should list the files you want to see without having to manually add each one.

If anything was unclear, feel free to ask any questions and I’ll do my best to answer it.


:tada: Thanks to @AB1908 for the help with the initial sorting functions and @scholarInTraining for pointing me in the right direction in the QuickAdd documentation and explaining how to do the separate file for the variables.

8 Likes

Are you able to add YAML tag on this too?

This is a fabulous addition - super useful. Unfortunately my javscript coding is non-existent. Like the previous user, would be amazing to filter the file list by YAML e.g. I have a projectstatus entry and would only like to list those that are “Active”… Any tips?

Capturing to any file or files with a specific tag is now possible without any User Scripts.

Yes I saw that and this is amazing! it does what is advertised and I have replaced my {{ield}} setup with just a #tag now.
Shout out to the creator of this amazing plugin

Thanks for sharing this information.
Can’t this be done in a single script using the settings feature?

Answering my own question. Yes, it is possible. I just created one and a little tutorial. It is a bit tedious to have to create a new macro for each use case, but the script is configurable and shared. I’ve written a little tutorial, but I can only export it in PDF, not sure if there is any other way.

This is the workflow we are aiming at, right?

1 Like

In case anyone wants the script, here it is:

module.exports = {
    entry: async (QuickAdd, settings) => {
        const folderName = settings.folderName;
        const files = await QuickAdd.app.vault.getFiles();
        const { quickAddApi: { suggester } } = QuickAdd;
        const filteredFiles = files.filter(file => file.path.includes(folderName));
        const pickedFile = await suggester(
            (file) => file.basename,
            filteredFiles
        );
        QuickAdd.variables.pickedFileName = pickedFile.basename;
        QuickAdd.variables.pickedFilePath = pickedFile.path;
    },
    settings: {
        name: "File picker",
        author: "Danielo Rodriguez",
        options: {
            folderName: {
                type: "text",
                defaultValue: "",
                placeholder: "Folder name",
            },
        }
    },
};
2 Likes

Can you explain the process of creating macro for the same?

quickadd-macro-showing-a-list-of-files-to-use-in-macros.html.zip (828.2 KB)

Let me know if that helps

Hey thanks for the detailed writeup . Really appreciate your effort. I am getting this error when I try to add macro in the last step

Invalid macro name. I have followed the same steps you mentioned . Only changed the folder name to People as that’s what is present in my Vault.

EDIT : I loaded the macro’s first in macro choice and followed the steps. I am able to edit in files. Thanks a lot !

Does it work as you expect now?

Yes it does. Is there anyway I can omit results . for ex we have selected folders for people and resturants etc. Is there anyway I can list files which are in root folder and omit folders like templates, other folders ?

Yes, but for that I will need to update the script to take another option for that, and filter those out. I wanted to add it, but first I just wanted to check the viability of this

1 Like

Oh cool no issues it definitely works the way we intend to . I am easily able to jot down quick points to respective notes. Quickadd has a handy feature to insert after mentioned place . So I am using that !

const search_terms = ['vocabulary', '-words'];
const settings = {
  // unnecessary
  name: 'File picker',
  options: {
    folderName: {
      type: 'text',
      defaultValue: '',
      placeholder: 'Folder name',
    },
  },
};

module.exports = async (internals) => {
  await entry.call(this, internals);
  return internals;
};

async function entry(internal) {
  const files = await internal.app.vault.getMarkdownFiles();
  const { suggester } = internal.quickAddApi;

  const filteredFiles = files.filter(filterByPath);
  function filterByPath({ path }) {
    return search_terms.some((search_term) => path.includes(search_term));
  }

  const pickedFile = await suggester(suggestByBaseName, filteredFiles);
  function suggestByBaseName({ basename }) {
    return basename;
  }

  internal.variables.pickedFileName = pickedFile.basename;
  internal.variables.pickedFilePath = pickedFile.path;
}

here’s the script for filtering the file list.

You should make it configurable

1 Like
module.exports = {
  entry: async (QuickAdd, settings) => {
    const folderName = settings.folderName;
    const excludedFoldersInput = settings.excludedFolders;
    const excludedFolders = excludedFoldersInput
      .split(',')
      .map((folder) => folder.trim());

    const files = await QuickAdd.app.vault.getFiles();
    const {
      quickAddApi: { suggester },
    } = QuickAdd;

    const filteredFiles = files.filter((file) => {
      const isIncludedFolder = file.path.includes(folderName);

      if (excludedFolders.length > 0) {
        return (
          isIncludedFolder &&
          !excludedFolders.some((excluded) => file.path.includes(excluded))
        );
      } else {
        return isIncludedFolder;
      }
    });

    const pickedFile = await suggester((file) => file.basename, filteredFiles);

    QuickAdd.variables.pickedFileName = pickedFile.basename;
    QuickAdd.variables.pickedFilePath = pickedFile.path;
  },
  settings: {
    name: 'File picker',
    author: 'Danielo Rodriguez',
    options: {
      folderName: {
        type: 'text',
        defaultValue: '',
        placeholder: 'Folder name',
      },
    },
  },
};

Here is the updated code which is configurable . We can specify the folders as @danielo515 mentioned.
More intuitive way would be to select folders like checkbox to exclude, but I am not sure how to proceed with that .
Thanks again for the help !

1 Like