Jump to content

Script Filter JSON: parameter for "do not update knowledge / latching"


luckman212

Recommended Posts

Problem:

 

I have some script filters where I wish the items to be listed in the precise order they were output by the script.  BUT, I also want to maintain the selected/highlighted item even when changing the arguments in Alfred's input box. Currently, to do that you must set a uid: within your JSON (ref.). The problem with this is, as soon as you action your first item from that script, the next time you invoke it, that item is floated to the top. So, catch-22.

 

My "Poor Man's Solution"

 

I wrote this small script that wipes out Alfred's knowledge for a specific script filter object after actioning. This works, but feels like a pretty ugly and inefficient hack.

 

Call the script after your script filter using bash and pass as a paramter the name of your script filter object e.g.

#!/usr/bin/env bash
nohup "alfred_reset_knowledge.sh" "MyFancyScriptFilter" &

 

*nb: requires: jq and plist2json.py

#!/usr/bin/env bash

[ -n "$1" ] || exit

# obtain object ID
KDB="$HOME/Library/Application Support/Alfred/Databases/knowledge.alfdb"
mapfile -t objIds < <(
  plist2json.py info.plist |
  jq -r --arg name "$1" 'objects.objects |
    map(select(
      .type=="alfred.workflow.input.scriptfilter" and 
      .config.keyword==$name
    ))[] | .uid')

if (( ${#objIds[@]} > 0 )); then
  # short pause to allow Alfred to upate SQLite db
  sleep 1
  for oId in "${objIds[@]}"; do
    #reset knowledge
    echo "resetting knowledge for object $oId" 1>&2
    sqlite3 "$KDB" "DELETE FROM 'latching' WHERE item LIKE \"${oId}%\";"
    sqlite3 "$KDB" "DELETE FROM 'knowledge' WHERE item LIKE \"${oId}.%\" AND hidden IS NOT 1;"
  done
fi

 

Wish:

- a parameter we could use within the script filter JSON to indicate to Alfred NOT to update the knowledge db when actioning this item (or the entire script). E.g.

 

single item:

{
  "uid": "foo123",
  "title": "Foo",
  "arg": "123",
  "knowledge": false  <==
}

 

entire script filter:

{
  "rerun" : 1,
  "knowledge": false,  <==
  "items": [
    ...
  ]
}

 

Edited by luckman212
Link to comment
Share on other sites

There is an efficient solution to this, which I use in RecentlyAdded.


For clarity, I’ll use ENV[varName] when referring to an environment variable, and varName when referring to a variable (or preferably constant) in your code. 


  1. Check if ENV[uidSeed] exists.
  2. If yes: make uidSeed with the contents of ENV[uidSeed].
  3. If not: make uidSeed something unique. Good pick: random number. Better pick: current date (year, month, day, hour, minute, second).
  4. When you output your Script Filter JSON, append uidSeed to the uid of every item and add it in variables.


What this means is that if your Script Filter was just launched, the steps above will execute 1 → 3 → 4. But on every rerun, it will be 1 → 2 → 4. This creates what you seek: results which are aware of themselves only during the current session.

Link to comment
Share on other sites

Thanks @vitor for your always inspiring and clever solutions. But, I think in this case, it wouldn't work for me, because I am not using rerun. I am talking about typing in Alfred's box, which causes the script filter to re-execute completely. I guess I could store the uidSeed on disk somewhere and check if its mtime is >5 sec old or something but that seems about as clunky as what I've come up with before.

 

I can share my workflow if you want, it's called "border" and allows you to pick images from your clipboard history and apply borders & shadows (uses ImageMagick under the hood) of various sizes and colors to them... 

 

image.thumb.png.795bc2430fd5e2da74b94d9dea2051a9.png

Link to comment
Share on other sites

7 minutes ago, luckman212 said:

I am not using rerun. I am talking about typing in Alfred's box, which causes the script filter to re-execute completely.

 

I got that, but it should work the same for both cases. From the docs (emphasis mine):

 

Quote

Variables can be passed out of the script filter within a variables object. (…) Secondly, any variables passed out of a script will be passed back in as environment variables when the script is run within the same session. This can be used for very simply managing state between runs as the user types input or when the script is set to re-run after an interval.

 

7 minutes ago, luckman212 said:

I can share my workflow if you want

 

Sure. If you’ve tried the above and confirmed it’s not working, I’ll take a look and try to understand why.

Edited by vitor
Link to comment
Share on other sites

  • 3 months later...
  • 1 month later...

Ah, I thought you were already using it! Had I realised you were waiting on the docs, I’d have posted a snippet sooner. Yes, you got it right (don’t forget the quotes, though), you add it at the top level. Taking from your code in the first post:

 

{
  "rerun" : 1,
  "skipknowledge": true,
  "items": [
    ...
  ]
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...