-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparsenotes.py
221 lines (186 loc) · 7.63 KB
/
parsenotes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import re
from os import listdir
from os.path import join
from dateutil.parser import parse
import numpy as np
import pandas as pd
import mistune
'''
TODO
-Sublist
'''
actiontest = re.compile("#[A-Z]")
def ReadinFiletoString(path):
'''Reads in file as a single sting'''
with open(path,'r') as filename:
return filename.read()
#Functions that work on textlines
def SplitbyCarriage(string):
'''Takes a sting and makes a list of lines seperated by carraige return'''
return string.split('\n')
def DeleteEmptyLines(noteslist):
'''Removes empty lines from a notelist'''
return [line for line in noteslist if len(line) != 0]
def AddTag(textline,tag):
'''Takes a textline and encloses it in an html tag'''
starttag = '<' + tag + '>'
endtag = '</' + tag + '>'
return starttag + textline + endtag
def IsHeader(textline):
'''Returns True if the textline is identified as a header according to Markdown
formatting'''
return bool(re.match('#{1,}\s',textline))
def IsAction(textline):
'''Function that returns True if textline has an #Name Tag.'''
return bool(re.findall("#[A-Za-z]{1,}",textline))
def StripHead(textline):
'''Function to strip a markdown # or * from the beginning of a line'''
if bool(re.split('(#|\*){1,}\s',textline,maxsplit=1)):
return re.split('(#|\*){1,}\s',textline,maxsplit=1)[-1]
else:
return textline
def SplitAction(textline):
return re.split('#(?=[A-Z])',textline)
def RenderLine(textline):
'''Function that turns a text line into an html line with tags'''
#Create the line
md = mistune.Markdown()
if IsAction(md(textline)):
#return AddClass(md(textline),'Action')
return AddStyle(md(textline),{'color':'red'})
else:
return md(textline)
#Functions that accept html lines
def AddClass(htmlline,class_name):
'''Adds a class attribute to a line that already has html tags.'''
templist = re.split('>',htmlline,maxsplit=1)
return templist[0] + ' class="' + class_name + '">' + templist[1]
def AddID(htmlline,id_name):
'''Adds an ID attribute to a line that already has an html tag.'''
templist = re.split('>',htmlline,maxsplit = 1)
return templist[0] + ' id="' + id_name + '">' + templist[1]
def AddStyle(htmlline,styledict):
'''Adds inline style'''
templist = re.split('>',htmlline,maxsplit=1)
stylestring = "style ="
newstring=' style='
for k,v in styledict.items():
newstring = newstring +'"' + k + ":" +v + '"' +";"
return templist[0] + newstring +'>' + templist[1]
#Functions that accept a list of text lines.
def RenderNotes(textlist):
'''Takes a list of lines and calls Renderline on each of them to put html
tags around each one'''
htmllist = []
for line in textlist:
htmllist.append(RenderLine(line))
return htmllist
def WriteNotes(textlist):
'''Takes a texlist, removes empty lines and returns a single string with newlines between
old list elements'''
totalstring = ''
for line in DeleteEmptyLines(textlist):
totalstring = totalstring + line + '\n'
return totalstring
#Other stuff
def InsertHTML(page,variableID,texttoinsert):
restring = '{{ '+ variableID + ' }}' #This has the potential to be a little buggy
tempsplit = page.split(restring)
return tempsplit[0] + texttoinsert + tempsplit[1]
def AddHeader(headertext,level=1):
'''Adds a heater html tag to a textline
headertext string - textline to enclose in header tag
level int - header level number (h1,h2,etc)
'''
opentag = '<h' + str(level) + '>'
closetag = '</h' + str(level) + '>'
return opentag + headertext + closetag
def FindMeetings(folderpath):
'''Looks in folderpath for meetings. A meeting is any markdown file
with the following format: dd-mm-yy-[meetingname] returns a list of distinct meeting names'''
mdfiles = [f for f in listdir(folderpath) if f[-3:] == ".md"]
meetingslist1= []
for file in mdfiles:
meeting = re.split('-[0-9]{1,2}-[0-9]{1,2}-[0-9]{1,4}',file)[0]
meetingslist1.append(meeting)
meetingslist2 = []
for meeting in meetingslist1:
if meeting not in meetingslist2:
meetingslist2.append(meeting)
return meetingslist2
def FindLatest(meetingname,folderpath):
'''Returns a full pathname to the latest file of meetingname'''
allfiles = listdir(folderpath)
thismeeting = [file for file in allfiles if meetingname in file]
datearray = np.array([])
for onemeeting in thismeeting:
onedate = parse(re.search('[0-9]{1,2}-[0-9]{1,2}-[0-9]{2,4}(?=.md)',onemeeting)[0])
datearray = np.append(datearray,onedate)
maxindex = datearray.argmax()
latestmeeting = thismeeting[maxindex]
return join(folderpath,latestmeeting)
def ReadMeeting(meetingpath):
'''Creates a htmllist from a meeting notes file'''
with open(meetingpath) as fh:
htmllist = RenderNotes(DeleteEmptyLines(SplitbyCarriage(fh.read())))
return htmllist
def ComposePage(folderpath):
'''Finds all the latest meetings in a given folder and returns a string with html tags'''
#Get all the meetings
allmeetings = FindMeetings(folderpath)
finalstring = ''
#For Each meeting compose a string of the meeting notes
for meetingname in allmeetings:
temp = WriteNotes(ReadMeeting(FindLatest(meetingname,folderpath)))
temp = AddID(AddTag(AddHeader(meetingname) + temp,'div'),meetingname)
finalstring = finalstring + temp + '<p></p>'
#Add a div to link
return finalstring
def WriteNotesHTMLPage(folderpath,htmlpath,finalpagename):
'''Function to write the complete page.
Arguments:
folderpath string - path to the folder where the notes reside.
htmlpath - path to the html header template
finalpagename - name of the final page, it will reside in the folderpath.
'''
with open(htmlpath,'r') as fh:
template = fh.read()
#Read in all of the notes
allnotes = ComposePage(folderpath)
#Add in the actions
allnotes = WriteActionsHTML(FindActions(folderpath)) + "<p></p>" + allnotes
#Put a div around everything to fix margin with top menu bar
allnotes = AddClass(AddTag(allnotes,'div'),'ActionsAndNotes')
#Add the two together
finalpage = InsertHTML(template,'meetings',allnotes)
#Write the final page
outfilepath = folderpath + '/' + finalpagename + '.html'
with open(outfilepath,'w') as fh:
fh.write(finalpage)
return None
def FindActions(folderpath):
'''
Finds the Actions Marked with a Hashtag in the Notes
'''
meetinglist = FindMeetings(folderpath)
actionslist =[]
for meeting in meetinglist:
textlist = SplitbyCarriage(ReadinFiletoString(FindLatest(meeting,folderpath)))
for textline in textlist:
if IsAction(textline):
action = re.split('#[A-Z]',textline)[0]
people = re.findall('(?<=#)[A-Za-z]{1,}',textline)
for person in people:
actionslist.append([action,person])
return pd.DataFrame(columns = ['Action','Name'],data = actionslist)
def WriteActionsHTML(actionsdf):
people = actionsdf['Name'].unique()
actionstringall = AddHeader('Actions')
for person in people:
persondf = actionsdf.query('Name == @person')
actionstring1person = AddHeader(person,2)
for index,action in persondf.iterrows():
actionstring1person = actionstring1person + RenderLine(action['Action'])
actionstringall = actionstringall + actionstring1person
actionstringall = AddID(AddClass(AddTag(actionstringall,'div'),'actions'),'ActionList')
return actionstringall