Editorial Workflows

GrepMan

public workflow

Install Workflow...

This workflow contains at least one Python script. Only use it if you trust the person who shared this with you, and if you know exactly what it does.

I understand, install the workflow!

This is a workflow for Editorial, a Markdown and plain text editor for iOS. To download it, you need to view this page on a device that has the app installed.

Description: The "Tag&Grep-Manager":

Greps lines matching a combination of tags or a general string in all Dropbox files, and shows them in a list. Select an item to open the corresponding file and jump to that line.

In the flavour of a "tag browser", a List of '@[a-z]' ist extracted from the files and can be used to construct search filters.

Last but not least, favourite search filters are read from and can be added to the file "tag_searches.md".

Shared by: Timo Dickscheid

Comments: Comment Feed (RSS)

There are no comments yet.

+ Add Comment

Workflow Preview
Set Variable ?
Variable Name
start
Value
0
Set Variable ?
Variable Name
searchstr
Value
""
Run Python Script ?
Source Code
#coding: utf-8
import workflow
import editor
import console
import ui
import os
import re
from collections import defaultdict
import operator
import datetime,dateutil.parser
from threading import Timer
from glob import glob

dir = os.path.join(
	os.path.split(os.getcwd())[0],
	'Dropbox'
)
searchesfile = os.path.join(dir,'org/favorite_tagsearches.md')
fnames = glob(dir+'/*/*.md')+glob(dir+'*.md')

items = ui.ListDataSource([])
matches = {}
searchstr = ''
workflow.set_output('org/dashboard.md')
duepat = re.compile(r'^.*@due\((\d\d\d\d-\d\d-\d\d)\).*')
itempat = re.compile(r'^\s*-\s*')
tagpat=re.compile(r'(?:\s+|^)@[a-z0-9]+')
todaydate = datetime.datetime.today()
searches = {}

def getSearches():
	global searches
	try:
		with open(searchesfile) as f:
			lines = [itempat.sub('',l).strip()
										for l in f
										if itempat.search(l)>=0]
			searches = {l.split(':')[0]:l.split(':')[1] for l in lines }
	except Exception as e:
		print str(e)
	return searches.keys()

def addSearch(sender):
	if re.match(r'^\s*$',searchfield.text):
		return
	Timer(0.25,addSearchThread).start()

def addSearchThread():
	searchname = console.input_alert('name of search:')
	with open(searchesfile, "a") as f:
		f.write(" - %s: %s\n"%(searchname,searchfield.text))
	getSearches()

def removeTags(s,tags):
	if len(tags)==0:
		return s
	result=s.strip()
	for t in tags:
		result =result.replace(t,'')
	result=itempat.sub('',result)
	return result

def grep(s=None):
	global searchstr
	if s==None: return {}
	res = {}
	sstr = s.strip()
	required=[w for w in sstr.split(' ') if w[0]!='!']
	filtered=[w[1:] for w in sstr.split(' ') if w[0]=='!']
	for fn in fnames:
		if fn==searchesfile: continue
		with open(fn) as f:
				lines={' '.join([removeTags(l,required),'|',os.path.basename(fn)]):(fn,i) 
											for i,l in enumerate(f) 
											if  all([re.search(t.lower(),l.lower()) 
																for t in required])
											and all([re.search(t.lower(),l.lower())==None 
																for t in filtered])
								}
				if len(lines)>0 and lines!=None: 
					res.update(lines)
	searchstr = required[0]
	return res

def select(item):
	lines=matches.keys()
	fname,linenr = matches[lines[item.selected_row]]
	linetxt=searchstr
	with open(fname) as f:
		linetxt = f.readlines()[linenr]
	workflow.set_variable('searchstr',linetxt)
	workflow.set_output(fname.replace(dir,''))
	view.close()
	
def showDue(object):
	global matches
	allmatches = grep('@due(\(\d\d\d\d-\d\d-\d\d\))')
	matches = {}
	for k,v in allmatches.items():
		duestr = duepat.sub(r'\1',k)
		if duestr=='':
			print 'couldnt find due date in',k
			continue
		try:
			duedate = dateutil.parser.parse(duestr,fuzzy=True)
		except Exception as e:
			print 'couldnt parse due string',duestr
			print str(e)
			continue
		delta = (todaydate-dateutil.parser.parse(duestr,fuzzy=True)).days
		if delta>=0:
			matches[k]=v
	searchfield.text=''
	items.items = matches.keys()

def runGrep(sender):
		global matches
		matches = grep(searchfield.text)
		items.items = matches.keys()
		
def applySavedSearch(sender):
	searchname = sender.segments[sender.selected_index]
	if searches.has_key(searchname):
		searchfield.text = searches[searchname]
	else:
		ui.hud_alert('No search found with name %s'%searchname)
	global matches
	matches = grep(searchfield.text)
	items.items = matches.keys()
	
def clearSearchfield(sender):
	searchfield.text=''

view = ui.load_view()
searchfield,table,duebutton,clearbutton,addSearchButton,segcontrol,grepbutton = view.subviews
table.data_source = items
segcontrol.segments = getSearches()
segcontrol.action = applySavedSearch

showDue(None)
view.present('fullscreen')
view.wait_modal()
Open Document ?
File Name
%var:Input
In Dropbox
ON
Highlight Occurrences ?
Search for
%var:searchstr
Regular Expression
OFF
Select First Result
ON
Move Caret ?
Direction
  • Backward
  • Forward
  • Start/End of Document
  • Start/End of Line
  • Number of Characters:
1