Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 9a50fcf611
Fetching contributors…

Cannot retrieve contributors at this time

322 lines (276 sloc) 8.36 kB
# Copyright (c) 2009-2010 Fabio Cevasco
# website: http://www.h3rald.com/glyph
# license: MIT
# encoding: utf-8
require 'rubygems'
require 'pathname'
require 'yaml'
require 'gli'
require 'extlib'
require 'rake'
# Glyph is a Rapid Document Authoring Framework able to produce structured documents effortlessly.
module Glyph
# The directory containing Glyph library files
LIB = Pathname(__FILE__).dirname.expand_path/'glyph'
# The directory containing the full Glyph installation
HOME = LIB/'../../'
# The directory containing all Glyph tests
SPEC_DIR = Pathname(__FILE__).dirname.expand_path/'../spec'
# The directory containing all Glyph Rake tasks
TASKS_DIR = Pathname(__FILE__).dirname.expand_path/'../tasks'
require LIB/'system_extensions'
require LIB/'utils'
require LIB/'config'
require LIB/'node'
require LIB/'bookmark'
require LIB/'document'
require LIB/'macro_validators'
require LIB/'macro'
require LIB/'syntax_node'
require LIB/'parser'
require LIB/'interpreter'
require LIB/'analyzer'
require LIB/'reporter'
extend Glyph::Utils
# A generic Glyph error.
class Error < RuntimeError; end
# A syntax error.
class SyntaxError < Error; end
# A macro error.
class MacroError < Error
include Glyph::Utils
attr_reader :macro
# Initializes a new Glyph::MacroError
# @param [String] message the error message
# @param [Glyph::Macro] macro the macro that caused the error
def initialize(message, macro)
@macro = macro
super(message)
end
# Displays the error message, source, path and node value (if debugging)
def display
warning exception.message
path = @macro.path.blank? ? "" : "\n path: #{@macro.path}"
msg " source: #{@macro.source_name}#{path}"
msg "#{"-"*54}\n#{@macro.node.to_s.gsub(/\t/, ' ')}\n#{"-"*54}" if Glyph.debug?
end
end
# An infinite recursion error
class MutualInclusionError < MacroError; end
# The current version of Glyph
VERSION = "0.5.2"
# All the currently-loaded macros
MACROS = {}
# All the currently-loaded macro representations
REPS = {}
# All macro aliases
ALIASES = {:by_alias => {}, :by_def => {}}
begin
unless const_defined? :MODE then
MODE = {
:debug => false,
:lite => false,
:test => false,
:library => false,
:safe => false
}
end
rescue
end
# The main document being generated by Glyph
@@document = nil
(class << self; self; end).instance_eval do
["test", "lite", "debug", "library", "safe"].each do |mode|
define_method((mode+"?").to_sym) do
MODE[mode.to_sym]
end
define_method((mode+"_mode=")) do |m|
MODE[mode.to_sym] = m
end
end
end
# The directory of the current Glyph project.
PROJECT = (Glyph.test?) ? Glyph::SPEC_DIR/"test_project" : Pathname.new(Dir.pwd)
# Glyph's configuration
CONFIG = Glyph::Config.new :resettable => true, :mutable => false
home_dir = Pathname.new(RUBY_PLATFORM.match(/win32|mingw/) ? ENV['HOMEPATH'] : ENV['HOME'])
# System configuration
SYSTEM_CONFIG =
Glyph::Config.new(:file => HOME/'config.yml')
# Global configuration
GLOBAL_CONFIG =
Glyph.test? ? Glyph::Config.new(:file => SPEC_DIR/'.glyphrc') : Glyph::Config.new(:file => home_dir/'.glyphrc')
# Project configuration
PROJECT_CONFIG =
Glyph::Config.new(:file => PROJECT/'config.yml', :resettable => true) rescue Glyph::Config.new(:resettable => true, :mutable => true)
# Loads all Rake tasks
def self.setup
FileList["#{TASKS_DIR}/**/*.rake"].each do |f|
load f
end
end
# Used to access @@document
def self.document
@@document
end
# Used to set @@document
def self.document=(document)
@@document = document
end
# Returns the value of a configuration setting
def self.[](setting)
Glyph::CONFIG.get(setting)
end
# Overrides a configuration setting
# @param [String, Symbol] setting the configuration setting to change
# @param value the new value
def self.[]=(setting, value)
PROJECT_CONFIG.set setting, value
self.config_refresh
end
# Restores Glyph configuration (keeping all overrides and project settings)
def self.config_refresh
CONFIG.merge!(SYSTEM_CONFIG.merge(GLOBAL_CONFIG.merge(PROJECT_CONFIG)))
Glyph.safe_mode = Glyph['options.safe_mode']
end
# Resets Glyph configuration (removing all overrides and project settings)
def self.config_reset
Glyph::CONFIG.reset
Glyph::PROJECT_CONFIG.reset
self.config_refresh
end
# Resets Glyph completely, i.e.:
# * Re-enables all Glyph Rake tasks
# * Resets the configuration to system defaults
# * Clears macros and snippets
def self.reset
self.enable_all
self.config_reset
MACROS.clear
REPS.clear
end
# Reenables all Glyph Rake tasks
def self.enable_all
Rake::Task.tasks.each {|t| t.reenable }
end
# Reenables a Rake task
# @param [Symbol, String] task the task to enable
def self.enable(task)
Rake::Task[task].reenable
end
# Reenables and runs a Rake task
# @param [Symbol, String] task the task to run
# @param *args the task arguments
def self.run!(task, *args)
Rake::Task[task].reenable
self.run task, *args
end
# Runs a Rake task
# @param [Symbol, String] task the task to run
# @param *args the task arguments
def self.run(task, *args)
Rake::Task[task].invoke *args
end
# Defines a new macro
# @param [Symbol, String] name the name of the macro
def self.macro(name, &block)
MACROS[name.to_sym] = block
end
# Defines a new macro representation
# @since 0.5.0
# @param [Symbol, String] name the name of the macro
def self.rep(name, &block)
REPS[name.to_sym] = block
# Mirror aliases as well
ALIASES[:by_def][name.to_sym].to_a.each { |a| REPS[a] = block }
end
# Loads macro representations for a given output
# @since 0.5.0
# @param [Symbol, String] output a valid output format
def self.reps_for(output)
Glyph.instance_eval file_load(Glyph::HOME/"macros/reps/#{output}.rb") rescue nil
end
# Loads project macro representations for a given output
# @since 0.5.0
# @param [Symbol, String] output a valid output format
def self.project_reps_for(output)
Glyph.instance_eval file_load(Glyph::PROJECT/"lib/macros/reps/#{output}.rb") rescue nil
end
#@since 0.5.0
# Defines a new macro in Glyph code.
# @param [Symbol, String] name the name of the macro
# @param [String] text the Glyph code used to define the macro
def self.define(name, text)
macro name do
body = text.dup
# Parameters
body.gsub!(/\{\{(\d+)\}\}/) do
raw_param($1.to_i).to_s.strip
end
# Attributes
body.gsub!(/\{\{([^\[\]\|\\\s]+)\}\}/) do
raw_attr($1.to_sym).to_s.strip
end
interpret body
end
end
# Defines an alias for an existing macro
# @param [Hash] text the single-key hash defining the alias
# @example
# {:old_name => :new_name}
def self.macro_alias(pair)
name = pair.keys[0].to_sym
orig = pair.values[0].to_sym
ALIASES[:by_def][orig] = [] unless ALIASES[:by_def][orig]
ALIASES[:by_def][orig] << name unless ALIASES[:by_def][orig].include? name
ALIASES[:by_alias][name] = orig
MACROS[name] = MACROS[orig]
end
# Compiles a single Glyph file
# @param [String] src the full or relative path to the source file
# @param [String] out the full or relative path to the output file
def self.compile(src, out=nil)
pwd = Dir.pwd
Dir.chdir Pathname.new(src).parent.to_s
begin
require 'glyph/commands'
self['system.quiet'] = true
self.library_mode = true
TOPLEVEL_BINDING.eval('self').run ["compile", src.to_s, out].compact
rescue Exception => e
raise
ensure
Dir.chdir pwd
self.library_mode = false
self.lite_mode = false
self['system.quiet'] = false
end
end
# Converts a text containing Glyph markup language into the current Glyph output target.
#
# *Note* Only 'html' is supported as output target for now.
# @param [String] text the text to convert
# @return [String] the converted text
# @example
# require 'glyph'
# Glyph.filter "section[header[Test]\nA Test section...]"
def self.filter(text)
self.lite_mode = true
self.enable_all
result = ""
begin
self['system.quiet'] = true
self.library_mode = true
self.run 'load:all'
result = Interpreter.new(text).document.output
rescue Exception => e
raise
ensure
self.lite_mode = false
self.library_mode = false
self['system.quiet'] = false
end
result
end
end
Glyph.setup
Jump to Line
Something went wrong with that request. Please try again.