##// END OF EJS Templates
fix write binary and non math $...
Matthias BUSSONNIER -
Show More
@@ -1,73 +1,76 b''
1 """
1 """
2 Module that allows latex output notebooks to be conditioned before
2 Module that allows latex output notebooks to be conditioned before
3 they are converted.
3 they are converted.
4 """
4 """
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 # Configurable traitlets
7 # Configurable traitlets
8
8
9 # Needed to override transformer
9 # Needed to override transformer
10 from .transformers import (ActivatableTransformer)
10 from .transformers import (ActivatableTransformer)
11
11
12 class LatexTransformer(ActivatableTransformer):
12 class LatexTransformer(ActivatableTransformer):
13 """
13 """
14 Converter for latex destined documents.
14 Converter for latex destined documents.
15 """
15 """
16
16
17 def cell_transform(self, cell, other, index):
17 def cell_transform(self, cell, other, index):
18 """
18 """
19 Apply a transformation on each cell,
19 Apply a transformation on each cell,
20
20
21 receive the current cell, the resource dict and the index of current cell as parameter.
21 receive the current cell, the resource dict and the index of current cell as parameter.
22
22
23 Returns modified cell and resource dict.
23 Returns modified cell and resource dict.
24 """
24 """
25 if hasattr(cell, "source") and cell.cell_type == "markdown":
25 if hasattr(cell, "source") and cell.cell_type == "markdown":
26 cell.source = remove_math_space(cell.source)
26 cell.source = remove_math_space(cell.source)
27 return cell, other
27 return cell, other
28
28
29 def remove_math_space(text):
29 def remove_math_space(text):
30 """
30 """
31 Remove the space between latex math commands and enclosing $ symbols.
31 Remove the space between latex math commands and enclosing $ symbols.
32 """
32 """
33
33
34 # First, scan through the markdown looking for $. If
34 # First, scan through the markdown looking for $. If
35 # a $ symbol is found, without a preceding \, assume
35 # a $ symbol is found, without a preceding \, assume
36 # it is the start of a math block. UNLESS that $ is
36 # it is the start of a math block. UNLESS that $ is
37 # not followed by another within two math_lines.
37 # not followed by another within two math_lines.
38 math_regions = []
38 math_regions = []
39 math_lines = 0
39 math_lines = 0
40 within_math = False
40 within_math = False
41 math_start_index = 0
41 math_start_index = 0
42 ptext = ''
42 ptext = ''
43 last_character = ""
43 last_character = ""
44 skip = False
44 skip = False
45 for index, char in enumerate(text):
45 for index, char in enumerate(text):
46 #Make sure the character isn't preceeded by a backslash
46 #Make sure the character isn't preceeded by a backslash
47 if (char == "$" and last_character != "\\"):
47 if (char == "$" and last_character != "\\"):
48 # Close the math region if this is an ending $
48 # Close the math region if this is an ending $
49 if within_math:
49 if within_math:
50 within_math = False
50 within_math = False
51 skip = True
51 skip = True
52 ptext = ptext+'$'+text[math_start_index+1:index].strip()+'$'
52 ptext = ptext+'$'+text[math_start_index+1:index].strip()+'$'
53 math_regions.append([math_start_index, index+1])
53 math_regions.append([math_start_index, index+1])
54 else:
54 else:
55 # Start a new math region
55 # Start a new math region
56 within_math = True
56 within_math = True
57 math_start_index = index
57 math_start_index = index
58 math_lines = 0
58 math_lines = 0
59 # If we are in a math region, count the number of lines parsed.
59 # If we are in a math region, count the number of lines parsed.
60 # Cancel the math region if we find two line breaks!
60 # Cancel the math region if we find two line breaks!
61 elif char == "\n":
61 elif char == "\n":
62 if within_math:
62 if within_math:
63 math_lines += 1
63 math_lines += 1
64 if math_lines > 1:
64 if math_lines > 1:
65 within_math = False
65 within_math = False
66 ptext = ptext+text[math_start_index:index]+"\n"
67 print 'catching up with --',text[math_start_index:index],'--'
68
66 # Remember the last character so we can easily watch
69 # Remember the last character so we can easily watch
67 # for backslashes
70 # for backslashes
68 last_character = char
71 last_character = char
69 if not within_math and not skip:
72 if not within_math and not skip:
70 ptext = ptext+char
73 ptext = ptext+char
71 if skip:
74 if skip:
72 skip = False
75 skip = False
73 return ptext
76 return ptext
@@ -1,155 +1,155 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """
2 """
3 ================================================================================
3 ================================================================================
4
4
5 |,---. | | , .| |
5 |,---. | | , .| |
6 ||---', .|--- |---.,---.,---. |\ ||---.,---.,---.,---.. ,,---.,---.|---
6 ||---', .|--- |---.,---.,---. |\ ||---.,---.,---.,---.. ,,---.,---.|---
7 || | || | || || | | \ || || | || | \ / |---'| |
7 || | || | || || | | \ || || | || | \ / |---'| |
8 `` `---|`---'` '`---'` ' ` `'`---'`---'`---'` ' `' `---'` `---'
8 `` `---|`---'` '`---'` ' ` `'`---'`---'`---'` ' `' `---'` `---'
9 `---'
9 `---'
10 ================================================================================
10 ================================================================================
11
11
12 Highly experimental for now
12 Highly experimental for now
13
13
14 """
14 """
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 from __future__ import print_function
18 from __future__ import print_function
19 import sys
19 import sys
20 import io
20 import io
21 import os
21 import os
22
22
23 from converters.template import ConverterTemplate
23 from converters.template import ConverterTemplate
24 # From IPython
24 # From IPython
25
25
26 # All the stuff needed for the configurable things
26 # All the stuff needed for the configurable things
27 from IPython.config.application import Application
27 from IPython.config.application import Application
28 from IPython.config.loader import ConfigFileNotFound
28 from IPython.config.loader import ConfigFileNotFound
29 from IPython.utils.traitlets import Unicode, Bool
29 from IPython.utils.traitlets import Unicode, Bool
30
30
31 from converters.transformers import (ExtractFigureTransformer)
31 from converters.transformers import (ExtractFigureTransformer)
32
32
33 from converters.config import GlobalConfigurable
33 from converters.config import GlobalConfigurable
34
34
35
35
36 class NbconvertApp(Application):
36 class NbconvertApp(Application):
37 """A basic application to convert ipynb files
37 """A basic application to convert ipynb files
38
38
39 """
39 """
40
40
41 stdout = Bool(True, config=True,
41 stdout = Bool(True, config=True,
42 help="""
42 help="""
43 Wether to print the converted ipynb file to stdout
43 Wether to print the converted ipynb file to stdout
44 use full do diff files without actually writing a new file
44 use full do diff files without actually writing a new file
45 """)
45 """)
46
46
47 write = Bool(False, config=True,
47 write = Bool(False, config=True,
48 help="""Shoudl the converted notebook file be written to disk
48 help="""Shoudl the converted notebook file be written to disk
49 along with potential extracted resources.
49 along with potential extracted resources.
50 """
50 """
51 )
51 )
52
52
53 fileext = Unicode('txt', config=True,
53 fileext = Unicode('txt', config=True,
54 help="""Extension of the file that should be written to disk"""
54 help="""Extension of the file that should be written to disk"""
55 )
55 )
56
56
57 aliases = {
57 aliases = {
58 'stdout':'NbconvertApp.stdout',
58 'stdout':'NbconvertApp.stdout',
59 'write':'NbconvertApp.write',
59 'write':'NbconvertApp.write',
60 }
60 }
61
61
62 flags = {}
62 flags = {}
63 flags['no-stdout'] = (
63 flags['no-stdout'] = (
64 {'NbconvertApp' : {'stdout' : False}},
64 {'NbconvertApp' : {'stdout' : False}},
65 """Do not print converted file to stdout, equivalent to --stdout=False
65 """Do not print converted file to stdout, equivalent to --stdout=False
66 """
66 """
67 )
67 )
68
68
69 def __init__(self, **kwargs):
69 def __init__(self, **kwargs):
70 super(NbconvertApp, self).__init__(**kwargs)
70 super(NbconvertApp, self).__init__(**kwargs)
71 self.classes.insert(0, ConverterTemplate)
71 self.classes.insert(0, ConverterTemplate)
72 # register class here to have help with help all
72 # register class here to have help with help all
73 self.classes.insert(0, ExtractFigureTransformer)
73 self.classes.insert(0, ExtractFigureTransformer)
74 self.classes.insert(0, GlobalConfigurable)
74 self.classes.insert(0, GlobalConfigurable)
75
75
76 def load_config_file(self, profile_name):
76 def load_config_file(self, profile_name):
77 """load a config file from the config file dir
77 """load a config file from the config file dir
78
78
79 profile_name : {string} name of the profile file to load without file extension.
79 profile_name : {string} name of the profile file to load without file extension.
80 """
80 """
81 try:
81 try:
82 Application.load_config_file(
82 Application.load_config_file(
83 self,
83 self,
84 profile_name+'.nbcv',
84 profile_name+'.nbcv',
85 path=[os.path.join(os.getcwdu(), 'profile')]
85 path=[os.path.join(os.getcwdu(), 'profile')]
86 )
86 )
87 return True
87 return True
88 except ConfigFileNotFound:
88 except ConfigFileNotFound:
89 self.log.warn("Config file for profile '%s' not found, giving up ", profile_name)
89 self.log.warn("Config file for profile '%s' not found, giving up ", profile_name)
90 return False
90 return False
91
91
92
92
93 def initialize(self, argv=None):
93 def initialize(self, argv=None):
94 """parse command line and load config"""
94 """parse command line and load config"""
95 self.parse_command_line(argv)
95 self.parse_command_line(argv)
96 cl_config = self.config
96 cl_config = self.config
97 profile_file = argv[1]
97 profile_file = argv[1]
98 if not self.load_config_file(profile_file):
98 if not self.load_config_file(profile_file):
99 exit(1)
99 exit(1)
100 self.update_config(cl_config)
100 self.update_config(cl_config)
101
101
102
102
103
103
104 def run(self):
104 def run(self):
105 """Convert a notebook in one step"""
105 """Convert a notebook in one step"""
106 ipynb_file = (self.extra_args or [None])[2]
106 ipynb_file = (self.extra_args or [None])[2]
107
107
108 # If you are writting a custom transformer, append it to the dictionary
108 # If you are writting a custom transformer, append it to the dictionary
109 # below.
109 # below.
110 userpreprocessors = {}
110 userpreprocessors = {}
111
111
112 # Create the converter
112 # Create the converter
113 C = ConverterTemplate(config=self.config, preprocessors=userpreprocessors)
113 C = ConverterTemplate(config=self.config, preprocessors=userpreprocessors)
114
114
115 output, resources = C.from_filename(ipynb_file)
115 output, resources = C.from_filename(ipynb_file)
116 if self.stdout :
116 if self.stdout :
117 print(output.encode('utf-8'))
117 print(output.encode('utf-8'))
118
118
119 out_root = ipynb_file[:-6].replace('.', '_').replace(' ', '_')
119 out_root = ipynb_file[:-6].replace('.', '_').replace(' ', '_')
120
120
121 keys = resources.get('figures', {}).keys()
121 keys = resources.get('figures', {}).keys()
122 if self.write :
122 if self.write :
123 with io.open(os.path.join(out_root+'.'+self.fileext), 'w') as f:
123 with io.open(os.path.join(out_root+'.'+self.fileext), 'w') as f:
124 f.write(output)
124 f.write(output)
125 if keys :
125 if keys :
126 if self.write:
126 if self.write:
127 files_dir = out_root+'_files'
127 files_dir = out_root+'_files'
128 if not os.path.exists(out_root+'_files'):
128 if not os.path.exists(out_root+'_files'):
129 os.mkdir(files_dir)
129 os.mkdir(files_dir)
130 for key in keys:
130 for key in keys:
131 with io.open(os.path.join(files_dir, key), 'wb') as f:
131 with io.open(os.path.join(files_dir, key), 'w') as f:
132 f.write(resources['figures'][key])
132 f.write(resources['figures'][key])
133 elif self.stdout:
133 elif self.stdout:
134 print('''====================== Keys in Resources ==================================''')
134 print('''====================== Keys in Resources ==================================''')
135 print(resources['figures'].keys())
135 print(resources['figures'].keys())
136 print("""
136 print("""
137 ===========================================================================
137 ===========================================================================
138 you are responsible from writing those data do a file in the right place if
138 you are responsible from writing those data do a file in the right place if
139 they need to be.
139 they need to be.
140 ===========================================================================
140 ===========================================================================
141 """)
141 """)
142
142
143 def main():
143 def main():
144 """Convert a notebook to html in one step"""
144 """Convert a notebook to html in one step"""
145 app = NbconvertApp.instance()
145 app = NbconvertApp.instance()
146 app.description = __doc__
146 app.description = __doc__
147 app.initialize(argv=sys.argv)
147 app.initialize(argv=sys.argv)
148 app.start()
148 app.start()
149 app.run()
149 app.run()
150 #-----------------------------------------------------------------------------
150 #-----------------------------------------------------------------------------
151 # Script main
151 # Script main
152 #-----------------------------------------------------------------------------
152 #-----------------------------------------------------------------------------
153
153
154 if __name__ == '__main__':
154 if __name__ == '__main__':
155 main()
155 main()
General Comments 0
You need to be logged in to leave comments. Login now