Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F62813953
snippet_helper.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, May 15, 20:30
Size
14 KB
Mime Type
text/x-python
Expires
Fri, May 17, 20:30 (2 d)
Engine
blob
Format
Raw Data
Handle
17692732
Attached To
R3683 Slides
snippet_helper.py
View Options
#!/usr/bin/env python3
import
subprocess
import
os
import
re
import
abc
from
pygments
import
highlight
from
pygments.lexers
import
CppLexer
from
pygments.lexers
import
PythonLexer
from
pygments.lexers
import
MatlabLexer
from
pygments.formatters
import
HtmlFormatter
from
pygments.formatters
import
LatexFormatter
from
pygments
import
token
from
IPython.display
import
HTML
from
tempfile
import
NamedTemporaryFile
################################################################
class
SlicedSnippet
(
object
):
"""
When you slice a snippet, this object is returned
so that all your operations can apply directly to the snippet if need be.
"""
def
__init__
(
self
,
snippet
,
slice
):
self
.
start
=
slice
.
start
if
slice
.
start
is
None
:
self
.
start
=
1
self
.
end
=
slice
.
stop
-
1
self
.
snippet
=
snippet
def
pigment
(
self
,
**
kwargs
):
kwargs
[
'start'
]
=
self
.
start
kwargs
[
'end'
]
=
self
.
end
return
self
.
snippet
.
pigment
(
**
kwargs
)
def
extract
(
self
):
return
self
.
snippet
.
extract
(
start
=
self
.
start
,
end
=
self
.
end
)
class
Snippet
(
abc
.
ABC
):
"""
Snippet objects manipulate codes.
"""
default_output
=
'html'
default_line_numbering
=
False
def
__getitem__
(
self
,
slice
):
return
SlicedSnippet
(
self
,
slice
)
def
__init__
(
self
,
inp
,
format_flag
=
False
,
compile_flag
=
False
,
working_dir
=
'/tmp'
):
self
.
working_dir
=
working_dir
try
:
self
.
loadfile
(
inp
)
except
Exception
:
self
.
content
=
inp
.
strip
()
if
format_flag
:
self
.
format
()
if
compile_flag
:
self
.
compile
()
# elif language == 'matlab':
# self.lexer = MatlabLexer()
def
save
(
self
,
filename
):
"""
Saves the snippet in another file
:param filename: The filename to save the snippet to
"""
f
=
open
(
filename
,
'w'
)
f
.
write
(
self
.
content
)
f
.
close
()
def
loadfile
(
self
,
inp
):
filename
=
inp
full_filename
=
os
.
path
.
realpath
(
filename
)
f
=
open
(
full_filename
)
self
.
content
=
f
.
read
()
f
.
close
()
def
getTemporaryFile
(
self
,
**
kwargs
):
f
=
NamedTemporaryFile
(
dir
=
self
.
working_dir
,
**
kwargs
)
f
.
write
(
self
.
content
.
encode
())
f
.
flush
()
return
f
@abc.abstractmethod
def
format
(
self
):
raise
RuntimeError
(
'pure virtual routine'
)
@abc.abstractmethod
def
execute
(
self
,
working_dir
=
'/tmp'
,
args
=
''
,
libraries
=
''
):
raise
RuntimeError
(
'pure virtual routine'
)
def
compile
(
self
,
working_dir
=
'/tmp'
):
raise
RuntimeError
(
'pure virtual routine'
)
def
get_lines
(
self
):
return
self
.
content
.
split
(
'
\n
'
)
def
get_content
(
self
):
return
self
.
content
def
__str__
(
self
):
_content
=
self
.
content
.
split
(
'
\n
'
)
ret
=
""
for
i
,
line
in
enumerate
(
_content
):
ret
+=
'{0}: {1}
\n
'
.
format
(
i
,
line
)
return
ret
class
KeywordLexer
(
object
):
def
__init__
(
self
,
keyword
):
if
keyword
==
'curly_brackets'
:
keyword
=
'{|}'
self
.
keyword
=
keyword
def
get_tokens
(
self
,
text
):
pattern
=
'('
+
self
.
keyword
+
')'
splits
=
re
.
split
(
pattern
,
text
)
if
len
(
splits
)
==
1
:
return
[(
token
.
Text
,
text
)]
res
=
[]
# print(splits)
# print(token.Keyword.Type)
for
count
,
s
in
enumerate
(
splits
):
# print(count, s)
if
count
%
2
==
0
:
res
.
append
((
token
.
Text
,
s
))
else
:
res
.
append
((
token
.
Keyword
.
Type
,
s
))
# print(res)
return
res
class
LineLexer
(
object
):
def
__init__
(
self
,
line_number
):
self
.
line_number
=
line_number
def
get_tokens
(
self
,
text
):
splits
=
text
.
split
(
'
\n
'
)
res
=
[]
splits1
=
'
\n
'
.
join
(
splits
[:
self
.
line_number
])
+
'
\n
'
splits2
=
splits
[
self
.
line_number
]
+
'
\n
'
splits3
=
'
\n
'
+
'
\n
'
.
join
(
splits
[
self
.
line_number
+
1
:])
+
'
\n
'
splits
=
[
splits1
]
+
[
splits2
]
+
[
splits3
]
# print(splits)
for
count
,
s
in
enumerate
(
splits
):
if
count
==
1
:
res
.
append
((
token
.
Keyword
.
Type
,
s
))
else
:
res
.
append
((
token
.
Text
,
s
))
# print(res)
return
res
class
CustomLatexFormatter
(
LatexFormatter
):
def
__init__
(
self
,
**
kwargs
):
LatexFormatter
.
__init__
(
self
,
**
kwargs
)
def
format
(
self
,
tokens
,
outfile
):
res
=
[]
for
t
,
s
in
tokens
:
if
t
==
token
.
Keyword
.
Type
:
import
pygments.formatters.latex
as
la
s
=
la
.
escape_tex
(
s
,
self
.
commandprefix
)
s
=
r'\color{red}{\huge{'
+
s
+
'}}'
t
=
token
.
Escape
res
.
append
((
t
,
s
))
LatexFormatter
.
format
(
self
,
res
,
outfile
)
class
CustomHtmlFormatter
(
HtmlFormatter
):
def
__init__
(
self
,
**
kwargs
):
HtmlFormatter
.
__init__
(
self
,
**
kwargs
)
def
format
(
self
,
tokens
,
outfile_final
):
# HtmlFormatter.format(self, tokens, outfile_final)
# return
from
io
import
StringIO
outfile
=
StringIO
()
res
=
[]
ss
=
[]
for
t
,
s
in
tokens
:
if
t
==
token
.
Keyword
.
Type
:
ss
.
append
(
s
)
s
=
'A'
*
24
t
=
token
.
Text
res
.
append
((
t
,
s
))
# print(res)
HtmlFormatter
.
format
(
self
,
res
,
outfile
)
final
=
outfile
.
getvalue
()
while
ss
:
s
=
ss
.
pop
(
0
)
final
=
final
.
replace
(
'A'
*
24
,
'<span style="color:red;font-size:150%">{0}</span>'
.
format
(
s
),
1
)
outfile_final
.
write
(
final
)
def
extract
(
self
,
start
=
None
,
end
=
None
):
_content
=
self
.
content
.
split
(
'
\n
'
)
_content
=
[(
c
+
'
\n
'
)
for
c
in
_content
]
if
start
is
None
:
start
=
1
if
end
is
None
:
end
=
len
(
_content
)
snip
=
_content
[
start
-
1
:
end
]
snip
=
''
.
join
(
snip
)
return
snip
def
pigment
(
self
,
start
=
None
,
end
=
None
,
keyword
=
None
,
line_highlight
=
None
,
output
=
None
,
line_numbering
=
None
,
**
kwargs
):
if
start
is
None
:
start
=
1
if
output
is
None
:
output
=
self
.
default_output
lexer
=
self
.
lexer
if
keyword
is
not
None
:
lexer
=
self
.
KeywordLexer
(
keyword
)
elif
line_highlight
is
not
None
:
if
line_highlight
<
start
or
line_highlight
>
end
:
raise
RuntimeError
(
'line_highlight out of the sub snippet'
)
line_highlight
-=
start
lexer
=
self
.
LineLexer
(
line_highlight
)
if
line_numbering
is
None
:
line_numbering
=
self
.
default_line_numbering
if
output
==
'html'
:
formatter
=
HtmlFormatter
(
full
=
False
,
linenos
=
line_numbering
,
linenostart
=
start
)
elif
output
==
'latex'
:
formatter
=
LatexFormatter
(
full
=
False
,
linenos
=
line_numbering
,
linenostart
=
start
)
if
(
keyword
is
not
None
)
or
(
line_highlight
is
not
None
):
format_class
=
self
.
CustomHtmlFormatter
if
output
==
'latex'
:
format_class
=
self
.
CustomLatexFormatter
formatter
=
format_class
(
full
=
False
,
linenos
=
line_numbering
,
linenostart
=
start
)
snip
=
self
.
extract
(
start
=
start
,
end
=
end
)
colored_snippet
=
highlight
(
snip
,
lexer
,
formatter
)
# print(colored_snippet)
if
output
==
'html'
:
HTML_TEMPLATE
=
"""<style>
{}
</style>
{}
"""
css
=
formatter
.
get_style_defs
()
colored_snippet
=
HTML
(
HTML_TEMPLATE
.
format
(
css
,
colored_snippet
))
return
colored_snippet
@staticmethod
def
getLatexStyleDefs
():
return
LatexFormatter
(
full
=
True
)
.
get_style_defs
()
################################################################
class
CPPSnippet
(
Snippet
):
"""
Snippet objects manipulate Cpp codes.
At construction it can be formatted using clang-format
and it can be compiled to check for consistency.
"""
class
CompilationError
(
Exception
):
""" Compilation error """
pass
def
__init__
(
self
,
inp
,
include_paths
=
None
,
**
kwargs
):
if
include_paths
is
None
:
self
.
include_paths
=
[]
else
:
self
.
include_paths
=
[
os
.
path
.
abspath
(
i
)
for
i
in
include_paths
]
Snippet
.
__init__
(
self
,
inp
,
**
kwargs
)
self
.
lexer
=
CppLexer
()
def
format
(
self
):
f
=
self
.
getTemporaryFile
()
p
=
subprocess
.
Popen
(
'clang-format {0}'
.
format
(
f
.
name
),
shell
=
True
,
stdout
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
if
p
.
returncode
:
raise
RuntimeError
(
'Failed to launch clang-format'
)
formatted_file
=
stdout
self
.
content
=
formatted_file
.
decode
(
'utf-8'
)
def
execute
(
self
,
working_dir
=
'/tmp'
,
args
=
''
,
libraries
=
''
):
self
.
compile
(
working_dir
=
working_dir
)
f
=
self
.
getTemporaryFile
(
suffix
=
'.cpp'
,
delete
=
False
)
working_dir
=
os
.
path
.
dirname
(
f
.
name
)
# file_dir = os.path.dirname(self.full_filename)
previous_dir
=
os
.
getcwd
()
os
.
chdir
(
working_dir
)
include_paths
=
self
.
include_paths
+
[
working_dir
]
include_paths
=
[
'-I {0}'
.
format
(
a
)
for
a
in
include_paths
]
include_paths
=
' '
.
join
(
include_paths
)
p
=
subprocess
.
Popen
(
'g++ -Wall -Wextra {1} {2} -o exec {0}'
.
format
(
f
.
name
,
include_paths
,
libraries
),
shell
=
True
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
ret
=
p
.
returncode
if
ret
!=
0
:
return
ret
,
stdout
,
stderr
p
=
subprocess
.
Popen
(
'./exec {0}'
.
format
(
args
),
shell
=
True
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
ret
=
p
.
returncode
os
.
chdir
(
previous_dir
)
return
ret
,
stdout
,
stderr
def
compile
(
self
):
f
=
self
.
getTemporaryFile
(
suffix
=
'.cpp'
,
delete
=
False
)
working_dir
=
os
.
path
.
dirname
(
f
.
name
)
# file_dir = os.path.dirname(self.full_filename)
previous_dir
=
os
.
getcwd
()
os
.
chdir
(
self
.
working_dir
)
include_paths
=
self
.
include_paths
+
[
working_dir
]
include_paths
=
[
'-I {0}'
.
format
(
a
)
for
a
in
include_paths
]
include_paths
=
' '
.
join
(
include_paths
)
cmd
=
'g++ -Wall -Wextra {1} -c {0}'
.
format
(
f
.
name
,
include_paths
)
p
=
subprocess
.
Popen
(
cmd
,
shell
=
True
,
stderr
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
ret
=
p
.
returncode
os
.
chdir
(
previous_dir
)
if
ret
!=
0
:
raise
CPPSnippet
.
CompilationError
(
'compilation failed
\n
'
+
cmd
+
'
\n
'
+
stderr
.
decode
(
'utf-8'
))
os
.
remove
(
f
.
name
)
o_file
=
os
.
path
.
splitext
(
f
.
name
)[
0
]
+
'.o'
os
.
remove
(
o_file
)
################################################################
class
PythonSnippet
(
Snippet
):
"""
Snippet objects manipulate Python codes.
At construction it can be formatted using autopep8.
"""
def
__init__
(
self
,
inp
,
**
kwargs
):
Snippet
.
__init__
(
self
,
inp
,
**
kwargs
)
self
.
lexer
=
PythonLexer
()
def
format
(
self
):
f
=
self
.
getTemporaryFile
()
p
=
subprocess
.
Popen
(
'autopep8 {0}'
.
format
(
f
.
name
),
shell
=
True
,
stdout
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
if
p
.
returncode
:
raise
RuntimeError
(
'Failed to launch autopep8'
)
formatted_file
=
stdout
self
.
content
=
formatted_file
.
decode
(
'utf-8'
)
def
execute
(
self
,
args
=
[]):
f
=
self
.
getTemporaryFile
(
suffix
=
'.py'
)
cmd
=
'python3 {0} {1}'
.
format
(
f
.
name
,
' '
.
join
(
args
))
previous_dir
=
os
.
getcwd
()
os
.
chdir
(
self
.
working_dir
)
p
=
subprocess
.
Popen
(
cmd
,
shell
=
True
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
os
.
chdir
(
previous_dir
)
if
p
.
returncode
:
raise
RuntimeError
(
'Failed to run snippet
\n
'
+
cmd
+
'
\n
'
+
stderr
.
decode
())
return
stdout
################################################################
class
SnippetCollection
(
Snippet
):
def
__init__
(
self
):
self
.
functions
=
dict
()
self
.
func_names
=
[]
def
addFunction
(
self
,
f_name
,
code
):
if
f_name
in
self
.
functions
:
raise
RuntimeError
(
'function already declared'
)
self
.
func_names
.
append
(
f_name
)
self
.
functions
[
f_name
]
=
Snippet
(
code
,
format_flag
=
True
)
self
.
compile
()
def
__getitem__
(
self
,
key
):
return
self
.
functions
[
key
]
def
flatten
(
self
):
global_input
=
"""
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cassert>
"""
+
'/'
*
70
+
'
\n\n
'
for
f_name
in
self
.
func_names
:
global_input
+=
"void {0}(){{
\n
"
.
format
(
f_name
)
global_input
+=
self
.
functions
[
f_name
]
.
content
global_input
+=
'
\n
}
\n\n
'
+
'/'
*
70
+
'
\n\n
'
global_input
+=
"""
int main(int argc, char ** argv){\n"""
for
f_name
in
self
.
func_names
:
global_input
+=
f_name
+
'();
\n
'
global_input
+=
'
\n
}
\n
'
flat
=
Snippet
(
global_input
,
format_flag
=
True
)
return
flat
def
compile
(
self
,
**
kwargs
):
global_snippet
=
self
.
flatten
()
global_snippet
.
compile
(
**
kwargs
)
def
save
(
self
,
filename
):
global_snippet
=
self
.
flatten
()
open
(
filename
,
'w'
)
.
write
(
global_snippet
.
content
)
def
pigment
(
self
,
*
args
):
return
self
.
flatten
()
.
pigment
(
*
args
)
def
last
(
self
):
return
self
.
functions
[
self
.
func_names
[
-
1
]]
################################################################
# def printMatlab(code):
#
# html_snippet = highlight(
# code, MatlabLexer(),
# HtmlFormatter(full=True, style='colorful',
# classprefix='matlab_'))
#
# display(HTML(html_snippet))
# # return html_snippet
# ## testing
# Snippet.default_output = 'latex'
# Snippet.default_line_numbering = True
#
# snippet = SnippetCollection()
# snippet.addFunction('if_syntax', '''
# int p, q;
# if (p > q) {
# /*
# Statement1;
# Statement2;
# */
# }
# ''')
#
# print (snippet['if_syntax'].pigment())
Event Timeline
Log In to Comment