Jump to content

DrLulz

Member
  • Posts

    62
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by DrLulz

  1. My initial attempt at an Anki workflow. More to come after boards (have to put away addicting things such as Alfred ). I welcome any and all suggestions. Download, GitHub, Packal. Requirements: Alfred Anki Commands: :anki :aset :apath Anki Terminology: Collection = Group of Decks Notes = Collection of Facts Cards = Representation of Facts A note has a one to many relationship with cards, while a card can have only one associated note. Custom Dark Theme: Cards (notes) created from the workflow use this theme. Once the first card is created (from within workflow) the theme is available within Anki. The theme comes loaded with jQuery v1.11.2 and plugins Zoom, Magnific Popup, Panzoom (mobile only), and Noty. You can find it in Anki under Tools > Manage Note Types > Alfred Dark. If creating cards from inside Anki the theme has optional fields. Front, F NoteFront side, and optional note Back, B NoteBack side and optional note classThe theme default is to center all text. To adjust text to the left enter left in the class field. NotyShow an optional note on the back-side of the card. Good for reinforcement. httpEntering a URL in this field displays a link in the bottom right on the back-side. Accepts www.site.com without http video - Accepts youtube and vimeo urls. Link to the video is displayed in the upper left on the back-side. Workflow Progression: 1. :aset As of now contains two actionable items.Update collection (manual collection refresh) Set Anki collection path (redirects to :apath) :apathThe workflow looks for the Anki collection in the most typical locations. If the path is not found the user will be prompted to enter the path manually.The default directory is /Users/OSX_NAME/Documents/ANKI_USER/collection.anki2 The default ANKI_USER created when Anki is first run is User 1. If you have changed this, enter your Anki user name. If the path is found :apath is only useful if needing to switch between collections. 2. :anki Search the collection for a deckSearch by name, or deck id If the deck doesn’t exist you can create a new deck with the query as the title. Select deck Search for notes within selected deckSearch by facts, or tags If the card is not found you can create a basic, two-sided card (cloze additions on the to-do list). The theme is the custom dark theme described above. Select cardCurrently the only option after selecting a card is to modify its tags. tags are entered as #tag1 #tag2 #tag3 Credits: This workflow uses the python workflow library Alfred-Workflow (by deanishe). The internal structure borrows *heavily* from the FuzzyFolders and Reddit workflows (also by deanishe). The new_card.py was written by (guess who) deanishe, as a demo for my edification. TO-DO: Anki Sync File Action to import csv’s Sort decks by new, reviewing, missed More robust display of deck/card statistics Open Anki to a specific deck Choose model (theme) when adding cards Allow for cloze cards Rename decks
  2. I appreciate the demo. Thank you for that. I'm going with the leveled approach for the "drill-down". The easier the workflow is to navigate the more I use it, so usability and functionality are my top concerns. In the Alfred-Workflow readthedocs tutorial you use argparse, but I've noticed in many of you workflows you use docopt. What's the advantage? Also, in one of my tests I chained a script filter to a run script which saves cached_data before calling a trigger. Its working ok, but is this disadvantageous? It won't be used too often, as I'm shooting for leveled navigation, but its nice to have options.
  3. So, as always it seems, I need to dig a little deeper before asking questions. My first question is outlined, in detail, in the Alfred-Workflow docs under Persistent Data. Please disregard question 1. I'm not a programmer, so I'm really looking for a way to think about structuring this project. Though, I'm sure its hard to say given that I don't have more information regarding the desired goal. I'm trying to prevent a complete rework after I'm months into the project, but then again, that may be just what I need to actually learn something.
  4. I have a few questions regarding workflow structure, storage, and python how-to's. Anki is a flashcard program, it is written in python, and has a sqlite database. 1. In order to connect to the database I need to supply a path. Since I'm using the Anki module alone (without anki's version of PyQt, aqt), I have to supply the path manually. The way I'm doing this is rather costly, and I would like to "store" the path after a successful connection is made, so further instances of the workflow have access to and use this path. Below, I've covered the most likely paths to Anki, but at a later time I would like to ask the user, through Alfred, to input the path if an error occurs. As a point of style, is it customary to import a module within a def? def get_col(): default_locations = [ os.environ['HOME']+'/Anki/User 1/collection.anki2', os.environ['HOME']+'/.anki/User 1/collection.anki2', 'collection.anki2' ] for location in default_locations: if os.path.exists(location): return location else: import glob home_path = os.path.expanduser('~') pattern = (home_path + '/**' + '/Anki' + '/*' + '/collection.anki2') for path in glob.glob(pattern): return path 2. When a result is selected with Alfred, and passed to the next script as the query, how can I get the result of the second script to display in Alfred? The wf.add_item doesn't seem to do it. The script 2, at the end of the post, should display the card count. 3. Besides querying Anki's database, eventually I would like to add cards from Alfred. The flow of the workflow ideally would be to first select a deck, and then options and deck statistics would display below in the results area. One option would be to add a card to the selected deck. After choosing "Add Card" the user would type in the front side, and by some magic of python, the front side text would display as the first result, the input area would clear and allow for the backside to be entered, which would display as the second result before submitting the change. This is why I'm asking for suggestions for structure. Is there a best way to account for these options by structuring the workflow a particular way? Further down the road I could allow for changes to the front or back after the initial input so that mistakes on card entry could be corrected. And much further down, I could allow for images to be attached with Alfred's file action. I've been playing with Anki heavily, I've authored a addon, HTML 2 ANKI (repo), and generally feel confident to start merging what I've learned into an Alfred workflow. 4. Within the workflow I've supplied the Anki module, but to import the module I first have to append the path with sys.path.append, else I receive errors, or run the script from the Anki folder. I did make sure to include __init__.py in all subfolders, however, the Anki module's __init__.py is not empty, and this seems to be the source of my frustration. I won't need the module until I start adding cards with Alfred (Anki says that doing it through the database is not recommended, mentioning that when updating Anki issues may arise), but I wanted to know if appending the path is acceptable here. I'll be sitting for step1 this summer, so I'm just trying to form a plan at this point, but afterwards I'd like to get this going. Anki's popular for people learning new languages, and med students, so I'm hoping it will be of use for a few people. As always suggestions are most appreciated. Script 1: # -*- coding: utf-8 -*- # [Run from subdirectory] import os, sys #abspath = os.path.abspath(__file__) #dname = os.path.dirname(abspath) + '/main' #sys.path.append(dname) # [IMPORT] import re import sqlite3 import json #from anki import storage, stats #from BeautifulSoup import BeautifulSoup, Comment, NavigableString from workflow import Workflow log = None def get_col(): default_locations = [ os.environ['HOME']+'/Anki/User 1/collection.anki2', os.environ['HOME']+'/.anki/User 1/collection.anki2', 'collection.anki2' ] for location in default_locations: if os.path.exists(location): return location else: import glob home_path = os.path.expanduser('~') pattern = (home_path + '/**' + '/Anki' + '/*' + '/collection.anki2') for path in glob.glob(pattern): return path return None def db_decks(db): results =[] deck_db = db.execute("SELECT decks FROM col") decks = json.loads(deck_db.fetchone()[0]) for d in decks.items(): deck = {'title': None, 'id': None} deck['title'] = d[1]['name'] deck['id'] = d[0] log.debug(deck) if deck['id'] is None: continue results.append(deck) return results def key_for_deck(deck): return '{} {}'.format(deck['title'], deck['id']) def main(wf): query = None if len(wf.args): query = wf.args[0] apath = get_col() connection = sqlite3.connect(apath) decks = db_decks(connection) if query: decks = wf.filter(query, decks, key_for_deck) if not decks: wf.add_item('No items', icon=ICON_WARNING) for deck in decks: wf.add_item( title = deck['title'], subtitle = deck['id'], arg = deck['id'] + ' ' + deck['title'] + ' ' + apath, valid = True, icon = 'icon.png') wf.send_feedback() if __name__ == '__main__': wf = Workflow() log = wf.logger sys.exit(wf.run(main)) Script 2: 1. How can I get it's result to display in Alfred? 2. With very large decks (many cards), I get an error saying so, I'm thinking this is the sqlite, ideas? # -*- coding: utf-8 -*- import os, sys, re import sqlite3, json from workflow import Workflow log = None def db_cards(db, did): cards_did = db.execute("SELECT COUNT(*) " "FROM cards " "WHERE cards.did = ?", (did,) ) card_count = cards_did.fetchone() result = card_count[0] return result def main(wf): did, d_title, apath = wf.args[0].split() connection = sqlite3.connect(apath) count = db_cards(connection, did) wf.add_item( title=d_title, subtitle=unicode(count), arg=did, valid=True, icon='icon.png') wf.send_feedback() if __name__ == '__main__': wf = Workflow() log = wf.logger sys.exit(wf.run(main))
  5. Result from terminal. Is this my issue? : drlulz$ env -i runanki env: runanki: No such file or directory
  6. I have an executable located at ~/Documents/anki/runanki echo $PATH = /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin I created an alias in .bash_profile, but I know from searching that Alfred doesn't load the local environment. I would like to call runanki from a run script, but can't figure it out. I don't really care about using the alias in Alfred. Have tried the following, all of which work in the terminal. What is my hangup? /Users/drlulz/Documents/anki/runanki cd ~/Documents/anki runanki shopt -s expand_aliases if [ -f "${HOME}/.bash_profile" ] ; then source "${HOME}/.bash_profile" fi runanki
  7. GitHub link is broke, remove the semicolon it should work.
  8. The version I'm using was downloaded last week from Packal. When I type "pocket wf:reset" and press return nothing occurs visibly, its is as if its waiting for an argument. I assume it would prompt me to reauthorize after running the reset?
  9. Sometimes calling the workflow produces no results when it did previously. If I delete com.fniephaus.pocket from Keychain and run the workflow again everything is fine. Is there something I can do to prevent this behavior?
  10. Possibly you should require an IQ test on certain workflows. Maybe a secret sub-forum where people like me can't access. In my haste I forgot to install pandoc. I guess I thought it was a web service, I'm not sure what I was thinking. Apologies.
  11. (dp0Voutputs p1 (lp2 (dp3 Vdescription p4 VPortable Document Format p5 sVarg p6 Vpdf p7 sa(dp8 g4 Vnative Haskell p9 sg6 Vnative p10 sa(dp11 g4 VJSON version of native AST p12 sg6 Vjson p13 sa(dp14 g4 Vplain text p15 sg6 Vplain p16 sa(dp17 g4 Vpandoc\u2019s extended markdown p18 sg6 Vmarkdown p19 sa(dp20 g4 Voriginal unextended markdown p21 sg6 Vmarkdown_strict p22 sa(dp23 g4 VPHP Markdown extra extended markdown p24 sg6 Vmarkdown_phpextra p25 sa(dp26 g4 Vgithub extended markdown p27 sg6 Vmarkdown_github p28 sa(dp29 g4 VreStructuredText p30 sg6 Vrst p31 sa(dp32 g4 VXHTML 1 p33 sg6 Vhtml p34 sa(dp35 g4 VHTML 5 p36 sg6 Vhtml5 p37 sa(dp38 g4 VLaTeX p39 sg6 Vlatex p40 sa(dp41 g4 VLaTeX beamer slide show p42 sg6 Vbeamer p43 sa(dp44 g4 VConTeXt p45 sg6 Vcontext p46 sa(dp47 g4 Vgroff man p48 sg6 Vman p49 sa(dp50 g4 VMediaWiki markup p51 sg6 Vmediawiki p52 sa(dp53 g4 VDokuWiki markup p54 sg6 Vdokuwiki p55 sa(dp56 g4 VTextile p57 sg6 Vtextile p58 sa(dp59 g4 VEmacs Org-Mode p60 sg6 Vorg p61 sa(dp62 g4 VGNU Texinfo p63 sg6 Vtexinfo p64 sa(dp65 g4 VOPML p66 sg6 Vopml p67 sa(dp68 g4 VDocBook p69 sg6 Vdocbook p70 sa(dp71 g4 VOpenDocument p72 sg6 Vopendocument p73 sa(dp74 g4 VOpenOffice text document p75 sg6 Vodt p76 sa(dp77 g4 VWord docx p78 sg6 Vdocx p79 sa(dp80 g4 VHaddock markup p81 sg6 Vhaddock p82 sa(dp83 g4 Vrich text format p84 sg6 Vrtf p85 sa(dp86 g4 VEPUB v2 book p87 sg6 Vepub p88 sa(dp89 g4 VEPUB v3 p90 sg6 Vepub3 p91 sa(dp92 g4 VFictionBook2 e-book p93 sg6 Vfb2 p94 sa(dp95 g4 VAsciiDoc p96 sg6 Vasciidoc p97 sa(dp98 g4 VInDesign ICML p99 sg6 Vicml p100 sa(dp101 g4 VSlidy HTML and javascript slide show p102 sg6 Vslidy p103 sa(dp104 g4 VSlideous HTML and javascript slide show p105 sg6 Vslideous p106 sa(dp107 g4 VDZSlides HTML5 + javascript slide show p108 sg6 Vdzslides p109 sa(dp110 g4 Vreveal.js HTML5 + javascript slide show p111 sg6 Vrevealjs p112 sa(dp113 g4 VS5 HTML and javascript slide show p114 sg6 Vs5 p115 sasVinputs p116 (lp117 (dp118 Vdescription p119 Vnative Haskell p120 sVarg p121 Vnative p122 sa(dp123 g119 VJSON version of native AST p124 sg121 Vjson p125 sa(dp126 g119 Vpandoc\u2019s extended markdown p127 sg121 Vmarkdown p128 sa(dp129 g119 Voriginal unextended markdown p130 sg121 Vmarkdown_strict p131 sa(dp132 g119 VPHP Markdown Extra extended markdown p133 sg121 Vmarkdown_phpextra p134 sa(dp135 g119 Vgithub extended markdown p136 sg121 Vmarkdown_github p137 sa(dp138 g119 VTextile p139 sg121 Vtextile p140 sa(dp141 g119 VreStructuredText p142 sg121 Vrst p143 sa(dp144 g119 VHTML p145 sg121 Vhtml p146 sa(dp147 g119 VDocBook p148 sg121 Vdocbook p149 sa(dp150 g119 Vtxt2tags p151 sg121 Vt2t p152 sa(dp153 g119 Vdocx p154 sg121 Vdocx p155 sa(dp156 g119 VEPUB p157 sg121 Vepub p158 sa(dp159 g119 VOPML p160 sg121 Vopml p161 sa(dp162 g119 VEmacs Org-mode p163 sg121 Vorg p164 sa(dp165 g119 VMediaWiki markup p166 sg121 Vmediawiki p167 sa(dp168 g119 VTWiki markup p169 sg121 Vtwiki p170 sa(dp171 g119 VHaddock markup p172 sg121 Vhaddock p173 sa(dp174 g119 VLaTeX p175 sg121 Vlatex p176 sas.
  12. Pandoctor 1.0.5 Alfred 2.6 (374) Starting debug for 'Pandoctor' [ERROR: alfred.workflow.action.script] 10:51:12 pandoctor.py:1206 DEBUG {u'<argument>': u'/Users/drlulz/Desktop/Untitled.md', u'<flag>': u'in_path', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': False, u'store': True} 10:51:12 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:12 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache 10:51:12 workflow.py:970 DEBUG Cached data saved at : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache [ERROR: alfred.workflow.output.script] 10:51:12 pandoctor.py:1206 DEBUG {u'<argument>': u'[path]', u'<flag>': u'pandoc_inputs', u'config': False, u'help': False, u'launch': True, u'run': False, u'search': False, u'store': False} 10:51:12 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:12 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:13 pandoctor.py:1206 DEBUG {u'<argument>': u'markdown', u'<flag>': u'inputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:13 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:13 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [ERROR: alfred.workflow.action.script] 10:51:15 pandoctor.py:1206 DEBUG {u'<argument>': u'markdown', u'<flag>': u'in_format', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': False, u'store': True} 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache 10:51:15 workflow.py:970 DEBUG Cached data saved at : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache [ERROR: alfred.workflow.output.script] 10:51:15 pandoctor.py:1206 DEBUG {u'<argument>': u'', u'<flag>': u'pandoc_outputs', u'config': False, u'help': False, u'launch': True, u'run': False, u'search': False, u'store': False} 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:15 pandoctor.py:1206 DEBUG {u'<argument>': u'', u'<flag>': u'outputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:15 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:16 pandoctor.py:1206 DEBUG {u'<argument>': u'w', u'<flag>': u'outputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:16 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:16 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:16 pandoctor.py:1206 DEBUG {u'<argument>': u'wi', u'<flag>': u'outputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:16 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:16 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:17 pandoctor.py:1206 DEBUG {u'<argument>': u'wik', u'<flag>': u'outputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:17 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:17 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [STDERR: alfred.workflow.input.scriptfilter] 10:51:17 pandoctor.py:1206 DEBUG {u'<argument>': u'wiki', u'<flag>': u'outputs', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:17 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:17 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [ERROR: alfred.workflow.action.script] 10:51:21 pandoctor.py:1206 DEBUG {u'<argument>': u'mediawiki', u'<flag>': u'out_format', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': False, u'store': True} 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache 10:51:21 workflow.py:970 DEBUG Cached data saved at : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache [ERROR: alfred.workflow.output.script] 10:51:21 pandoctor.py:1206 DEBUG {u'<argument>': u'', u'<flag>': u'pandoc_options', u'config': False, u'help': False, u'launch': True, u'run': False, u'search': False, u'store': False} 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache [ERROR: alfred.workflow.input.scriptfilter] Code 1: 10:51:21 pandoctor.py:1206 DEBUG {u'<argument>': u'', u'<flag>': u'options', u'config': False, u'help': False, u'launch': False, u'run': False, u'search': True, u'store': False} 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/runner.cache 10:51:21 workflow.py:940 DEBUG Loading cached data from : /Users/drlulz/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/com.hackademic.pandoctor/pandoc.cache 10:51:21 workflow.py:1275 ERROR u'options' Traceback (most recent call last): File "/Users/drlulz/Google Drive/MacBook/Alfred/Alfred.alfredpreferences/workflows/user.workflow.155F404E-339A-46A3-9025-93C99FEF4B1D/workflow/workflow.py", line 1273, in run func(self) File "pandoctor.py", line 1208, in main res = pd.run(args) File "pandoctor.py", line 355, in run return method() File "pandoctor.py", line 442, in search_codepath data = getattr(self.pandoc, prop, None) File "pandoctor.py", line 174, in options return self.data['options']KeyError: u'options'
  13. Not sure what I'm doing wrong. I ran dr:config Now trying to convey .md to mediawiki. After selecting output format I get Error in workflow 'com.academic.pandoctor' with subtitle u'options'.
  14. I got as far as returning the below from python, but was running into many issues in different circumstances. [(u'insulin', u'http://www.merriam-webster.com/medical/insulin' u'a protein hormone that is synthesized in the pancreas from proinsulin and secreted by the beta cells of the islets of Langerhans, that is essential for the metabolism of carbohydrates, lipids, and proteins, that regulates blood sugar levels by facilitating the uptake of glucose into tissues, by promoting its conversion into glycogen, fatty acids, and triglycerides, and by reducing the release of glucose from the liver, and that when produced in insufficient quantities results in diabetes mellitus '), (u'insulin coma therapy', u'http://www.merriam-webster.com/medical/insulin%20coma%20therapy' <sx>INSULIN SHOCK THERAPY</sx>), (u'insulin{ndash}dependent diabetes', u'http://www.merriam-webster.com/medical/insulin%7Bndash%7Ddependent%20diabetes' <sx>type 1 diabetes</sx>)] One such issue was encoding. When reading your tutorial, you mention to convert everything initially as its brought in and then convert back on the way out. There seems to be many ways to approach this (u'', unicode(), .decode(), etc), though I may be mixing apples and oranges. How can I reveal the encoding of any given string, so that I can begin to understand this idea. Before your answer I had changed the URL to u'x' + urllib.quote(y) + u'z' + API out of desperation. So the ? and = are inferred from their type? This would make good sense. In python, would you call {'key': API_KEY} a record, and how is this distinct from dict? I had given up on str.replace, and was using the below, but the definition still contained some children. Removing BeautifulSoup all together seems optimal to say the least. term = word.get('id') url = u'http://www.merriam-webster.com/medical/' + urllib.quote(term) def_tag = word.find('dt') term_def = def_tag.contents[0] Your last two points I would like to ask questions on after I've digested it a little. Also, thank you very much for taking the time.
  15. Here's what I've changed. I not getting an error but I'm not getting results either. # encoding: utf-8 from workflow import Workflow, ICON_WEB, web from bs4 import BeautifulSoup #from lxml import etree import sys API_KEY = 'API' def _mdict_search(query): url = u'http://www.dictionaryapi.com/api/v1/references/medical/xml/' + query + "?key=" params = dict(auth_token=API_KEY) r = web.get(url, params) r.raise_for_status() return _mdict_results(r.content) def _mdict_results(content): soup = BeautifulSoup(content) words = soup.find_all(id=True) results = [] for word in words: term = word.find_all('entry') title = wf.decode(term.replace('<entry id="', '').replace('">', '')) wf.logger.debug(title) url = u'http://www.merriam-webster.com/medical/' + title define = table.find('dt') desc = wf.decode(define.replace('<dt>', '').replace('</dt>', '')) # going to be a problem results.append((title, url, desc)) return results def main(wf): query = wf.args[0] def wrapper(): return _mdict_search(query) #results = wf.cached_data('results', wrapper, max_age=60) results = _mdict_search(query) for result in results: wf.add_item( title=result[0], subtitle=result[2], arg=result[1], valid=True, icon=ICON_WEB) wf.send_feedback() if __name__ == '__main__': wf = Workflow() sys.exit(wf.run(main)) Where am i going wrong?
  16. I'm finding it difficult to see my errors. For instance, I'm getting 'unicode' object has no attribute 'items' but I'm not sure where to look. Might this have something to do with for word in words: or for result in results:?
  17. Thanks for the switch in perspective. I read part one of your tutorial twice, the second time very slowly. As an exercise I'm trying to recreate the idea with something I'd use often. Merriam-Webster has a Medical Dictionary, and also an API. The results are returned with xml, so I found a thread where you do something similar. In the example you're grabbing html tags, unless I'm missing some fundamental idea (very likely the case) I didn't see why I couldn't do this with the returned xml. Though, now that I'm writing this I don't see why I'm parsing xml to turn it back to xml other than to display it in Alfred. I still don't think I'm looking at this correctly. It would great if I could get this working similar to your searchio, filtering per keypress. The Dictionary API Returns: <entry_list version="1.0"> <entry id="insulin"> <hw>in·su·lin</hw> <pr>ˈin(t)-s(ə-)lən</pr> <sound> <wav>insuli01.wav</wav> <wpr>!in(t)-s(u-)lun</wpr> </sound> <fl>noun</fl> <def> <sensb> <sens> <dt> a protein hormone that is synthesized in the pancreas from proinsulin and secreted by the beta cells of the is lets of Langerhans, that is essential for the metabolism of carbohydrates, lipids, and proteins, that regulate s blood sugar levels by facilitating the uptake of glucose into tissues, by promoting its conversion into glyc ogen, fatty acids, and triglycerides, and by reducing the release of glucose from the liver, and that when pro duced in insufficient quantities results in diabetes mellitus <dx> see <dxt>ILETIN</dxt> </dx> </dt> </sens> </sensb> </def> </entry> </entry_list> Based on the linked thread, I was trying: # encoding: utf-8 from workflow import Workflow, ICON_WEB, web from lib import BeautifulSoup import sys API_KEY = 'API KEY' def request_mdict_search(query): url = u'http://www.dictionaryapi.com/api/v1/references/medical/xml' r = web.get(url, query, {'?key=': API_KEY}) r.raise_for_status() return parse_mdict_results(r.content) def parse_mdict_results(content): soup = BeautifulSoup(content) words = soup.findAll('entry') results = [] for word in words: part1 = word.find('entry') title = wf.decode(part1.replace('<entry id="', '').replace('">', '')) wf.logger.debug(title) url = u'http://www.merriam-webster.com/medical/' + title part2 = table.find('dt') desc = wf.decode(part2.replace('<dt>', '').replace('</dt>', '')) # going to be a problem results.append((title, url, desc)) return results def main(wf): query = wf.args[0] def wrapper(): return request_mdict_search(query) #results = wf.cached_data('results', wrapper, max_age=60) results = request_mdict_search(query) for result in results: wf.add_item( title=result[0], subtitle=result[1], arg=result[1], valid=True, icon=ICON_WEB) wf.send_feedback() if __name__ == '__main__': wf = Workflow() sys.exit(wf.run(main)) Ideally I'd have the Title and Subtitle in Alfred as the Word and Definition. Though I'm concerned with <dx> & <dxt> tags inside the definition tag. I would need to ignore these in the result. Alternatively the website gives a php example. <?php // This function grabs the definition of a word in XML format. function grab_xml_definition ($word, $ref, $key) { $uri = "http://www.dictionaryapi.com/api/v1/references/" . urlencode($ref) . "/xml/" . urlencode($word) . "?key=" . urlencode($key); return file_get_contents($uri); }; $xdef = grab_xml_definition("test", "medical", "API_KEY"); ?> Which, if either, of the two directions should I work towards?
  18. What I was going for was to start the workflow using a keyword with flags as options. So, something like "export -t -i -400 : tag1 tag2" would export highlights, titlecase text, export images at a width of 400px, and apply tags. Another option is infer spaces (-s) which is dependent on a wordlist. I was trying to speed up this process of inferring spaces by having wordlists suited to different areas, so the list would be shorter. (Enter snafu) If the user choose to infer spaces on their text I wanted the applescript to call up Alfred, have Alfred present my xml, make a selection, and then pass the query back to the Applescript to finish up. On a different note, am I correct in assuming the xml "autocomplete" has nothing to do with filtering the xml based on user input, but is only to.. well... autocomplete by pressing right arrow? I tried to dissect the Evernote workflow to see how he accomplishes this. It's a bit complicated for my current level, but it looks like he's matching the typed letters to notebook names and then making the xml on the fly. How does one filter results? The proxy.scpt serves only one purpose for my workflow, which is to store the value of a variable for later retrieval (Its just one line, property word_list : ""). I cringed a little when I went this direction because I know there has to be a better, more elegant, way to achieve such a simple task. I read about cached data and persistent data, but I'm not sure how to access and write to these directories, and I still don't know if that's overkill for such a simple thing. In regards to "Choose from list," I was trying to steer clear of having applescript accept input and do that solely from Alfred (better aesthetics). The last part (your #3) was my goal, but I couldn't for the life of me figure a way to get the query back to the running script. Splitting the script, that sounds like it might work. I will need to read more about cached data so that the original options are passed along to the second script. My confusion lied wholly in the fact that I couldn't see a way to get more input from the user (with Alfred) to modify the running process.
  19. I borrowed my wife's LG bluetooth headset (she gave me a weird look). I was clear across the room (~10m) using Alfred Remote triggers with the headset mic for dictation. Neat!
  20. Doing a Skim search with dictation and then advancing page results with Alfred remote. 1. Remote Trigger --> Keyword 2. Dictate Query --> Skim Search Applescript 3. Use Run Script on the Remote to advance page results. (icon) The search Applescript is "listening" (not really, but you get the idea) for keypress with: on isControlKeyPressed() return (do shell script "/usr/bin/python -c 'import Cocoa; print Cocoa.NSEvent.modifierFlags() & Cocoa.NSControlKeyMask > 1'") is "True" end isControlKeyPressed To advance the page use: tell application id "sevs" control key down delay 0.2 control key up end tell
  21. I thought I'd put this here, if it's not the right place let me know. The dropbox link below is a somewhat cohesive version of my fork. A few more questions. If I want to include _skimmer.app in the workflow do I have your permission, and if yes what is the correct way to credit you? In your experience how often do new app releases break workflows? Initially I had everything setup correctly in the above posts, but I never thought Evernote itself was the issue, and I still think its odd that file://localhost will not run from OmniOutliner after Yosemite. Dropbox
  22. I've been doing some reading. I didn't want to reply back without a specific question, and I'm not sure if I should start a new thread for this so I'll just post it here until someone tells me otherwise. The wikify workflow was a big help, and I was successful getting crosstalk working between applescript and python. This work around is laughable. Please, someone point me in the right direction. I am attempting to call the Alfred window from Applescript, make a selection, and then return the result. The idea is described in this post. I’ve done the following. tell application "Alfred 2" to search "choose list" The keyword “choose list” is a script filter with an xml list. The result/query is passed to a Run Script which modifies a property of another proxy.scpt. Back to the Applescript, directly after search “choose list”, I retrieve the modified property of proxy.scpt. To ensure the returned property was the result of Script Filter —> Run Script I get the modified time of proxy.scpt and repeat until its greater than the current time, exiting after x many seconds. set word_list to my get_wrd_list() on get_wrd_list() set proxy_path to quoted form of ((do shell script "pwd") & "/proxy.scpt") set time_start to do shell script "date +%s" set time_mod to do shell script "stat -f %m " & proxy_path repeat until time_mod > time_start set time_mod to do shell script "stat -f %m " & proxy_path set time_exit to do shell script "date +%s" if time_exit - time_start > 10 then exit repeat end repeat set proxy_value to load script ((POSIX file ((do shell script "pwd") & "/proxy.scpt"))) return proxy_value's word_list end get_wrd_list Like I said, laughable and borderline ridiculous if not completely. I’d like to do this in python. I’ve been looking at the Alfred-Workflow documentation, which is extensive and yet tailor made for someone starting out. I’m slowly becoming more proficient, and currently understand 25% of what I read (up from 10% last month), but some of the subtle nuances are lost. How should I go about this? Dropbox
×
×
  • Create New...