#!/usr/bin/env ruby =begin rdoc == match_parens - find mismatches of parentheses, braces, (angle) brackets, in texts === Synopsis match_parens [_filename_] === Description Mismatches of parentheses, braces, (angle) brackets, especially in TeX sources which may be rich in those, may be difficult to trace. This little script helps you by writing your text to standard output, after adding a left margin to your text, which will normally be almost empty, but will clearly show any mismatches. (Just try me on myself to see that the parenthesis starting this sentence will not appear to be matched at the end of the file. If you look at me in the vim editor, then select this paragraph and try the command :!% The exit value of the script is 0 when there are no mismatches, 1 otherwise. Angle brackets are only looked for inside HTML text, where HTML is supposed to start with , =begin rdoc, or <, =end or RDOC === Examples Suppose we have two files, _good_ and _bad_, containing these texts: good: bad: This is a (simple) test This is a (simple test without mismatches containing mismatches then here are some usage examples. First a simple test on these files: $ match_parens good 1 This is a (simple) test 2 without mismatches $ echo $? 0 $ match_parens bad 1 ( This is a (simple test 2 ( containing mismatches $ echo $? 1 Just report if there are mismatches: $ match_parens good >/dev/null && echo fine || echo problems fine $ match_parens bad >/dev/null && echo fine || echo problems problems Report all tex files with mismatches in the current directory: $ for i in *.tex; do match_parens $i >/dev/null || echo $i; done Matches must be in correct order: $ echo -e "This is a ([simple)] test\n" | match_parens 1 ([)] This is a ([simple)] test 2 ([)] === Copyright Copyright (C) 2009 Wybo Dekker (wybo@dekkerdocumenten.nl) This program is free software: you can redistribute it and/or modify it under the terms of the {GNU General Public License}[http://www.gnu.org/licenses/] as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the {GNU General Public License}[http://www.gnu.org/licenses/] for more details. $Id: match_parens,v 1.10 2012/02/20 13:28:52 wybo Exp $ =end private s, n, html, notparens = '', '0', false, '^{}[]()' RELEASE = 1.4 arg = ARGV[0] || '' unless arg.empty? test(?e,arg) or raise("file #{arg} does not exist") test(?r,arg) or raise("file #{arg} is not readable") end while x = gets() if html && (x=~/^(RDOC|[# ]*=end)/ || x=~/<\/html>/i) html = false notparens = '^{}[]()' elsif !html && (x=~/^(</i) html = true notparens = '^{}[]()<>' end # remove {x} where x in []{}()<>, copy all parens to s s << x.sub(/^<]\}/,''). tr(notparens,'') # remove matches from inside while s.gsub!(/\{\}|\(\)|\[\]|<>/,'') do end puts ["%7d" % [n.next!],s,x].join("\t") end exit s.empty? ? 0 : 1