Created
March 4, 2015 20:00
-
-
Save avdgaag/f40be301ef37a52b8c7b to your computer and use it in GitHub Desktop.
AsciiDoc filter for literate programming-style code blocks.
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
#!/usr/bin/env ruby | |
require 'open3' | |
require 'tmpdir' | |
module Literate | |
class Line | |
INDENT = ''.freeze | |
def self.indent(str) | |
return str if str == "" | |
str.gsub(/^/, INDENT) | |
end | |
def initialize(str) | |
@str = str | |
end | |
def to_s | |
@str | |
end | |
def cd? | |
!path.nil? | |
end | |
def path | |
@str[/^#{INDENT}%-? cd (.+)$/, 1] | |
end | |
def silent? | |
@str =~ /^#{INDENT}%- / | |
end | |
def ignore? | |
@str =~ /^#{INDENT}%% / | |
end | |
def command? | |
@str =~ /^#{INDENT}% / | |
end | |
def plain? | |
!silent? && !ignore? && !command? | |
end | |
def formatted_command | |
"#{INDENT}% #{command}\n" | |
end | |
def command | |
@command ||= | |
begin | |
@str[/^#{INDENT}%[-%]? (.+)$/, 1].gsub /\{\{(.+)\}\}/ do |match| | |
Command.capture($1.strip).chomp | |
end | |
end | |
end | |
end | |
def self.in_masked_tmpdir | |
original_directory = Dir.pwd | |
new_dir = File.join(Dir.pwd, 'tmp') | |
Dir.chdir(new_dir) | |
yield(new_dir).gsub(new_dir, "~/examples") | |
ensure | |
Dir.chdir original_directory | |
end | |
class LineReader | |
include Enumerable | |
def initialize(source) | |
@source = source | |
end | |
def each | |
@source.each_line do |line| | |
yield Line.new(line) | |
end | |
end | |
end | |
class Command | |
attr_reader :line | |
def initialize(line) | |
@line = line | |
end | |
def result | |
if line.silent? | |
run | |
'' | |
elsif line.ignore? || line.cd? | |
line.formatted_command | |
elsif line.command? | |
line.formatted_command + | |
Line.indent(run) | |
else | |
line.to_s | |
end | |
end | |
def self.capture(cmd) | |
input, output, wait_thr = Open3.popen2e(cmd) | |
output.read | |
ensure | |
input.close | |
output.close | |
end | |
private | |
def run | |
self.class.capture(line.command) | |
end | |
end | |
def self.literalize(str) | |
in_masked_tmpdir do |dir| | |
original_directory = dir | |
LineReader.new(str).each_with_object('') do |line, output| | |
if line.cd? | |
dir = File.join(dir, line.path) | |
raise "Invalid path: #{dir}" unless dir.start_with?(original_directory) | |
Dir.chdir(dir) | |
end | |
output << Command.new(line).result | |
end | |
end | |
end | |
end | |
puts Literate.literalize(STDIN.read) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment