From b867b0877d5457908ba5677ba98ac3f200f32b85 Mon Sep 17 00:00:00 2001 From: Brandon Mathis Date: Mon, 28 May 2012 04:29:18 -0500 Subject: [PATCH] Refactored code plugins so that shared regexes are mixed in methods Added option to mark one line or groups of lines in a code block Relates to issue #584 --- plugins/backtick_code_block.rb | 30 +++++----- plugins/code_block.rb | 30 +++++----- plugins/include_code.rb | 49 ++++++++------- plugins/pygments_code.rb | 105 +++++++++++++++++++++++++++++---- 4 files changed, 147 insertions(+), 67 deletions(-) diff --git a/plugins/backtick_code_block.rb b/plugins/backtick_code_block.rb index 055aebe..c4581bf 100644 --- a/plugins/backtick_code_block.rb +++ b/plugins/backtick_code_block.rb @@ -8,23 +8,23 @@ module BacktickCodeBlock input.encode!("UTF-8") input.gsub /^`{3}(.+?)`{3}/m do str = $1.to_s - linenos = true - start = 1 str.gsub /([^\n]+)?\n(.+?)\Z/m do - @options = $1 || '' + markup = $1 || '' code = $2.to_s - if @options =~ /\s*linenos:false/i - linenos = false - @options = @options.sub(/\s*linenos:false/i,'') - end - if @options =~ /\s*start:(\d+)/i - start = $1.to_i - @options = @options.sub(/\s*start:\d+/i,'') - end - if @options =~ AllOptions - highlight(code, $1, {caption: $2, url: $3, anchor: $4 || 'Link', linenos: linenos, start: start}) - elsif @options =~ LangCaption - highlight(code, $1, {caption: $2 || '', linenos: linenos, start: start}) + + linenos = get_linenos(markup) + markup = replace_linenos(markup) + + marks = get_marks(markup) + markup = replace_marks(markup) + + start = get_start(markup) + markup = replace_start(markup) + + if markup =~ AllOptions + highlight(code, $1, {caption: $2, url: $3, anchor: $4 || 'Link', linenos: linenos, start: start, marks: marks}) + elsif markup =~ LangCaption + highlight(code, $1, {caption: $2 || '', linenos: linenos, start: start, marks: marks}) else highlight(code, 'plain', {linenos: linenos, start: start}) end diff --git a/plugins/code_block.rb b/plugins/code_block.rb index 18a416c..8cbb7ad 100644 --- a/plugins/code_block.rb +++ b/plugins/code_block.rb @@ -54,21 +54,19 @@ module Jekyll def initialize(tag_name, markup, tokens) @caption = nil @url = nil - @lang = nil - @start = 1 - @linenos = true - if markup =~ /\s*lang:(\w+)/i - @lang = $1 - markup = markup.sub(/lang:\w+/i,'') - end - if markup.strip =~ /\s*linenos:false/i - @linenos = false - markup = markup.strip.sub(/linenos:false/i,'') - end - if markup =~ /\s*start:(\d+)/i - @start = $1.to_i - markup = markup.sub(/\s*start:\d+/i,'') - end + + @lang = get_lang(markup) + markup = replace_lang(markup) + + @linenos = get_linenos(markup) + markup = replace_linenos(markup) + + @mark = get_marks(markup) + markup = replace_marks(markup) + + @start = get_start(markup) + markup = replace_start(markup) + if markup =~ CaptionUrlTitle @caption = $1 @url = $2 + $3 @@ -87,7 +85,7 @@ module Jekyll def render(context) code = super.strip - code = highlight(code, @lang, {caption: @caption, url: @url, anchor: @anchor, start: @start, linenos: @linenos}) + code = highlight(code, @lang, {caption: @caption, url: @url, anchor: @anchor, start: @start, marks: @marks, linenos: @linenos}) code = context['pygments_prefix'] + code if context['pygments_prefix'] code = code + context['pygments_suffix'] if context['pygments_suffix'] code diff --git a/plugins/include_code.rb b/plugins/include_code.rb index 8886efd..94eb534 100644 --- a/plugins/include_code.rb +++ b/plugins/include_code.rb @@ -30,30 +30,27 @@ module Jekyll def initialize(tag_name, markup, tokens) @title = nil @file = nil - @start = 1 - @end = nil - @linenos = true - if markup.strip =~ /\s*lang:(\w+)/i - @filetype = $1 - markup = markup.strip.sub(/lang:\w+/i,'') - end - if markup.strip =~ /\s*linenos:false/i - @linenos = false - markup = markup.strip.sub(/linenos:false/i,'') - end - if markup =~ /\s*start:(\d+)/i - @start = $1.to_i - markup = markup.sub(/\s*start:\d+/i,'') - end - if markup =~ /\s*end:(\d+)/i - @end = $1.to_i - markup = markup.sub(/\s*end:\d+/i,'') - end - if markup =~ /\s*range:(\d+),(\d+)/i - @start = $1.to_i - @end = $2.to_i - markup = markup.sub(/\s*range:\d+,\d+/i,'') - end + + @lang = get_lang(markup) + markup = replace_lang(markup) + + @linenos = get_linenos(markup) + markup = replace_linenos(markup) + + @marks = get_marks(markup) + markup = replace_marks(markup) + + @start = get_start(markup) + markup = replace_start(markup) + + @end = get_end(markup) + markup = replace_end(markup) + + range = get_range(markup, @start, @end) + @start = range[:start] + @end = range[:start] + markup = replace_range(markup) + if markup.strip =~ /(.*)?(\s+|^)(\/*\S+)/i @title = $1 || nil @file = $3 @@ -83,10 +80,10 @@ module Jekyll if @start > 1 or @end < length code = code.split(/\n/).slice(@start -1, @end + 1 - @start).join("\n") end - @filetype = file.extname.sub('.','') if @filetype.nil? + @lang = file.extname.sub('.','') unless @lang title = @title ? "#{@title} (#{file.basename})" : file.basename url = "/#{code_dir}/#{@file}" - highlight(code, @filetype, {caption: title, url: url, anchor: 'download', start: @start, linenos: @linenos}) + highlight(code, @lang, {caption: title, url: url, anchor: 'download', start: @start, marks: @marks, linenos: @linenos }) end end end diff --git a/plugins/pygments_code.rb b/plugins/pygments_code.rb index a06d59d..86b6cd6 100644 --- a/plugins/pygments_code.rb +++ b/plugins/pygments_code.rb @@ -29,12 +29,13 @@ module HighlightCode lang = 'perl' if lang == 'pl' lang = 'yaml' if lang == 'yml' lang = 'coffeescript' if lang == 'coffee' - lang = 'plain' if lang == '' or lang.nil? + lang = 'plain' if lang == '' or lang.nil? or !lang - caption = options[:caption] || nil - url = options[:url] || nil - anchor = options[:anchor] || nil - wrap = options[:wrap] || true + caption = options[:caption] || nil + url = options[:url] || nil + anchor = options[:anchor] || nil + wrap = options[:wrap] || true + marks = options[:marks] linenos = options[:linenos] start = options[:start] @@ -49,7 +50,7 @@ module HighlightCode code = pygments(code, lang).match(/
(.+)<\/pre>/m)[1].gsub(/ *$/, '') #strip out divs 
end - code = tableize_code(code, lang, { linenos: linenos, start: start }) + code = tableize_code(code, lang, { linenos: linenos, start: start, marks: marks }) caption = captionize(caption, url, anchor) if caption figure = "
#{caption}#{code}
" @@ -66,19 +67,103 @@ module HighlightCode def tableize_code (code, lang, options = {}) start = options[:start] lines = options[:linenos].nil? ? true : options[:linenos] + marks = options[:marks] || [] table = "
" - table += number_lines(start, code.lines.count) if lines + table += number_lines(start, code.lines.count, marks) if lines table += "
"
-    table += code.gsub /^((.+)?(\n?))/, '\1'
+    if marks.size
+      code.lines.each_with_index do |line,index|
+        table += "#{line}"
+      end
+    else
+      table += code.gsub /^((.+)?(\n?))/, '\1'
+    end
     table +="
" end - def number_lines (start, count) + def number_lines (start, count, marks) start ||= 1 lines = "
"
     count.times do |index|
-      lines += "#{index + start}\n"
+      lines += "#{index + start}\n"
     end
     lines += "
" end + + def get_lang (input) + lang = nil + if input =~ /\s*lang:(\w+)/i + lang = $1 + end + lang + end + + def replace_lang (input) + input.sub /\s*lang:\w+/i, '' + end + + def get_marks (input) + # Matches pattern for line marks and returns array of line numbers to mark + # Example input mark:1,5-10,2 + # Outputs: [1,2,5,6,7,8,9,10] + marks = [] + if input =~ /\s*mark:(\d\S*)/i + marks = $1.gsub /(\d+)-(\d+)/ do + ($1.to_i..$2.to_i).to_a.join(',') + end + marks = marks.split(',').collect {|s| s.to_i}.sort + end + marks + end + + def replace_marks (input) + input.sub(/\s*mark:\d\S*/i,'') + end + + def get_linenos (input) + linenos = true + if input =~ /\s*linenos:false/i + linenos = false + end + linenos + end + + def replace_linenos (input) + input.sub(/\s*linenos:false/i,'') + end + + def get_start (input) + start = 1 + if input =~ /\s*start:(\d+)/i + start = $1.to_i + end + start + end + + def replace_start (input) + input.sub(/\s*start:\d+/i,'') + end + + def get_end (input) + endline = nil + if input =~ /\s*end:(\d+)/i + endline = $1.to_i + end + endline + end + + def replace_end (input) + input.sub(/\s*end:\d+/i,'') + end + + def get_range (input, start, endline) + if input =~ /\s*range:(\d+),(\d+)/i + start = $1.to_i + eneline = $2.to_i + end + {start: start, end: endline} + end + def replace_range (input) + input.sub(/\s*range:\d+,\d+/i,'') + end end