-
Notifications
You must be signed in to change notification settings - Fork 386
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from mwouts/v0.3.0
V0.3.0
- Loading branch information
Showing
30 changed files
with
1,387 additions
and
696 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
from .languages import cell_language | ||
from .cell_metadata import metadata_to_rmd_options, rmd_options_to_metadata, \ | ||
json_options_to_metadata, metadata_to_json_options | ||
from nbformat.v4.nbbase import new_code_cell, new_markdown_cell | ||
import re | ||
|
||
|
||
def code_to_rmd(source, metadata, default_language): | ||
lines = [] | ||
language = cell_language(source) or default_language | ||
options = metadata_to_rmd_options(language, metadata) | ||
lines.append(u'```{{{}}}'.format(options)) | ||
lines.extend(source) | ||
lines.append(u'```') | ||
return lines | ||
|
||
|
||
def cell_to_text(self, | ||
cell, | ||
next_cell=None, | ||
default_language='python'): | ||
source = cell.get('source').splitlines() | ||
metadata = cell.get('metadata', {}) | ||
skipline = True | ||
if 'noskipline' in metadata: | ||
skipline = not metadata['noskipline'] | ||
del metadata['noskipline'] | ||
|
||
lines = [] | ||
if cell.cell_type == 'code': | ||
if self.ext == '.Rmd': | ||
lines.extend(code_to_rmd(source, metadata, default_language)) | ||
else: | ||
language = cell_language(source) or default_language | ||
if language == default_language: | ||
if self.ext == '.R': | ||
options = metadata_to_rmd_options(language, metadata)[2:] | ||
if options != '': | ||
lines.append('#+ ' + options) | ||
else: | ||
options = metadata_to_json_options(metadata) | ||
if options != '{}': | ||
lines.append('#+ ' + options) | ||
lines.extend(source) | ||
else: | ||
lines.extend(self.markdown_escape( | ||
code_to_rmd(source, metadata, default_language))) | ||
|
||
# Two blank lines before next code cell | ||
if next_cell and next_cell.cell_type == 'code': | ||
lines.append('') | ||
else: | ||
if source == []: | ||
source = [''] | ||
lines.extend(self.markdown_escape(source)) | ||
|
||
# Two blank lines between consecutive markdown cells | ||
if self.ext == '.Rmd' and next_cell \ | ||
and next_cell.cell_type == 'markdown': | ||
lines.append('') | ||
|
||
if skipline and next_cell: | ||
lines.append('') | ||
|
||
return lines | ||
|
||
|
||
_start_code_rmd = re.compile(r"^```\{(.*)\}\s*$") | ||
_start_code_md = re.compile(r"^```(.*)$") | ||
_end_code_md = re.compile(r"^```\s*$") | ||
_option_code_rpy = re.compile(r"^#\+(.*)$") | ||
_blank = re.compile(r"^\s*$") | ||
|
||
|
||
def start_code_rmd(line): | ||
return _start_code_rmd.match(line) | ||
|
||
|
||
def start_code_rpy(line): | ||
return _option_code_rpy.match(line) | ||
|
||
|
||
def text_to_cell(self, lines): | ||
if self.start_code(lines[0]): | ||
return self.code_to_cell(lines, parse_opt=True) | ||
elif self.prefix != '' and not lines[0].startswith(self.prefix): | ||
return self.code_to_cell(lines, parse_opt=False) | ||
else: | ||
return self.markdown_to_cell(lines) | ||
|
||
|
||
def parse_code_options(line, ext): | ||
if ext == '.Rmd': | ||
return rmd_options_to_metadata(_start_code_rmd.findall(line)[0]) | ||
elif ext == '.R': | ||
return rmd_options_to_metadata(_option_code_rpy.findall(line)[0]) | ||
else: # .py | ||
return 'python', json_options_to_metadata(_option_code_rpy.findall( | ||
line)[0]) | ||
|
||
|
||
def code_to_cell(self, lines, parse_opt): | ||
# Parse options | ||
if parse_opt: | ||
language, metadata = parse_code_options(lines[0], self.ext) | ||
if self.ext == '.Rmd': | ||
metadata['language'] = language | ||
else: | ||
metadata = {} | ||
|
||
# Find end of cell and return | ||
if self.ext == '.Rmd': | ||
for pos, line in enumerate(lines): | ||
if pos > 0 and _end_code_md.match(line): | ||
next_line_blank = pos + 1 == len(lines) or \ | ||
_blank.match(lines[pos + 1]) | ||
if next_line_blank and pos + 2 != len(lines): | ||
return new_code_cell( | ||
source='\n'.join(lines[1:pos]), metadata=metadata), \ | ||
pos + 2 | ||
else: | ||
r = new_code_cell( | ||
source='\n'.join(lines[1:pos]), | ||
metadata=metadata) | ||
r.metadata['noskipline'] = True | ||
return r, pos + 1 | ||
else: | ||
prev_blank = False | ||
for pos, line in enumerate(lines): | ||
if parse_opt and pos == 0: | ||
continue | ||
|
||
if self.prefix != '' and line.startswith(self.prefix): | ||
if prev_blank: | ||
return new_code_cell( | ||
source='\n'.join(lines[parse_opt:(pos - 1)]), | ||
metadata=metadata), pos | ||
else: | ||
r = new_code_cell( | ||
source='\n'.join(lines[parse_opt:pos]), | ||
metadata=metadata) | ||
r.metadata['noskipline'] = True | ||
return r, pos | ||
|
||
if _blank.match(line): | ||
if prev_blank: | ||
# Two blank lines at the end == empty code cell | ||
return new_code_cell( | ||
source='\n'.join(lines[parse_opt:(pos - 1)]), | ||
metadata=metadata), min(pos + 1, len(lines) - 1) | ||
prev_blank = True | ||
else: | ||
prev_blank = False | ||
|
||
# Unterminated cell? | ||
return new_code_cell( | ||
source='\n'.join(lines[parse_opt:]), | ||
metadata=metadata), len(lines) | ||
|
||
|
||
def markdown_to_cell(self, lines): | ||
md = [] | ||
for pos, line in enumerate(lines): | ||
# Markdown stops with the end of comments | ||
if line.startswith(self.prefix): | ||
md.append(self.markdown_unescape(line)) | ||
elif _blank.match(line): | ||
return new_markdown_cell(source='\n'.join(md)), pos + 1 | ||
else: | ||
r = new_markdown_cell(source='\n'.join(md)) | ||
r.metadata['noskipline'] = True | ||
return r, pos | ||
|
||
# still here => unterminated markdown | ||
return new_markdown_cell(source='\n'.join(md)), len(lines) | ||
|
||
|
||
def markdown_to_cell_rmd(lines): | ||
prev_blank = False | ||
for pos, line in enumerate(lines): | ||
if start_code_rmd(line): | ||
if prev_blank and pos > 1: | ||
return new_markdown_cell( | ||
source='\n'.join(lines[:(pos - 1)])), pos | ||
else: | ||
|
||
r = new_markdown_cell( | ||
source='\n'.join(lines[:pos])) | ||
r.metadata['noskipline'] = True | ||
return r, pos | ||
|
||
if _blank.match(line) and prev_blank: | ||
return new_markdown_cell( | ||
source='\n'.join(lines[:(pos - 1)])), pos + 1 | ||
prev_blank = _blank.match(line) | ||
|
||
# Unterminated cell? | ||
return new_markdown_cell(source='\n'.join(lines)), len(lines) |
Oops, something went wrong.