Jump to content


  • Posts

  • Joined

  • Last visited

Posts posted by pdazero

  1. Hi @swissmanu this works as advertised but it's slower than File Filter (I have several thousand files). Also I've becoming increasingly uncomfortable with scripts like these (checkout the awesome Acidham markdown script) for the same reason, just not snappy on a large note vault.


    I ended up doing an alternate approach:

    - Usual File Filter (filename and contents) on my markdown vault

    - If I want to create a new markdown note, I press a predefined KEY COMBO

    - This KEY COMBO runs a Keyboard Maestro script that runs copies the original query by means of cmd-a + cmd-c, strips Alfred keyword, creates file and finally opens it



    The best solution would be to have an option always add custom actions to File Filter (probably to other filters as well).


    Other workaround would be to store the original query to work with it later with a key modifier action and discard the selected file (if existed) + default callback. But this seems that hasn't been implemented yet, it's on Feature Requests:




  2. @deanisheThank you. I have to say this was a huge feat for me, but finally managed to do it. I first had to learn javascript arrow functions, what the hell is objc.unwrap() and other spices lol.


    Here is the final run function from CalendarEvents.scpt:

    function run(argv) {
    	if (!haveAccess()) {
    		return JSON.stringify({error: 'No Access to Calendars', events: []})
    	let days = 7,
    		events = [],
    		formatter = $.NSISO8601DateFormatter.alloc.init
    	// convert all times to local time because Python sucks at timezones
    	formatter.timeZone = $.NSTimeZone.localTimeZone
    	if (argv.length > 0) days = parseInt(argv[0], 10)
    	let arr = getEvents(days),
    		ekEvents = arr[0],
    		colours = arr[1],
    		attendees = [],
    		strAttendees = ''
    	ekEvents.forEach(event => {
    		if (event.status === $.EKEventStatusCanceled) return
    		if (event.allDay) return
    		let title = ObjC.unwrap(event.title),
    			url = ObjC.unwrap(event.URL.absoluteString),
    			notes = ObjC.unwrap(event.notes),
    			location = ObjC.unwrap(event.location)
    		// Clean attendees
    		while (attendees.length > 0) {
    		if (event.hasAttendees) {
    			ObjC.unwrap(event.attendees).forEach(a => {
    			strAttendees = attendees.join();
    		// ensure these have values otherwise they'll be omitted from
    		// JSON output because they're undefined
    		title = title ? title : ''
    		url = url ? url : ''
    		notes = notes ? notes : ''
    		location = location ? location : ''
    			uid: ObjC.unwrap(event.eventIdentifier),
    			title: title,
    			url: url,
    			notes: notes,
    			location: location,
    			attendees: strAttendees,
    			account: ObjC.unwrap(event.calendar.source.title),
    			calendar: ObjC.unwrap(event.calendar.title),
    			calendar_id: ObjC.unwrap(event.calendar.calendarIdentifier),
    			start_date: ObjC.unwrap(formatter.stringFromDate(event.startDate)),
    			end_date: ObjC.unwrap(formatter.stringFromDate(event.endDate)),
    			colour: colours[ObjC.unwrap(event.calendar.calendarIdentifier)],
    	events.sort((a, b) => {
    		if (a.start_date < b.start_date) return -1
    		if (a.start_date > b.start_date) return 1
    		if (a.title < b.title) return -1
    		if (a.title > b.title) return 1
    		return 0
    	console.log(`${events.length} event(s)`)
    	return JSON.stringify({error: null, events: events})

    So, I modified a bit your suggestion in order to pass a comma-separated list of the attendees. I had to did this because it looks I had troubles with passing an array.


    Then, edited main function on video-conferences.py (just an excerpt):


        icons = Icons(wf.cachefile('icons'))
        for d in events:
            subtitle = u'{}–{} on {} // {} ({})'.format(
                d['calendar'], d['account'])
            it = wf.add_item(d['title'], subtitle, arg=d['url'], valid=True,
            it.setvar('calendar_name', d['calendar'])
            it.setvar('event_id', d['uid'])
            # PDAZERO: Set url to zoom scheme (in case it's zoom)
            zoom_url_match = re.search('https://[a-z0-9]+\.zoom\.us/[a-z0-9_.-]+/(\d+.*)',d['url'])
            if zoom_url_match:
                it.setvar('zoom_url','zoommtg://zoom.us/join?confno=' + zoom_url_match.group(1))
            if d['attendees'] is not None:
                strAttendees = ''
                attendees = d['attendees'].split(',')
                for attendee in attendees:
                    strAttendees = strAttendees + "\n- " + attendee
                it.setvar('attendees', strAttendees)
                del strAttendees
                it.setvar('attendees', '')

    Later on, I just pass the attendees var to the clipboard and paste it on my markdown minute. I'll work now in building the minute from scratch because I still have friction in that part of my everyday routine.


    BTW I'm also using https://www.aaronsaray.com/2020/leave-zoom-with-alfred "lz" alfred command to just leave the meeting right now without fiddling with the exit buttons.


    Thanks again !

  3. 6 hours ago, infinite_okay said:

    I've been interested in the zettelkasten filing method and have been tying to find a way to prefix the {date} to the name of the file when its being created, specifically "YYYYddmmHHMM". So that when you input for {title}, title="{date}(input).md."


    I did a small hack to this alfred-note workflow (scroll back a few posts and you'll see  it), but the code is deleted every time the workflow is updated. What I use now is a keyboard maestro macro that paste the current ZettelID, so I do Alfred "mdc (key combo) title bla bla" and I get proper zettel filename.

  4. On 7/22/2020 at 10:45 AM, pdazero said:

    Ok, I think I found some additional unicode-related bugs.


    @Acidham thank you for your continued development on this superb workflow ! I update the bugs above in 3.0.0:


    1) Filename "Planificación status.md"


    Alfred "mds planificación" didn't find any files!

    Partially fixed. Now it finds exact "planificación" matches on filenames, but did not find matches inside note files.


    2) Tag with accents don't work well "#PlanificaciónEstratégica"


    Alfred "md#planif" shows a hit of "planificacio" tag (does NOT exist) and after pressing enter no notes are shown

    This is fixed, and shows both tags "#planificación" and "#planificaciónestratégica"


    Alfred "md#planificació" shows hits of "planificación" (does NOT exist) and "planificaciónestrate" (does NOT exist) , after pressing enter on either no notes are shown

    New behavior: Alfred "md#planificació" does not show any hits, but should show the same hits as "md#planif".


    Alfred "md#planificaciónestratégica" shows  "planificaciónestratégica" (does exist), after pressing enter no notes are shown

    New behavior: Alfred "md#planificación" and "md#planificaciónestratégica", same problem, no hits whatsoever.


    Thanks !

  5. Ok, I think I found some additional unicode-related bugs.


    1) Filename "Planificación status.md"

    Alfred "mds planificacion" does NOT find that file,  but did find other files that have the "planificacion" word (without accents) inside the note

    Alfred "mds planificación" didn't find any files!

    Alfred "mds planificaci" found all files, with and without accents.


    2) Tag with accents don't work well "#PlanificaciónEstratégica"

    Alfred "md#planif" shows a hit of "planificacio" tag (does NOT exist) and after pressing enter no notes are shown

    Alfred "md#planificació" shows hits of "planificación" (does NOT exist) and "planificaciónestrate" (does NOT exist) , after pressing enter on either no notes are shown

    Alfred "md#planificaciónestratégica" shows  "planificaciónestratégica" (does exist), after pressing enter no notes are shown


    You can replicate my adding the attached MD file: https://www.dropbox.com/t/GLIPNt6Pu5tk1MJ9


    BTW If you bear with me learning, I would happily invest time in suggesting code to fix these problems, but I need to know where to start. I'm overwhelmed by this unicode hell hehe.




  6. 5 minutes ago, Acidham said:

    What was the action until error was thrown? e.g. create note, Create MD Link, etc


    Which version of the Workflow are u using?


    First Search ('mds'), then actions menu (apple key + enter) and the menu does not display.


    Latest version: 2.4.0 with my humble addition (zettel id)

  7. 12 hours ago, Acidham said:

    Can you provide me with the filename or at least an example? I need to reproduce the issue on my end. 



    202007140936  Presentación Status.md

    Sorry its not "tilde"  but "spanish accent",  I got lost in translation...

  8. Hi @Acidham I think I might found a bug. I have files with tildes on them (spanish filenames) and I found this error on debug:

    File "/Users/xyz/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.CD0290B9-FE6D-4D27-9D91-7686F6F93660/search_actions.py", line 35, in <module>
        "arg": u"{0}|[[{2}]]({2})".format("link", note_title, os.path.basename(note_path)),
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xcc in position 24: ordinal not in range(128)


  9. @deanishe Thank  you for this, it's great !


    I tweaked it a little bit, in order to just join the ZOOM meeting without having to open a browser tab. I'm new to Alfred and Python so it's only a humble hack, with hardcoded regex. 


    I used Zoom url-scheme, as per https://marketplace.zoom.us/docs/guides/guides/client-url-schemes


    In video-conferences.py: 

    (Around line 261....)
    it.setvar('event_id', d['uid'])
    # PDAZERO: Set url to zoom scheme (in case it's zoom)
    zoom_url_match = re.search('https://[a-z0-9]+\.zoom\.us/[a-z0-9_.-]+/(\d+.*)',d['url'])
    if zoom_url_match:
      it.setvar('zoom_url','zoommtg://zoom.us/join?confno=' + zoom_url_match.group(1))

    And then open url with the "zoom_url" variable. If you are interested maybe you could do this a lot cleaner but my coding skills are not at their best today. Thanks again for this workflow.

  10. Absolutely agree with you. I think note taking is a very personal thing. I actually don't do a "proper" Zettelkasten, just taking what I like and works for me. Been to lot of note taking apps but the simplicity of md files is my new wave.


    Do note that the Zettel ID is not client nor app dependent though. Just a naming convention.


    I read in one of the posts that your scripts "auto-update"? How is that so? It would break my zettel id naming hack?

  11. @Acidham my main source of Zettelkasten wisdom comes from the forum at zettelkasten.de. I'm impressed of the several high quality and well thought topics there, rather  than talking about an app it's more about the philosophy of knowledge management.




    I'm also enjoying conversation on bear subrredit, obsidian forums and now this forum. I avoided alfred for years but Spotlight for some reason started to misbehave, couldn't fix it and MacOS reinstall is out of the question. Well, and also I migrated from Bear to local-notes paradigm.


    The reason I'm using the Zettel IDs is  that I liked the way I can sort by name in Finder, Windows or any app really. I've found that file modification dates can be messy, specially when synchronization is at works with the likes of Dropbox or Icloud. I'm intrigued also by this "Unique ID", even though I still haven't really found a use case for that, at least in my workflow - mainly because I've been a lazy note linker. Not being particularly disciplined in this means I must not ever change  the filename of the note, even though  I might have thought a better name, because  it can break MD links.


    BTW I don't use that YAML header I see in the template of your workflow. Why you see the need of that header? In my case:

    1- The creation date is on the file (although not reliable) and the Zettel ID (though you are forced to set up that ID)

    2- Tags might be mentioned in any part of the note. Actually I use to set them at the bottom because it's not important for the content, just for finding the right note. Also it's easy to batch add tags on expression-matching notes by appending text just with bash.


  12. @Acidham thank you a lot for this, it's a great workflow. Im using zettelkasten id's on my md filenames, I added this two lines of code on the getTargetFilePath function:


            zettelid = self.getTodayDate("%Y%m%d%H%M")
            file_name = Tools.strJoin(zettelid,' ',file_name)

    Maybe you could set up a env var for that option. I don't know Python, I just arranged this humble add-on copying and pasting from the rest of the code :)


  • Create New...