Add lilypond-book module and add support for instant preview.

Patch by Julien Rioux.
http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg162042.html



git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@35472 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Pavel Sanda 2010-09-21 16:34:30 +00:00
parent a5776fcc64
commit e7dd1bf9dd
6 changed files with 2346 additions and 7 deletions

View File

@ -257,6 +257,7 @@ dist_examples_DATA = \
examples/iecc12.fen \
examples/instant_preview.lyx \
examples/landslide.lyx \
examples/lilypond.lyx \
examples/linguistics.lyx \
examples/listerrors.lyx \
examples/modernCV.lyx \
@ -1100,6 +1101,7 @@ dist_layouts_DATA =\
layouts/kluwer.layout \
layouts/latex8.layout \
layouts/letter.layout \
layouts/lilypond.module \
layouts/linguistics.module \
layouts/literate-article.layout \
layouts/literate-book.layout \
@ -1209,6 +1211,7 @@ dist_scripts_PYTHON = \
scripts/legacy_lyxpreview2ppm.py \
scripts/listerrors \
scripts/lyxpreview2bitmap.py \
scripts/lyxpreview-lytex2bitmap.py \
scripts/lyxpreview-platex2bitmap.py \
scripts/lyxpreview_tools.py \
scripts/tex_copy.py

View File

@ -505,6 +505,7 @@ def checkFormatEntries(dtl_tools):
\Format literate nw NoWeb N "" "%%" "document"
\Format sweave Rnw "Sweave" S "" "%%" "document"
\Format lilypond ly "LilyPond music" "" "" "%%" "vector"
\Format lilypond-book lytex "LilyPond book (LaTeX)" "" "" "%%" "document"
\Format latex tex "LaTeX (plain)" L "" "%%" "document"
\Format pdflatex tex "LaTeX (pdflatex)" "" "" "%%" "document"
\Format xetex tex "LaTeX (XeTeX)" "" "" "%%" "document"
@ -572,6 +573,7 @@ def checkFormatEntries(dtl_tools):
\Format jlyx cjklyx "CJK LyX 1.4.x (euc-jp)" "" "" "" "document"
\Format klyx cjklyx "CJK LyX 1.4.x (euc-kr)" "" "" "" "document"
\Format lyxpreview lyxpreview "LyX Preview" "" "" "" ""
\Format lyxpreview-lytex lyxpreview-lytex "LyX Preview (LilyPond book)" "" "" "" ""
\Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)" "" "" "" ""
\Format pdftex pdftex_t PDFTEX "" "" "" ""
\Format program "" Program "" "" "" ""
@ -807,7 +809,7 @@ def checkConverterEntries():
addToRC(r'''\converter lilypond eps "lilypond -dbackend=eps --ps $$i" ""
\converter lilypond png "lilypond -dbackend=eps --png $$i" ""''')
addToRC(r'\converter lilypond pdf "lilypond -dbackend=eps --pdf $$i" ""')
print '+ found LilyPond version %s.' % version_number
logger.info('+ found LilyPond version %s.' % version_number)
elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
addToRC(r'''\converter lilypond eps "lilypond -b eps --ps $$i" ""
\converter lilypond png "lilypond -b eps --png $$i" ""''')
@ -819,6 +821,38 @@ def checkConverterEntries():
else:
logger.info('+ found LilyPond, but could not extract version number.')
#
path, lilypond_book = checkProg('a LilyPond book (LaTeX) -> LaTeX converter', ['lilypond-book'])
if (lilypond_book != ''):
version_string = cmdOutput("lilypond-book --version")
match = re.match('^(\S+)$', version_string)
if match:
version_number = match.groups()[0]
version = version_number.split('.')
if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 1):
addToRC(r'\converter lyxpreview-lytex ppm "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
if dvipng == "dvipng":
addToRC(r'\converter lyxpreview-lytex png "python -tt $$s/scripts/lyxpreview-lytex2bitmap.py" ""')
else:
addToRC(r'\converter lyxpreview-lytex png "" ""')
if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
# Note: The --lily-output-dir flag is required because lilypond-book
# does not process input again unless the input has changed,
# even if the output format being requested is different. So
# once a .eps file exists, lilypond-book won't create a .pdf
# even when requested with --pdf. This is a problem if a user
# clicks View PDF after having done a View DVI. To circumvent
# this, use different output folders for eps and pdf outputs.
addToRC(r'\converter lilypond-book latex "lilypond-book --lily-output-dir=ly-eps $$i" ""')
addToRC(r'\converter lilypond-book pdflatex "lilypond-book --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$i" ""')
logger.info('+ found LilyPond-book version %s.' % version_number)
elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 1):
addToRC(r'\converter lilypond-book latex "lilypond-book $$i" ""')
logger.info('+ found LilyPond-book version %s.' % version_number)
else:
logger.info('+ found LilyPond-book, but version %s is too old.' % version_number)
else:
logger.info('+ found LilyPond-book, but could not extract version number.')
#
checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
rc_entry = [ r'\converter noteedit lilypond "%%" ""', ''])
#

2020
lib/examples/lilypond.lyx Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
#\DeclareLyXModule[lilypond-book->latex]{LilyPond Book}
#DescriptionBegin
#This module adds an inset to enter LilyPond code directly into LyX.
#It will be processed in the output. See the lilypond.lyx example file.
#DescriptionEnd
# Author: Julien Rioux <jrioux@physics.utoronto.ca>
Format 27
OutputFormat lilypond-book
InsetLayout LilyPond
LabelString LilyPond
LaTeXType Environment
LaTeXName lilypond
LyXType Custom
Decoration Classic
Font
Color latex
Family typewriter
EndFont
LabelFont
Color latex
Size Small
EndFont
MultiPar true
CustomPars false
ForcePlain true
FreeSpacing true
PassThru true
ForceLTR true
End

View File

@ -0,0 +1,250 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# file lyxpreview-lytex2bitmap.py
# This file is part of LyX, the document processor.
# Licence details can be found in the file COPYING.
# author Angus Leeming
# with much advice from members of the preview-latex project:
# David Kastrup, dak@gnu.org and
# Jan-Åke Larsson, jalar@mai.liu.se.
# Full author contact details are available in file CREDITS
# This script takes a LaTeX file and generates a collection of
# png or ppm image files, one per previewed snippet.
# Pre-requisites:
# * A latex executable;
# * preview.sty;
# * dvipng;
# * pngtoppm (if outputing ppm format images).
# preview.sty and dvipng are part of the preview-latex project
# http://preview-latex.sourceforge.net/
# preview.sty can alternatively be obtained from
# CTAN/support/preview-latex/
# Example usage:
# lyxpreview-lytex2bitmap.py png 0lyxpreview.tex 128 000000 faf0e6
# This script takes six arguments:
# FORMAT: The desired output format. Either 'png' or 'ppm'.
# TEXFILE: the name of the .tex file to be converted.
# DPI: a scale factor, used to ascertain the resolution of the
# generated image which is then passed to gs.
# FG_COLOR: the foreground color as a hexadecimal string, eg '000000'.
# BG_COLOR: the background color as a hexadecimal string, eg 'faf0e6'.
# CONVERTER: the converter (optional). Default is latex.
# Decomposing TEXFILE's name as DIR/BASE.tex, this script will,
# if executed successfully, leave in DIR:
# * a (possibly large) number of image files with names
# like BASE[0-9]+.png
# * a file BASE.metrics, containing info needed by LyX to position
# the images correctly on the screen.
import glob, os, re, shutil, string, sys
from legacy_lyxpreview2ppm import legacy_conversion, \
legacy_conversion_step2
from lyxpreview_tools import copyfileobj, error, find_exe, \
find_exe_or_terminate, make_texcolor, mkstemp, run_command, warning
# Pre-compiled regular expressions.
latex_file_re = re.compile("\.tex$")
def usage(prog_name):
return "Usage: %s <format> <latex file> <dpi> <fg color> <bg color>\n"\
"\twhere the colors are hexadecimal strings, eg 'faf0e6'"\
% prog_name
def extract_metrics_info(dvipng_stdout, metrics_file):
metrics = open(metrics_file, 'w')
# "\[[0-9]+" can match two kinds of numbers: page numbers from dvipng
# and glyph numbers from mktexpk. The glyph numbers always match
# "\[[0-9]+\]" while the page number never is followed by "\]". Thus:
page_re = re.compile("\[([0-9]+)[^]]");
metrics_re = re.compile("depth=(-?[0-9]+) height=(-?[0-9]+)")
success = 0
page = ""
pos = 0
while 1:
match = page_re.search(dvipng_stdout, pos)
if match == None:
break
page = match.group(1)
pos = match.end()
match = metrics_re.search(dvipng_stdout, pos)
if match == None:
break
success = 1
# Calculate the 'ascent fraction'.
descent = string.atof(match.group(1))
ascent = string.atof(match.group(2))
frac = 0.5
if ascent >= 0 or descent >= 0:
if abs(ascent + descent) > 0.1:
frac = ascent / (ascent + descent)
# Sanity check
if frac < 0:
frac = 0.5
metrics.write("Snippet %s %f\n" % (page, frac))
pos = match.end() + 2
return success
def color_pdf(latex_file, bg_color):
use_preview_pdf_re = re.compile("(\s*\\\\usepackage\[[^]]+)(pdftex\]{preview})")
tmp = mkstemp()
success = 0
try:
for line in open(latex_file, 'r').readlines():
match = use_preview_pdf_re.match(line)
if match == None:
tmp.write(line)
continue
success = 1
tmp.write(" \\usepackage{color}\n" \
" \\pagecolor[rgb]{%s}\n" \
"%s\n" \
% (bg_color, match.group()))
continue
except:
# Unable to open the file, but do nothing here because
# the calling function will act on the value of 'success'.
warning('Warning in color_pdf! Unable to open "%s"' % latex_file)
warning(`sys.exc_type` + ',' + `sys.exc_value`)
if success:
copyfileobj(tmp, open(latex_file,"wb"), 1)
return success
def convert_to_ppm_format(pngtopnm, basename):
png_file_re = re.compile("\.png$")
for png_file in glob.glob("%s*.png" % basename):
ppm_file = png_file_re.sub(".ppm", png_file)
p2p_cmd = '%s "%s"' % (pngtopnm, png_file)
p2p_status, p2p_stdout = run_command(p2p_cmd)
if p2p_status != None:
error("Unable to convert %s to ppm format" % png_file)
ppm = open(ppm_file, 'w')
ppm.write(p2p_stdout)
os.remove(png_file)
def main(argv):
# Parse and manipulate the command line arguments.
if len(argv) != 6 and len(argv) != 7:
error(usage(argv[0]))
output_format = string.lower(argv[1])
dir, latex_file = os.path.split(argv[2])
if len(dir) != 0:
os.chdir(dir)
dpi = string.atoi(argv[3])
fg_color = make_texcolor(argv[4], False)
bg_color = make_texcolor(argv[5], False)
bg_color_gr = make_texcolor(argv[5], True)
# External programs used by the script.
path = string.split(os.environ["PATH"], os.pathsep)
if len(argv) == 7:
latex = argv[6]
else:
latex = find_exe_or_terminate(["latex", "pplatex", "platex", "latex2e"], path)
lilypond_book = find_exe_or_terminate(["lilypond-book"], path)
# Make a copy of the latex file
lytex_file = latex_file_re.sub(".lytex", latex_file)
shutil.copyfile(latex_file, lytex_file)
# Preprocess the latex file through lilypond-book.
lytex_call = '%s --latex-program=%s "%s"' % (lilypond_book, latex, lytex_file)
lytex_status, lytex_stdout = run_command(lytex_call)
if lytex_status != None:
warning("%s failed to compile %s" \
% (os.path.basename(lilypond_book), lytex_file))
warning(lytex_stdout)
# This can go once dvipng becomes widespread.
dvipng = find_exe(["dvipng"], path)
if dvipng == None:
# The data is input to legacy_conversion in as similar
# as possible a manner to that input to the code used in
# LyX 1.3.x.
vec = [ argv[0], argv[2], argv[3], argv[1], argv[4], argv[5], latex ]
return legacy_conversion(vec)
pngtopnm = ""
if output_format == "ppm":
pngtopnm = find_exe_or_terminate(["pngtopnm"], path)
# Move color information for PDF into the latex file.
if not color_pdf(latex_file, bg_color_gr):
error("Unable to move color info into the latex file")
# Compile the latex file.
latex_call = '%s "%s"' % (latex, latex_file)
latex_status, latex_stdout = run_command(latex_call)
if latex_status != None:
warning("%s failed to compile %s" \
% (os.path.basename(latex), latex_file))
warning(latex_stdout)
if latex == "xelatex":
warning("Using XeTeX")
# FIXME: skip unnecessary dvips trial in legacy_conversion_step2
return legacy_conversion_step2(latex_file, dpi, output_format)
# Run the dvi file through dvipng.
dvi_file = latex_file_re.sub(".dvi", latex_file)
dvipng_call = '%s -Ttight -depth -height -D %d -fg "%s" -bg "%s" "%s"' \
% (dvipng, dpi, fg_color, bg_color, dvi_file)
dvipng_status, dvipng_stdout = run_command(dvipng_call)
if dvipng_status != None:
warning("%s failed to generate images from %s ... looking for PDF" \
% (os.path.basename(dvipng), dvi_file))
# FIXME: skip unnecessary dvips trial in legacy_conversion_step2
return legacy_conversion_step2(latex_file, dpi, output_format)
# Extract metrics info from dvipng_stdout.
metrics_file = latex_file_re.sub(".metrics", latex_file)
if not extract_metrics_info(dvipng_stdout, metrics_file):
error("Failed to extract metrics info from dvipng")
# Convert images to ppm format if necessary.
if output_format == "ppm":
convert_to_ppm_format(pngtopnm, latex_file_re.sub("", latex_file))
return 0
if __name__ == "__main__":
main(sys.argv)

View File

@ -388,12 +388,12 @@ namespace graphics {
PreviewLoader::Impl::Impl(PreviewLoader & p, Buffer const & b)
: parent_(p), buffer_(b)
{
if (!pconverter_){
if (b.params().encoding().package() == Encoding::japanese)
pconverter_ = setConverter("lyxpreview-platex");
else
pconverter_ = setConverter("lyxpreview");
}
if (b.bufferFormat() == "lilypond-book")
pconverter_ = setConverter("lyxpreview-lytex");
else if (b.params().encoding().package() == Encoding::japanese)
pconverter_ = setConverter("lyxpreview-platex");
else
pconverter_ = setConverter("lyxpreview");
}