Compare commits

...

30 Commits
v0.4a ... main

Author SHA1 Message Date
Paul van Tilburg 6ee6a68694
Bump the version to 0.9 2023-12-12 15:08:04 +01:00
Paul van Tilburg 5b7130c2f9
Fix infinite loop when the viewer exits
* The viewer now sends `SIGHUP` to the main process when it exists
* The main process signal handler kills the viewer and terminates the
  notifier/main event loop when receiving `SIGINT`/`SIGTERM`/`SIGQUIT`
* The main process signal handler just terminates the notifier/main
  event loop when receiving `SIGHUP`
* Clean just after the notifier/main loop finishes
2023-12-12 15:08:04 +01:00
Paul van Tilburg fb1a0606fd
Fix code style and log message 2023-12-12 15:08:04 +01:00
Paul van Tilburg 174ec96c6d
Remove (commented) code that cleans after compile
This removes code commented out/refactored in commit 2cf1654.
2023-12-12 15:08:00 +01:00
Paul van Tilburg 2c996c7a18
Rename TODO to TODO.md because it is in Markdown format 2022-11-05 15:15:59 +01:00
Paul van Tilburg 0fe0a966f0
Rename COPYING to LICENSE for consistency 2022-11-05 15:15:23 +01:00
Paul van Tilburg 240ea58411
Fix confusing syntax 2022-11-05 15:08:15 +01:00
Paul van Tilburg 84b231d729
Bump the version to 0.8 2021-12-09 17:45:34 +01:00
Paul van Tilburg d78227a8e2
Just use relative paths (so they match up) 2021-12-09 17:45:09 +01:00
Paul van Tilburg c50791cba1
Preserve dirname for .with_extension; drop .base 2021-12-09 17:42:17 +01:00
Paul van Tilburg aa605a4306
Bump the version to 0.7 2020-12-04 22:40:45 +01:00
Paul van Tilburg c5d363406e
Fix infinite loop when exiting viewer
The CLD signal handler cleaned the ini file leading to another CLD
signal, which called the handler again etc.
Replace this by just killing the main process after the viewer exists
in the code for the fork.

Also note that we don't know which child process exited in the CLD
signal handler. This might be the viewer, but also rubber.
2020-12-04 22:37:54 +01:00
Paul van Tilburg bfdff5745b
Fix Rubocop style issues 2020-12-04 22:28:31 +01:00
Paul van Tilburg 15727a2f92 Remove trailing whitespace; fix minor warnings 2019-03-30 20:23:07 +01:00
Paul van Tilburg 11cd5be441 Againt, the directory is a Pathname object now 2018-06-22 23:13:37 +02:00
Paul van Tilburg 3a5609a5a3 Remove the unnecessary empty string argument 2018-06-22 23:13:21 +02:00
Paul van Tilburg 34bd63ca3d The directory is a Pathname object now; set the correct file path 2018-06-22 23:09:14 +02:00
Paul van Tilburg 49991c8924 Get the real path of the files and ensure uniqueness 2018-06-22 22:59:28 +02:00
Admar Schoonen c81a670261 Added printing empty lines after compilation
Adding printing an empty line after a compile iteration has finished
makes it easier to parse the output and look for errors.
2018-06-22 21:16:26 +02:00
Paul van Tilburg 48de8f578f Only compile if a dependency of the input file has been modified 2018-06-22 20:20:30 +02:00
Paul van Tilburg 12cccdde4c Add missing block variable 2018-06-22 20:09:09 +02:00
Paul van Tilburg 712b17c308 Rewrite to use the new rb-inotify API 2018-06-22 20:07:26 +02:00
Paul van Tilburg 96a6d3533c Replace the inotify library by rb-inotify 2015-09-06 10:26:41 +02:00
Paul van Tilburg 93a3eaf51e Fix Ruby 1.9.x compatbility issues 2012-11-25 11:38:21 +01:00
Paul van Tilburg 2cf165424a Only clean on exit, not after compile (DVI will be gone). 2009-08-06 17:17:39 +02:00
Paul van Tilburg 926e4ca4ec Merge branch 'master' of git.luon.net:/git/users/paul/rubberin 2009-07-16 12:02:56 +02:00
Paul van Tilburg 2d4227a362 Clean up cruft on quit. 2009-07-16 12:02:40 +02:00
Paul van Tilburg e0bcda0cf3 Added the --version commandline parameter. 2009-07-06 01:48:53 +02:00
Paul van Tilburg 654a04f401 Add the ToDo list. 2009-03-30 12:50:00 +02:00
Paul van Tilburg 5d621b32e8 Updated to release 0.6:
* Remove the .err-file if the compile was succesful.
* Watch the directories of the files that should be watched
  instead of the files themself.
* Look for CLOSE_WRITE events instead of MODIFY.  This makes
  rubberin compatible with vim/gedit/ispell/svn/git/etc.
2009-03-25 12:51:33 +01:00
3 changed files with 115 additions and 73 deletions

View File

8
TODO.md Normal file
View File

@ -0,0 +1,8 @@
ToDo items for rubberin
=======================
* Add options to track additional files.
* Add some (pre/post-)compile hooks.
* Don't destroy ARGV, just track if it contains --ps/--pdf/--help.
* Add a verbose (-v) and debug (-d) mode.
* Add configurability of default compile modes and used viewers.

180
rubberin
View File

@ -13,29 +13,31 @@
# the result of the LaTeX compilation and forces it to reload every time
# rubberin has recompiled the LaTeX file.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 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 WAR RANTY; without even the implied warranty of
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 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 WAR RANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this p rogram; if not, write to the Free Software Foundation, Inc.,
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
require 'getoptlong'
require 'inotify'
require 'pathname'
require "English"
require "getoptlong"
require "rb-inotify"
require "pathname"
# Small necessary Pathname class extension.
class Pathname
def extname=(ext)
raise "Invalid extension" unless ext.is_a? String and ext.match(/^\./)
raise "Invalid extension" unless ext.is_a?(String) && ext.match(/^\./)
@path.sub!(/#{extname}$/, ext)
end
end
@ -44,7 +46,7 @@ end
# Print the usage.
def usage
puts "Usage: #{Program} [options]... [tex-file] [rubber-options]..."
puts "Usage: #{PROGRAM} [options]... [tex-file] [rubber-options]..."
end
# Print the command line help.
@ -62,11 +64,11 @@ end
# Compile the input file using the right options based on the mode.
def compile(infile, mode)
mode_opt = {:pdf => "--pdf",
:ps => "--ps",
:pspdf => "--ps --pdf"}[mode]
params = ARGV.join(' ')
err_file = infile.with_extname('err')
mode_opt = { pdf: "--pdf",
ps: "--ps",
pspdf: "--ps --pdf" }[mode]
params = ARGV.join(" ")
err_file = infile.with_extname("err")
system "rubber --inplace #{mode_opt} #{params} #{infile} 2> #{err_file}"
File.open(err_file) { |file| puts file.read }
@ -75,64 +77,75 @@ end
# Start the right viewer based on the mode.
def view(infile, mode)
case mode
when :dvi
exec "xdvi.bin", "-watchfile", "1",
"-name", "xdvi", infile.with_extname('dvi')
when :ps
exec "evince", infile.with_extname('ps')
when :pdf, :pspdf
exec "evince", infile.with_extname('pdf')
when :dvi
system "xdvi.bin",
"-watchfile", "1",
"-name", "xdvi", infile.with_extname("dvi").to_s
when :ps
system "evince", infile.with_extname("ps").to_s
when :pdf, :pspdf
system "evince", infile.with_extname("pdf").to_s
end
end
# Clean up cruft related to compilation of the input file.
def clean(infile)
err_file = infile.with_extname("err")
File.unlink(err_file) if err_file.exist?
system "rubber --clean --inplace #{infile}"
end
# Reload the right viewer based on the mode.
def reload(infile, mode)
case mode
when :ps
system "evince", infile.with_extname('ps')
when :pdf, :pspdf
system "evince", infile.with_extname('pdf')
when :ps
system "evince", infile.with_extname("ps").to_s
when :pdf, :pspdf
system "evince", infile.with_extname("pdf").to_s
end
end
## Initialisation
Program = File.basename $0
Version = '0.4a'
PROGRAM = File.basename($PROGRAM_NAME).freeze
VERSION = "0.9".freeze
# Parse the command line options.
# Determine the compile mode from the options.
mode = :dvi
opts = GetoptLong.new(
[ "--help", "-h", GetoptLong::NO_ARGUMENT ],
[ "--ps", "-p", GetoptLong::NO_ARGUMENT ],
[ "--pdf", "-d", GetoptLong::NO_ARGUMENT ])
opts = GetoptLong.new(["--help", "-h", GetoptLong::NO_ARGUMENT],
["--ps", "-p", GetoptLong::NO_ARGUMENT],
["--pdf", "-d", GetoptLong::NO_ARGUMENT],
["--version", "-v", GetoptLong::NO_ARGUMENT])
opts.ordering = GetoptLong::REQUIRE_ORDER
opts.quiet = true
opts.each do |opt, arg|
opts.each do |opt, _arg|
case opt
when "--help"
help
exit 0
when "--ps"
mode = :ps
when "--pdf"
mode = if mode == :ps then :pspdf
else :pdf
end
when "--help"
help
exit 0
when "--ps"
mode = :ps
when "--pdf"
mode = if mode == :ps
:pspdf
else
:pdf
end
when "--version"
puts "#{PROGRAM} #{VERSION}"
exit 0
end
end
# Get the input file from the arguments.
if ARGV.length < 1
if ARGV.empty?
usage
exit 1
else
infile = Pathname.new(ARGV.shift)
def infile.base
self.basename(self.extname)
end
def infile.with_extname(ext)
file = self.base
file = dirname + basename(extname)
file.extname = ".#{ext}"
file
end
@ -141,37 +154,58 @@ end
# Check the input file.
begin
File.open(infile) {}
rescue => err
puts "#{Program}: #{err}"
rescue SystemCallError => e
puts "#{PROGRAM}: #{e}"
exit 2
end
# Find the dependancies of the input file using rubber-info and
# Find the dependencies of the input file using rubber-info and
# do an initial run.
files = `rubber-info --deps #{infile}`.chomp.split
compile(infile, mode)
puts
# Spawn a viewer based on the mode.
viewer_pid = fork
view(infile, mode) if not viewer_pid
# Handle signals.
["INT", "TERM", "QUIT"].each do |sig|
Signal.trap(sig) { Process.kill(sig, viewer_pid); exit }
end
# If xdvi exits, this program should exit too.
Signal.trap("CLD") { puts "#{Program}: viewer exited, so will I!"; exit }
pid = $PROCESS_ID
viewer_pid =
fork do
view(infile, mode)
# If xdvi/evince exits, this program should exit too.
puts "#{PROGRAM}: viewer exited, so will I!"
Process.kill("HUP", pid)
end
## Main event loop
# Add input file with dependancies to the watch list and start event loop.
i = Inotify.new
files.each do |file|
i.add_watch(file, Inotify::MODIFY)
notifier = INotify::Notifier.new
dirs = files.map { |file| Pathname.new(file).dirname }.uniq
dirs.each do |dir|
# Set up a watch per directory
notifier.watch(dir.to_s, :close_write) do |ev|
# Only compile if a dependency of the input file has been modified
file_path = (dir + ev.name).to_s
next unless files.include? file_path
puts "#{PROGRAM}: file #{ev.name} modified, compiling #{infile}..."
compile(infile, mode)
reload(infile, mode)
puts
end
end
# Process the events, recompile and reload when necessary.
i.each_event do |ev|
puts "I: file #{ev.name} modified, compiling #{infile}..."
compile(infile, mode)
reload(infile, mode)
# Handle signals during the main event loop.
["INT", "TERM", "QUIT"].each do |sig|
Signal.trap(sig) do
puts "#{PROGRAM}: caught signal #{sig}, stopping the viewer..."
Process.kill(sig, viewer_pid)
notifier.stop
end
end
Signal.trap("HUP") { notifier.stop }
# Run the main event loop.
notifier.run
# Clean before finishing!
clean(infile)