.PHONY : commands clean files
all : commands
-## commands : show all commands.
+## commands : show all commands.
commands :
@grep -h -E '^##' ${MAKEFILES} | sed -e 's/## //g'
-## serve : run a local server.
+## serve : run a local server.
serve : lesson-rmd
${JEKYLL} serve --config _config.yml,_config_dev.yml
-## site : build files but do not run a server.
+## site : build files but do not run a server.
site : lesson-rmd
${JEKYLL} build --config _config.yml,_config_dev.yml
-## figures : re-generate inclusion displaying all figures.
+## figures : re-generate inclusion displaying all figures.
figures :
@bin/extract_figures.py -s _episodes -p ${PARSER} > _includes/all_figures.html
-## clean : clean up junk files.
+## clean : clean up junk files.
clean :
@rm -rf ${DST}
@rm -rf .sass-cache
@find . -name '*~' -exec rm {} \;
@find . -name '*.pyc' -exec rm {} \;
-## clean-rmd : clean intermediate R files (that need to be committed to the repo).
+## clean-rmd : clean intermediate R files (that need to be committed to the repo).
clear-rmd :
@rm -rf ${RMD_DST}
@rm -rf fig/rmd-*
.PHONY : workshop-check
-## workshop-check : check workshop homepage.
+## workshop-check : check workshop homepage.
workshop-check :
@bin/workshop_check.py .
$(patsubst _extras/%.md,${DST}/%/index.html,$(wildcard _extras/*.md)) \
${DST}/license/index.html
-## lesson-rmd: : convert Rmarkdown files to markdown
+## lesson-rmd : convert Rmarkdown files to markdown
lesson-rmd: $(RMD_SRC)
@bin/knit_lessons.sh $(RMD_SRC)
-## lesson-check : validate lesson Markdown.
+## lesson-check : validate lesson Markdown.
lesson-check :
@bin/lesson_check.py -s . -p ${PARSER}
+## lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace.
+lesson-check-all :
+ @bin/lesson_check.py -s . -p ${PARSER} -l -w
+
+## unittest : run unit tests on checking tools.
unittest :
python bin/test_lesson_check.py
-## lesson-files : show expected names of generated files for debugging.
+## lesson-files : show expected names of generated files for debugging.
lesson-files :
@echo 'RMD_SRC:' ${RMD_SRC}
@echo 'RMD_DST:' ${RMD_DST}
@echo 'MARKDOWN_SRC:' ${MARKDOWN_SRC}
@echo 'HTML_DST:' ${HTML_DST}
-## lesson-fixme : show FIXME markers embedded in source files.
+## lesson-fixme : show FIXME markers embedded in source files.
lesson-fixme :
@fgrep -i -n FIXME ${MARKDOWN_SRC} || true
import re
from optparse import OptionParser
-from util import Reporter, read_markdown
+from util import Reporter, read_markdown, load_yaml
__version__ = '0.2'
parser = OptionParser()
parser.add_option('-l', '--linelen',
default=False,
- dest='line_len',
+ dest='line_lengths',
help='Check line lengths')
parser.add_option('-p', '--parser',
default=None,
default=os.curdir,
dest='source_dir',
help='source directory')
+ parser.add_option('-w', '--whitespace',
+ default=False,
+ dest='trailing_whitespace',
+ help='Check for trailing whitespace')
args, extras = parser.parse_args()
require(args.parser is not None,
"""Run tests on metadata."""
self.check_metadata()
- self.check_text()
+ self.check_line_lengths()
+ self.check_trailing_whitespace()
self.check_blockquote_classes()
self.check_codeblock_classes()
self.reporter.check_field(self.filename, 'metadata', self.metadata, 'layout', self.layout)
- def check_text(self):
+ def check_line_lengths(self):
"""Check the raw text of the lesson body."""
- if self.args.line_len:
+ if self.args.line_lengths:
over = [i for (i, l, n) in self.lines if (n > MAX_LINE_LEN) and (not l.startswith('!'))]
self.reporter.check(not over,
self.filename,
', '.join([str(i) for i in over]))
+ def check_trailing_whitespace(self):
+ """Check for whitespace at the ends of lines."""
+
+ if self.args.trailing_whitespace:
+ trailing = [i for (i, l, n) in self.lines if l.endswidth(' ')]
+ self.reporter.check(not trailing,
+ self.filename,
+ 'Line(s) end with whitespace: {0}',
+ ', '.join([str[i] for i in over]))
+
+
def check_blockquote_classes(self):
"""Check that all blockquotes have known classes."""
def load_yaml(filename):
"""
- Wrapper around YAML loading so that 'import yaml' and error
- handling is only needed in one place.
+ Wrapper around YAML loading so that 'import yaml' is only needed
+ in one file.
"""
- with open(filename, 'r') as reader:
- return yaml.load(reader)
+ try:
+ with open(filename, 'r') as reader:
+ return yaml.load(reader)
+ except (yaml.YAMLError, FileNotFoundError) as e:
+ print('Unable to load YAML file {0}:\n{1}'.format(filename, e), file=sys.stderr)
+ sys.exit(1)