Jump to content

deanishe

Member
  • Posts

    8,759
  • Joined

  • Last visited

  • Days Won

    522

Reputation Activity

  1. Like
    deanishe got a reaction from smarg19 in Workflow development   
    That reminds me. I uploaded my build script as smargh requested. It's fairly basic and only designed to work with workflows structured the same way as mine, i.e. all the files that should go in the distribution are in a single directory. It will automatically name the generated .alfredworkflow with the workflow's name grabbed from info.plist.
     
    Regarding other types of files:
     
    You can keep all the non-workflow files in your project root directory. For testing purposes, you can add a test runner to the same directory that creates the requisite test environment (e.g. adjusting sys.path, simulating Alfred's execution environment).
     
    I've found that the problem with relying on your build system to filter out any files that shouldn't end up in the workflow distribution is that it's one more thing that you have to remember to update when you change something. It's very easy to forget to exclude some big file you've added or include an essential one (at least, it's something I find very easy to forget).
     
    As a result, I try to organise my workflows so that there's a subdirectory that corresponds precisely to the distributed workflow. That way, it doesn't require me to work actively to stop things breaking.
  2. Like
    deanishe got a reaction from rice.shawn in Anyway to delay script filter from running (ie. wait until user has stopped typing or at least paused)   
    Heh. Didn't realise there were that many.
     
    SIGXFSZ: "File size limit exceeded". More like "Epileptic fit at keyboard".
  3. Like
    deanishe got a reaction from CJK in Workflow development   
    I start off with a project directory in ~/Code (where I keep my, well, code), usually named alfred-<worklflowname>.
     
    This directory is a git repo, which will probably go on GitHub.
     
    The actual source code goes in a src subdirectory. That way I can keep things that don't belong in the distributed workflow in the project (README.md, the compiled .alfredworkflow file, helper scripts or source graphics).
     
    I create an empty workflow in Alfred and add the icon. Then I copy the contents of it over to the src subdirectory I made. Then I delete the workflow in Alfred.
     
    I have two scripts to help with writing workflows. workflow-build.py creates the .alfredworkflow file from the specified directory. It's aimed at Python workflows and ignores .pyc files. workflow-install.py installs the workflow to Alfred's workflow directory (using the bundle ID as its name). Most importantly workflow-install.py -s symlinks the source directory instead of copying it, so I can keep the source code with my other code, not in Alfred's settings dir.
     
    I also write workflows in Sublime Text 3 (usually). I run them in iTerm, though, not in ST's terminal. I find ST's terminal isn't very reliable and chokes on a lot of output. It's also not great when the script needs arguments, which is often.
     
    The downside of using iTerm is that it uses my shell environment, not Alfred's, but I'm careful about keeping my system Python fairly pristine.
     
    I generally try to write workflow scripts as command-line apps, i.e. one main script that takes options and arguments, rather than a bunch of separate scripts. I find this helps me design the app in a more sensible way. If the workflow needs a whole bunch of action scripts, I also prefer to keep these all in the same script and Run Script action (I add the options to {query}). That way I don't have dozens of elements in Alfred's UI, which is a PITA to manage.
     
    The thing to watch out for when doing this is your imports. If everything is in one script, you'll likely end up importing a bunch of libraries that won't be needed, which slows the script down. If I'm using libraries that are slow to import (OS X-native ones, like Foundation or AddressBook are the worst), I import them in functions that use them, not at the top of the script.
     
    With something as big as ZotQuery, I'd still go with one main script and one main application class, but add sub-applications behind keywords, much like git or pip works.
  4. Like
    deanishe got a reaction from frankspin in Workflow Library for Python   
    I'm afraid I don't quite understand what it is you're trying to do or what you think would be overwritten/replaced.
     
    If you just want to store multiple accounts/datasets in parallel, you might create a dictionary saved via the settings/stored data API that maps account names to a prefix, then use the appropriate prefix for the account in your caching/data/Keychain keys:
     
    # `account name:prefix` mapping, e.g. {'Personal': 'account1', 'Work':'account2'} accounts = wf.settings['accounts'] # or accounts = wf.stored_data('accounts')   account = 'Personal' prefix = accounts[account]   api_key = wf.get_password('{}-apikey'.format(prefix)) def wrapper(): url = 'https://api.example.com/v1/whatever.json' r = web.get(url, params={'api_key':api_key}) return r.json() some_cached_data = wf.cached_data('{}-thedata'.format(prefix), wrapper, max_age=0) ... ... Thus, some_cached_data would be stored under the key (filename) account1-thedata for account Personal and account2-thedata for account Work.
  5. Like
    deanishe reacted to vitor in Run Command — Run commands using your shell configuration   
    Those specific commands work fine because they’re extremely limited, can’t act on selected items, rely only on system commands, and don’t take into account your own choices/customisations. This workflow was made exactly to bypass those limitations.

    If you have selected files/directories (or just a Finder window open in front) and want to act directly on them without having to write their path on Alfred, you need some of this extra complexity. The workflow also takes into account if you use zsh instead of bash, which matters if you’re used to the small differences between them. It also matters to read your shell’s startup files (which Alfred does not do on its own), which will load your specific configurations, like aliases and your PATH, which in turn allows you to run tools you have installed yourself that might reside in specific locations (like the ones installed via homebrew).

    Your example works only on extremely basic examples that have, for the most part, no practical use. Most of the time you need to do something custom, something that works like your shell, the way you have it configured, does. A simple /bin/bash Run Script block gives you nothing more than what the terminal does as soon as you install the system; RunCommand gives you your environment, the way you’ve set it up, and the possibility to act directly on selected items.
  6. Like
    deanishe got a reaction from OSchrock in Workflow for copying URL and Page Title and then Pasting as HTML link   
    Vitor has a bunch of AppleScripts that can get the URL and title of the frontmost tab.
     
    That should get you started.
  7. Like
    deanishe got a reaction from dfay in Using JavaScript for Automation   
    I was referring to the post before the post that you're referring to. The post above my post that says almost the same thing is not the post I was referring to, but rather the post before the post above my post that says almost the same thing as the post I made that isn't the post I'm referring to.
     
    It would be silly to refer to a post that said the same as the post that preceded the post I would, in this case, be referring to.
     
    Which is why I'm referring to the post I made before that post. The one that didn't say the same as the post that you think says the same as the post I'm not referring to. Which is not the post I meant.
  8. Like
    deanishe got a reaction from smarg19 in Using JavaScript for Automation   
    I was referring to the post before the post that you're referring to. The post above my post that says almost the same thing is not the post I was referring to, but rather the post before the post above my post that says almost the same thing as the post I made that isn't the post I'm referring to.
     
    It would be silly to refer to a post that said the same as the post that preceded the post I would, in this case, be referring to.
     
    Which is why I'm referring to the post I made before that post. The one that didn't say the same as the post that you think says the same as the post I'm not referring to. Which is not the post I meant.
  9. Like
    deanishe got a reaction from nesono in bash script workflow artificially serialized   
    It's not a problem with the mvim script, it's due to the way Alfred runs scripts. Alfred (correctly) doesn't consider a script finished while its STDOUT and/or STDERR are still open (i.e. there may still be some output to come), so to get Alfred to consider a backgrounded process finished, the process has to disconnect from or close STDOUT & STDERR:
     
    MVIM=/usr/local/bin/mvim case "{query}" in "h") cd ~/ && $MVIM > /dev/null 2>&1 ;; "d") cd ~/Downloads && $MVIM > /dev/null 2>&1 ;; *) echo "unknown directory specified" ;; esac
  10. Like
    deanishe got a reaction from pablojimeno in Pocket for Alfred   
    BTW, anyone who hasn't see the bookmark in the demo gif "The Beach Boys Shred I Get Around" really needs to see it
  11. Like
    deanishe got a reaction from idea4IT in Modifiers can alter item values other than subtitle   
    So, this popped up over in the help forum, but this is a better place for it to solicit feedback, methinks.

    Currently, Alfred allows you to specify alternate subtitles for the result items returned by Script Filters, so that you can let the user know which action would be run.

    Looks like this:
    <item arg="/path/to/Ideas.txt" uid="/path/to/Ideas.txt" valid="yes"> <title>Ideas.txt</title> <subtitle>Open file</subtitle> <subtitle mod="cmd">Reveal file in Finder</subtitle> <subtitle mod="alt">Trash file</subtitle> </item> Whereby the Script Filter is connected to three different Actions.
     
    The suggestion is to turn the alternate subtitles "inside out" and add a <mod> (or <alternate>) tag that can override not just the subtitle, but any of the item's parameters (that make sense):
    <item arg="/path/to/Ideas.txt" uid="/path/to/Ideas.txt" valid="no"> <title>Ideas.txt</title> <subtitle>Search in Ideas.txt</subtitle> <icon type="fileicon">/path/to/Ideas.txt</icon> <mod key="shift" valid="yes" arg="/path/to/Ideas.txt"> <subtitle>Open this file</subtitle> <!-- the super-smart workflow has figured out the default app for this filetype --> <icon type="fileicon">/Applications/Sublime Text.app</icon> </mod> <mod key="cmd" valid="yes" arg="/path/to/Ideas.txt"> <subtitle>Reveal in Finder</subtitle> <icon type="fileicon">/Applications/Finder.app</icon> </mod> <mod key="alt" valid="yes" arg="/path/to/Ideas.txt"> <subtitle>Trash</subtitle> <icon type="icon">trash.png</icon> </mod> </item> This would have a few advantages:
    It's possible to set an item to invalid for if, say, you want to require an additional argument by default, but override that in alternate actions. Currently, an action is always valid or never valid (this was the starting point). You can change not just the subtitle, but also the title and/or the icon, providing more and better contextual information (don't forget, some users turn off subtitles) You can change the arg. This means you can avoid a plethora of Run Scripts/Open URL actions and instead generate alternate URLs (e.g. to different search engines) right in your Script Filter and connect it to just one Open URL action. The same goes for copying different representations of data (e.g. colours, emoji or other non-ASCII text) to the pasteboard. (This would also require Alfred to allow multiple connections to the same Action/falling back to the "bare" action if there isn't another connection for the modifier) By avoiding hard-coded actions, it makes it easier to allow users to configure workflows without having their changes overwritten by a workflow update (which necessarily happens to any user-added actions and connections in a workflow) It wouldn't make sense to be able to override all of an item's options (e.g. uid, copy text and large text).
     
    It strikes me (and Florian) as a powerful addition.
     
    What do you think?
  12. Like
    deanishe reacted to Andrew in Modifiers can alter item values other than subtitle   
    Yep, I really like this. It would take a bit of an architectural change (allowing a single result item to have multi state validity) so it may not be a minor release... but I can definitely see something like this coming to workflows!
  13. Like
    deanishe got a reaction from Florian in Can a script filter result be valid only for certain modifiers?   
    Perhaps you could twizzle the <subtitle mod="cmd"> XML into a mod tag:
    <mod key="cmd" valid="yes">    <subtitle>My alternate subtitle</subtitle>    <arg>my alternate arg</arg> </mod> Having (optional) alternate args would make it easier to, say, open URLs to different websites or copy different formats of dates/colours/whatever to the clipboard without having to wrangle half a dozen Run Script/Open URL/Copy to Clipboard actions.
     
    It'd also make it easier for workflows to manage their own configuration without having to re-write their own info.plist, which is not an optimal solution.
  14. Like
    deanishe got a reaction from Andrew in Can a script filter result be valid only for certain modifiers?   
    Perhaps you could twizzle the <subtitle mod="cmd"> XML into a mod tag:
    <mod key="cmd" valid="yes">    <subtitle>My alternate subtitle</subtitle>    <arg>my alternate arg</arg> </mod> Having (optional) alternate args would make it easier to, say, open URLs to different websites or copy different formats of dates/colours/whatever to the clipboard without having to wrangle half a dozen Run Script/Open URL/Copy to Clipboard actions.
     
    It'd also make it easier for workflows to manage their own configuration without having to re-write their own info.plist, which is not an optimal solution.
  15. Like
    deanishe got a reaction from dfay in [REQUEST] Anki Workflow to Create Cards   
    I don't use Anki (the price of the app on iOS is ridiculous), but I use flashcards a lot (I had about 10,000 last time I looked).
     
    What I do is create the lists as TSV (tab-separated) files in a text editor and have a script to convert the TSV files into an importable format, e.g. .studyarchive files for Mental Case or a differently-formatted TSV for Flashcards Deluxe.
     
    It's hard to imagine a more efficient input interface than an editor, and I think it'd be a better investment of time creating a syntax definition for an editor than trying to coerce Alfred into working as a flashcard editor.
  16. Like
    deanishe got a reaction from frankspin in Navigate web results similar to folder navigation   
    I'm not a big fan of the external triggers method, as I prefer to keep as much of the complexity as possible in my code, where I can comment it, and out of Alfred's UI where it can be difficult to maintain an overview of which element does what (it's not possible to show a connection between a run script action and the external trigger it calls, for example). It's also a lot easier to refactor a workflow in a code editor than in Alfred's UI.
     
    What I'd do in this situation is to create a "multi-level" query using a delimiter, e.g. 〉, and show results according to the query.
     
    Thus, tlo would show a list of all boards. Hitting ENTER or TAB on a board would autocomplete the query to 'tlo board name 〉 ' (note the trailing space—it's important), and your script filter would then show a list of that board's lists. 'tlo board name 〉 blah' would filter the board's lists on blah. Hitting ENTER or TAB on a list expands the query to  'tlo board name 〉 list name 〉 ' (trailing space again) and your script filter shows the contents of the list and so on.
     
    The trailing space is important because you can use that to jump back up a level: if the user deletes the trailing space (i.e. the query now ends with 〉, you pop the last level off the query and go back to the previous list.
     
    Carlos's Recent Items workflow uses this technique, as do my Smart Folders and Packal Search workflows. My workflows might be of more use to you as a guide, as they're written in Python (which I think you're using, too).
  17. Like
    deanishe reacted to vitor in bash script workflow artificially serialized   
    Building (stylistically) on deanishe’s answer, you can shorten > /dev/null 2>&1 a bit by using &> /dev/null. As in
    MVIM=/usr/local/bin/mvim case "{query}" in "h") cd ~/ && $MVIM &> /dev/null ;; "d") cd ~/Downloads && $MVIM &> /dev/null ;; *) echo "unknown directory specified" ;; esac
  18. Like
    deanishe got a reaction from frankspin in Workflow Library for Python   
    The idea of cached_data() is to avoid generating/fetching data if the cache is up-to-date. So, instead of passing it the data it should cache, you pass it a function it can call to get fresh data if the cached data is too old/non-existent.
     
    You're passing the results of a call to getBoards(). You need to pass the function itself, which cached_data() will then call if necessary.
     
    Normally, that looks something like this:
     
    def fetch_new_data():     # grab data from a web service/app here     # ...     return new_data data = wf.cached_data('cache-name', fetch_new_data, max_age=600)  
     Note that I'm passing fetch_new_data not fetch_new_data() to cached_data(), i.e. the function itself, not the data returned from calling the function.
     
    You can't just pass the function in this case, however, as getBoards() takes an argument.
     
    Check out the example script here. Look at the wrapper function and the call to cached_data() (lines 82–89). Note that I pass wrapper to cached_data without calling it.
     
    You could also pass lambda api_key: getBoards(api_key) or functools.partial(getBoards, api_key). I wrote a separate wrapper() function in the tutorial to make it clearer and more explicit (lambda is ugly).
     
    Does that help?
  19. Like
    deanishe got a reaction from mklement0 in Add a version field for workflows   
    There's Packal, which is the de facto central repository for workflows. Shawn, the creator, is also working on a workflow to automatically update any workflows that you've installed from Packal (you have to submit a version number when you upload one to Packal). For the time being, I wrote a workflow to search Packal, which can also tell you which of your workflows are updateable.
    Ideally, Packal would be "advertised" more clearly on this board: a forum is really not a great platform for showcasing/discovering workflows (or collecting tutorials/documentation etc.).
  20. Like
    deanishe got a reaction from rice.shawn in JavaScript is the new automation language in Yosemite   
    I really like 80's music. That doesn't mean it isn't awful…
  21. Like
    deanishe got a reaction from rice.shawn in JavaScript is the new automation language in Yosemite   
    Wouldn't have been my first (or even fourth) choice as a new scripting language of OS X, but it sure is a massive improvement on AppleScript.
     
    Man, I hate that language. This is one time I'll be happy to reimplement loads of my code in a new language.
  22. Like
    deanishe got a reaction from smarg19 in MailTo: Select multiple Contacts *and* Groups and compose in your favourite email app   
    I have at least 8 Gmail accounts and an iCloud one as well, I think. At any rate, it's not actually necessary to be able to send or receive mails, just to run the program in order to test the workflow.
     
    So, yeah, I could definitely use one of these "beta-coins" shimmy-tangs in order to test the workflow.
     
    I'm up to my neck in work at the moment, however, so I can't promise that I'll be able to fix 'er up this weekend. It shouldn't be a big deal (max. 30 minutes is my optimistic/naïve estimate), but if it is, it'll have to wait.
     
    Also, looking over the code, I'm almost overwhelmed by the urge to totally rewrite/refactor it.
     
    If I could easily understand what my own code is doing, I probably would have already…
     
    Comment your code, boys and girls. Comment it for a clueless person. Because you'll come back to it a year later, and that clueless person will be you 
  23. Like
    deanishe got a reaction from TFV in Packal Search — search for cool new workflows from the comfort of Alfred   
    Packal.org Alfred Workflow Search  
    Search Packal.org's collection of workflows from the comfort of Alfred.  
     
    Downloading
    Get the workflow from GitHub or Packal.
     
    Usage
     
    packal workflows [query] — View/search for workflows by name/category/author/tag ↩ — Open workflow page on Packal.org in your browser ⌘+↩ — View/search workflows by the same author  
    packal tags [query] — View/search workflow tags ↩ or ⇥ — View/search workflows with selected tag  
    packal categories [query] — View/search workflow categories ↩ or ⇥ — View/search workflows in selected category  
    packal authors [query] — View/search workflow authors ↩ or ⇥ — View/search workflows by selected author  
    packal versions [query] — View/search OS X versions and compatible workflows ↩ or ⇥ — View/search workflows compatible with selected OS X version  
    packal status — Show a list of workflows that are out-of-date or are available on Packal.org, but were installed from elsewhere (i.e. they contain no Packal metadata, so can't be versioned by this workflow or updated by the Packal update workflow).  
    Icons
    Sometimes, an icon is shown after a workflow's name. They have the following meanings:
     
     
    Thanks, Licence Thanks to Shawn Patrick Rice for building Packal.org.
    Much use made of docopt and Alfred-Workflow.
    This workflow, excluding the Packal icon, is released under the MIT Licence.
    The Packal icon is the property of Shawn Patrick Rice.
     
     
       
  24. Like
    deanishe got a reaction from brunoc in MailTo: Select multiple Contacts *and* Groups and compose in your favourite email app   
    2015-07-29: Version 2 released
     
    MailTo: Select multiple Contacts and/or Groups, and compose in your favourite email app
     
    Search your Contacts and compose an email to one or more recipients (or none) in your preferred email program. Also supports Groups.
     
    The main aim—versus Alfred's built-in, more comprehensive contact handling—is to make it fast and easy to select multiple recipients and especially groups.
     


    Features
    Search and add recipients from your Contacts database Send to Groups/Distribution Lists (they're the same thing) Also enter email addresses by hand Use any email client you want (uses system default as standard) Results prioritised by order of email addresses in Contacts Download/Installation
     
    Grab your copy from GitHub or Packal. Install in the usual fashion.
     
    Usage
     
    Keyword is @
    @ + ENTER — compose a blank mail (no recipients) @ [part of name or email address] — search your Contacts for matches. You can also add email addresses not in your Contacts. ENTER/⌘+NUM — add selected email address to recipient list and go to email program TAB — add selected email address to recipient list and continue searching mailto — see and change current settings If you've entered an invalid email address, it will be removed from the recipient list when your email app is called. Supported apps
     
    In theory, MailTo should work with any email client (it uses the mailto: protocol).
     
    Tested and working with:
    Airmail 1 Airmail 2 Apple Mail Sparrow Thunderbird Postbox Airmail (email addresses only) Unibox MailMate Mailbox Beta (email addresses only) MS Outlook Google Chrome (if you've set a handler) Fluid single-session browsers Does not work with:
    Safari (it will just open your system default email client) More info
     
    Please see the documentation.
     
    Note on Groups
     
    When deciding which email address to use for members of Groups, MailTo will use the one you've specified, or then the primary email address for the contact (don't ask me how to set that; I haven't been able to figure it out), and then the first one in their list of email addresses.
     
    To specify which address to use for a contact in a Group, open Contacts and go to Edit > Edit Distribution List …
     
    Changelog
     
    2013-10-31
    Add recipient name when calling email client, i.e. "Bob Smith <bob.smith@example.com>" instead of just "bob.smith@example.com". 2013-11-01
    Add support for Groups Prioritise email addresses by primary status then order in Contacts Change ID (cache format has changed) Use MIT licence 2013-11-03
    Change config keywords to mailtoconf and mailtohelp so they don't get mixed in with search results from the default mailto action. 2013-12-03
    Properly format the mailto: URL so workflow works correctly with MailMate. 2013-12-06
    Added built-in, app-specific support for the email clients listed above. They should now work flawlessly without any need to edit settings. Note: the settings format has changed, so all your settings (yes, both of them) have been reset. There should be no need to edit them if you're using MailTo with your default system email client. 2014-03-24
    Fix plist parsing problems. 2014-09-13
    Add support for Mailbox Beta Add new keyword @ 2015-07-29
    Release V2 Supports more types of contact accounts Supports more email clients Users can add support for their own clients 2016-02-10
    Add support for MS Outlook Add support for Airmail 2 Remove duplicates based on name and email address
  25. Like
    deanishe got a reaction from aviris in Random theme within custom ttimeframe + freedom of fonts used   
    With regard to non-default fonts, Alfred could do what CSS does and allow you to specify a list of fonts, and fall back to a built-in font if none of the specified ones are found.
×
×
  • Create New...