Compare commits

...

19 Commits
master ... 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
3 changed files with 93 additions and 84 deletions

View File

View File

177
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 'rb-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,34 +64,33 @@ 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")
ret = system "rubber --inplace #{mode_opt} #{params} #{infile} 2> #{err_file}"
system "rubber --inplace #{mode_opt} #{params} #{infile} 2> #{err_file}"
File.open(err_file) { |file| puts file.read }
# Remove the output save file if compile was succesful.
#clean(infile) if ret
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').to_s
when :ps
exec "evince", infile.with_extname('ps').to_s
when :pdf, :pspdf
exec "evince", infile.with_extname('pdf').to_s
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')
err_file = infile.with_extname("err")
File.unlink(err_file) if err_file.exist?
system "rubber --clean --inplace #{infile}"
end
@ -97,55 +98,54 @@ end
# Reload the right viewer based on the mode.
def reload(infile, mode)
case mode
when :ps
system "evince", infile.with_extname('ps').to_s
when :pdf, :pspdf
system "evince", infile.with_extname('pdf').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
## Initialisation
Program = File.basename $0
Version = '0.6'
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 ],
[ "--version", "-v", 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 "--version"
puts "#{Program} #{Version}"
exit 0
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
@ -154,49 +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) do
Process.kill(sig, viewer_pid)
clean(infile)
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
end
# If xdvi exits, this program should exit too.
Signal.trap("CLD") do
puts "#{Program}: viewer exited, so will I!"
clean(infile)
exit
end
## Main event loop
# Add input file with dependancies to the watch list and start event loop.
notifier = INotify::Notifier.new
dirs = files.map { |file| File.dirname(file) }
dirs = files.map { |file| Pathname.new(file).dirname }.uniq
dirs.each do |dir|
# Set up a watch per directory
notifier.watch(dir, :close_write) do |ev|
notifier.watch(dir.to_s, :close_write) do |ev|
# Only compile if a dependency of the input file has been modified
next unless files.include?(dir + "/" + ev.name)
puts "I: file #{ev.name} modified, compiling #{infile}..."
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
# 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)