Ok I've caught on to your version-control comments at the top and have
started adding to them. This time I added two things to the script:
1) recognition of the computer's OS (only Linux or Mac at this point),
and appropriate changes to the commands to accommodate. After this
change, the script works exactly the same (from user's perspective) on
both my Ubuntu and Mac OSX 10.4 systems :) I used to have to keep
separate versions of the script for each one.
2) added a "known issue" comment that the script doesn't handle spaces
in directory names. It fails at line 43 (cd $currentdir) if the
directory of the lilypond source file has a space in the name.
Patrick Horgan wrote:
Jonathan Kulp wrote:
Patrick! It's all working beautifully now.
I must say that you are most awesomely cool. How wonderful to find someone that
digs in in the best linux/Unix tradition and puts together a string of programs
to achieve a desired result. Hats off to you.
Working on this script is making me understand the genius of the Unix
model. Someone with no programming experience like me can make
something that gets a job done using a bunch of tiny tools. Really fun!
... much cool stuff elided...
p.s. now that we have a tool with a version number, I might try learning how
to write a brief manpage for it. Good idea?
A most excellent idea! manedit is your friend. Complete wysiwyg man editor.
Its help has a complete and easy tutorial. On ubuntu it's just *sudo apt-get
install manedit*. Since you're doing that I'm adding a -a (about) with your
name and mine, some more comments so others can modify it more easily, and will
call it version 1.1.1. I also added a -V=viewer, so I could use, for example
evince if the output format was ps. N.B. evince doesn't display transparency so
if you use it with transparent gifs or pngs you might think the transparency
gone, but it's not.
Cool. I'll try this after the kids are in bed tonight.
One feature it really needs is an ability to handle the situation where the
output for file.ly is for example, file-page1.png and file-page2.png. You'd
have to get a wildcard list of things that matched $STEM*.png and loop over them
to do the conversions, then something like $viewer $STEM*.$FORMAT & at the end.
That would make it work as it currently does for most things, there'd just be
one thing in the list, but still work for the case where there's something
there. A generic wildcard is best because someone might have done a #(define
output-suffix "blablabla") and we want to support that case too. eog will bring
up all the pages and let you page up and page down through them, and evince will
bring a a window for each file. There's enough examples in the script so that
you could figure out how to do it if you would. We could call it 1.1.2;) If
you don't have time let me know and I'll get to it sometime. If you do, change
the version in the script, add to the changelog at the top and send me a copy:)
Maybe we could donate it to the lilypond project.
Patrick
Yes. I haven't thought much about multiple-page documents yet because
for me the object of the script is to produce small images of musical
examples to use in a research paper or on a website. Are there
situations where you want multiple-page examples with whitespace cropped
like this? I could see where it'd be nice to make a longer document's
background transparent. It's certainly worth a try to deal with a
longer file. The more flexible the script is, the better, after all.
I'll poke around with it this weekend, perhaps.
Most recent version attached.
Jon
--
Jonathan Kulp
http://www.jonathankulp.com
#!/bin/bash
#*****************************************************#
# Script for making image files from lilypond source #
# suitable for use as musical examples to insert in a #
# document or web page. #
# Creator - Jonathan Kulp #
# Johnny come lately assistant - Patrick Horgan #
#*****************************************************#
# Change log
#
# 1.1.2 Added platform recognition--Darwin or Linux
# Known issue: does not handle spaces in directory names
# 1.1.1 Added -a, -V and much comments
# 1.1 Added checking of return codes so we could
# abort if something failed.
# 1.0 Initial release
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# setformatlist - gets the list of all the things that
# you can convert to
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setformatlist()
{
currentdir=`pwd` # Remember our current directory
examp=`which ppmtojpeg` # find out where the progs are
returnstatus=$?
if [ $returnstatus -eq 0 ] ; then
OUTDIR="`dirname $examp`" #grab the directory
cd $OUTDIR # change to it so we can
# find all the programs starting with ppmtoxxxx
# and remove the initial part so that we can
# figure out what ppms can be converted to
ppmtos=`ls ppmto* | sed -n s/ppmto//p`
# same for pnmto
pnmtos=`ls pnmto* | sed -n s/pnmto//p`
# Now combine the two, change the space separated
# list into individ line that sort can sort with
# -u to throw away duplicates, then change newlines
# back to spaces so we have a sorted list without
# duplicate of all things we can convert to
alltos=`echo $ppmtos $pnmtos | tr " " "\n" | sort -u | tr "\n" " "`
fi
cd $currentdir # Change back so we don't affect anything
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# usage is called when we're called incorrectly.
# it never returns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
usage()
{
echo "Usage: " `basename $0` " [-v] [-t] [-rN] [-fFORMAT] filename"
echo " -v print version number and quit"
echo " -a about - tell about us and exit"
echo " -t indicates transparency is desired"
echo " -r=N set resolution to N (usually 72-2000)"
echo " -f=FORMAT set format to FORMAT one of:"
echo " jpeg, png, tiff, gif, pcx, bmp"
echo " -V=viewer set image viewer, examp: -V=evince"
echo " filename a lilypond file"
exit -1
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# about - tell about us and exit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
about()
{
echo `basename $0`
echo " Creator Jonathan Kulp"
echo " Johnny-come-lately Patrick Horgan"
exit 0
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set prompt to the prompt you want to give a user
# goodvals to the list of acceptable values
# call getval
# when it returns your value is in outval
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getval()
{
flag="notdone"
[EMAIL PROTECTED]
until [ $flag == "done" ] ; do
echo -n $prompt " "
read inval
if [ A$inval == "A" ] ; then
# inval is empty
if [ A$default != 'A' ] ; then
# default is set to something
inval=$default
default=""
else
#inval is empty, no default
echo You must enter a value
index=0
echo -n "Expecting one of : "
while [ "$index" -lt "$elementcount" ] ; do
echo -n "${goodvals["$index"]}" " "
let index++
done
echo
fi
fi
if [ A$inval != "A" ] ; then
# inval not empty, either they sent us something
# or we got it from the default
index=0
while [ "$index" -lt "$elementcount" ] ; do
# Walk through list of goodvals to see if we got one
if [ ${goodvals[$index]} == $inval ] ; then
# Yep! We're done.
flag="done"
outval=${goodvals[$index]}
fi
let index++
done
if [ $flag != "done" ] ; then
# inval not in goodvals, let them know
index=0
echo -n "Expecting one of : "
while [ "$index" -lt "$elementcount" ] ; do
echo -n "${goodvals["$index"]}" " "
let index++
done
echo
fi
fi
done
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set prompt to the prompt you want to give a user
# call getnumval
# when it returns your value is in outval
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getnumval()
{
flag="notdone"
until [ $flag == "done" ] ; do
echo -n $prompt " "
read inval
if [ A$inval == "A" ] ; then
# inval is empty
if [ A$default != 'A' ] ; then
# but default is not, so use it
inval=$default
default=""
else
# no inval, no default
echo You must enter a value, expecting a positive numeric value
fi
fi
if [ "A"$inval != 'A' ] ; then
# inval set either from user or default
case $inval in
*[^0-9]*) echo "Error: expecting positive numeric value" ;;
* ) flag="done" ;;
esac
fi
done
outval=$inval
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# validatearg()
# set inarg to the value of the argument
# set goodvals to the list of acceptable values
# set prompt to the error message you'd like to give,
# for example "ERROR: bad value for transparency arg"
# this routine will append to it, " expecting: " and
# the list of values from goodvals, then call usage
# to exit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
validatearg()
{
flag="notgood"
[EMAIL PROTECTED]
index=0
if [ "A"$inarg != "A" ] ; then
while [ "$index" -lt "$elementcount" ] ; do
if [ ${goodvals[$index]} == $inarg ] ; then
flag="good"
outval=${goodvals[$index]}
fi
let index++
done
fi
if [ $flag != "good" ] ; then
index=0
echo -n $prompt
echo -n " expecting one of : "
while [ "$index" -lt "$elementcount" ] ; do
echo -n "${goodvals["$index"]}" " "
let index++
done
echo
usage
fi
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# getopt_simple - Orig by Chris Morgan, stolen from
# the ABS Guide and modified a bit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getopt_simple()
{
until [ -z "$1" ] ; do
if [ ${1:0:1} = '-' ] ; then
tmp=${1:1} # Strip off leading '-' . . .
if [ ${tmp:0:1} = '-' ] ; then
tmp=${tmp:1} # Allow double -
fi
parameter=${tmp%%=*} # Extract name.
value=${tmp##*=} # Extract value.
eval $parameter=$value
else
filename=$1
fi
shift
done
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Our program starts here. This is the equivalent of
# our main()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Give initial defaults to things so we can tell if they
# change
alltos=""
transparency='no'
t='no'
resolution=0
r=0
format='none'
f='none'
V='eog'
filename="none"
version=1.1
setformatlist # Gets list of all image formats we can convert to
if [ $returnstatus -ne 0 ] ; then
# Apparently none!
echo "Sorry, you have to have the netpbm utilities installed to use this."
exit 1
fi
# process all the options
getopt_simple $*
if [ "$v" == 'v' ] ; then
# version
echo `basename $0` version $version
exit
fi
viewer=$V # default to eog
if [ "$a" == 'a' ] ; then
about
fi
if [ $filename == "none" ] ; then
usage
fi
if [ $t != 'no' ] ; then
# We let them use -t or --transparency, so if they used -t, we shove
# the value in $transparency so we don't have to deal with both later
transparency=$t
fi
if [ $transparency != 'no' ] ; then
# if transparency is set, make that setting be 'Y' cause that's what
# we check for later.
transparency='Y'
fi
# We know $r starts numeric cause we initialize it to 0 if it's not numeric
# now the user put something in in not numeric
case $r in
*[^0-9]*) echo "Error: resolution not numeric"; usage ;;
esac
if [ $r -ne 0 ] ; then
# same as with -t, two versions of args, -r and --resolution
resolution=$r
fi
# Now check resolution for numeric...if it came from -r it has already
# been checked, but no harm checking again
case $resolution in
*[^0-9]*) echo "Error: resolution must be positive numeric"; usage ;;
esac
if [ $f != 'none' ] ; then
# fold -f into --format
format=$f
fi
if [ $format != "none" ] ; then
# They set format so check it
inarg=$format
goodvals=( $alltos )
prompt="Error: format arg incorrect"
validatearg
fi
# get filename from first argument
srcfile="`basename $filename`"
# get filename without .ly extension
STEM="`basename $filename .ly`"
# determine output directory
OUTDIR="`dirname $filename`"
# determine whether user is on Linux or mac OSX
OS=$(uname)
if [[ $resolution -ne 0 ]] ; then
echo Resolution set to $resolution dots per inch.
RES=$resolution
else
# ask for output resolution
prompt="Enter output resolution in DPI 72, 100, 300, 600, etc...(72): "
default=72
getnumval
RES=$outval
fi
# If transparency is not set, then prompt for it if format is not set yet, or
# if format is set to one of the ones that supports transparency, i.e. gif, png
if [ "$transparency" == 'no' ] ; then
if [[ ( "$format" == 'gif') || ( "$format" == 'png' ) || ( "$format" ==
'none' ) ]] ; then
# only prompt for transparency if format unset or set to gif or png
prompt="Transparency? y/N"
default="N"
goodvals=("y" "Y" "n" "N")
getval
transparency=$outval
fi
fi
# ask for desired final output format with a lot of complications based on
# whether transparency is set.
if [[ ( "$transparency" == "Y" ) || ( "$transparency" == "y" ) ]] ; then
if [[ ( "$format" != 'gif') && ( "$format" != 'png' ) ]] ; then
# if they ask for transparency and format's set to something other
# than gif or png we can't procede--it makes no sense, get them to
# resolve it.
if [[ "$format" != 'none' ]] ; then
echo "You ask for transparency which doesn't work with" $format
fi
prompt="Enter desired output format png, gif (png): "
default="png"
goodvals=("png" "gif")
getval
FORMAT=$outval
else
FORMAT=$format
fi
else
# we know transparency's not Y or y, but make any other value be 'no'
# so we only have one thing to check for later
transparency="no"
# transparency's not set, so if they gave us a format on the command
# line use that, else ask them for one.
if [[ $format != 'none' ]] ; then
echo Output format is $format
FORMAT=$format
else
prompt="Enter desired output format jpeg, png, tiff, gif, pcx, bmp ...
(png) : "
default='png'
goodvals=( $alltos )
getval
FORMAT=$outval
fi
fi
cd $OUTDIR
# run lilypond on file with png output for further processing...
# command determined by result of "uname" command earlier
if [ "$OS" == "Darwin" ]
then
/Applications/LilyPond.app/Contents/Resources/bin/lilypond --format=png
-dresolution=$RES $srcfile
else
lilypond --format=png -dresolution=$RES $srcfile
fi
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
echo lilypond failed--aborting
exit $returnstatus
fi
# The next commands crop the png file so that
# it only includes the example instead of an entire page.
# First convert image to pnm for processing with netpbm tools
pngtopnm $STEM.png > $STEM.pnm
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
echo pngtopnm failed converting the file to pnm so it could be
cropped--aborting
exit $returnstatus
fi
# crop all the white space off
pnmcrop -white $STEM.pnm > $STEM-cropped.pnm
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
echo pnmcrop failed--aborting
exit $returnstatus
fi
# Now look for a command to do the final conversion, assume we won't find it...
outcmd="invalid"
# assume ppmto$FORMAT will be found
which >& /dev/null ppmto$FORMAT
if [ $? -eq 0 ] ; then
outcmd=ppmto$FORMAT
else
# Nope, try pnmto$FORMAT and see if we find that
which >& /dev/null pnmto$FORMAT
if [ $? -eq 0 ] ; then
outcmd=pnmto$FORMAT
fi
fi
if [ $outcmd == "invalid" ] ; then
# Baboo! Didn't find the command
echo "Sorry, can't find a command for that format."
exit -1
fi
# convert to end format
if [[ $transparency != 'no' ]] ; then
echo $outcmd -transparent '#ffffff' $STEM-cropped.pnm
$outcmd -transparent '#ffffff' $STEM-cropped.pnm > $STEM.$FORMAT
else
echo $outcmd $STEM-cropped.pnm
$outcmd $STEM-cropped.pnm > $STEM.$FORMAT
fi
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
echo $outcmd failed converting to final output--aborting
exit $returnstatus
fi
# removes pnm and ps files
rm *.pnm
if [ $FORMAT != 'ps' ] ; then
rm $STEM.ps
fi
# open final image as background process in "Eye of Gnome" Image Viewer
# or alternate viewer set via the -V argument
if [ "$OS" == "Darwin" ]
then
open $STEM.$FORMAT
else
$viewer $STEM.$FORMAT &
fi
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-user