Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F63660762
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
Tue, May 21, 16:42
Size
12 KB
Mime Type
text/x-python
Expires
Thu, May 23, 16:42 (2 d)
Engine
blob
Format
Raw Data
Handle
17802899
Attached To
R3683 Slides
snippet_helper.py
View Options
#!/usr/bin/env python3
import
subprocess
import
os
import
re
from
pygments
import
highlight
from
pygments.lexers
import
CppLexer
from
pygments.lexers
import
PythonLexer
# from pygments.lexer import RegexLexer
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
self
.
end
=
slice
.
stop
self
.
snippet
=
snippet
def
pigment
(
self
,
**
kwargs
):
kwargs
[
'start'
]
=
self
.
start
kwargs
[
'end'
]
=
self
.
end
return
self
.
snippet
.
pigment
(
**
kwargs
)
class
Snippet
(
object
):
"""
Snippet objects manipulate 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
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
,
include_paths
=
None
,
language
=
'cpp'
):
try
:
self
.
loadfile
(
inp
)
except
Exception
:
self
.
content
=
inp
.
strip
()
if
include_paths
is
None
:
self
.
include_paths
=
[]
else
:
self
.
include_paths
=
[
os
.
path
.
abspath
(
i
)
for
i
in
include_paths
]
if
format_flag
:
self
.
clang_format
()
if
compile_flag
:
self
.
compile
()
if
language
==
'cpp'
:
self
.
lexer
=
CppLexer
()
elif
language
==
'python'
:
self
.
lexer
=
PythonLexer
()
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
clang_format
(
self
):
f
=
NamedTemporaryFile
()
f
.
write
(
self
.
content
.
encode
())
f
.
flush
()
p
=
subprocess
.
Popen
(
'clang-format {0}'
.
format
(
f
.
name
),
shell
=
True
,
stdout
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
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
=
NamedTemporaryFile
(
suffix
=
'.cpp'
,
delete
=
False
)
f
.
write
(
self
.
content
.
encode
())
f
.
flush
()
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
,
working_dir
=
'/tmp'
):
f
=
NamedTemporaryFile
(
suffix
=
'.cpp'
,
delete
=
False
)
f
.
write
(
self
.
content
.
encode
())
f
.
flush
()
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} -c {0}'
.
format
(
f
.
name
,
include_paths
),
shell
=
True
,
stderr
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
ret
=
p
.
returncode
os
.
chdir
(
previous_dir
)
if
ret
!=
0
:
raise
Snippet
.
CompilationError
(
'compilation failed
\n
'
+
stderr
.
decode
(
'utf-8'
))
os
.
remove
(
f
.
name
)
o_file
=
os
.
path
.
splitext
(
f
.
name
)[
0
]
+
'.o'
os
.
remove
(
o_file
)
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
=
'\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
pigment
(
self
,
keyword
=
None
,
line_highlight
=
None
,
start
=
None
,
end
=
None
,
output
=
None
,
line_numbering
=
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
)
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
=
_content
[
start
-
1
:
end
]
snip
=
''
.
join
(
snip
)
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
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