[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] dtas-sinkedit: catch up to inotify/pipe changes in sourceedit
From: |
Eric Wong |
Subject: |
[PATCH] dtas-sinkedit: catch up to inotify/pipe changes in sourceedit |
Date: |
Sun, 12 Apr 2015 09:56:53 +0000 |
This is mainly for consistency in behavior with dtas-sourceedit.
Using dtas-sourcedit is still more common and recommended as it
is less likely to introduce audible gaps and pauses.
---
bin/dtas-sinkedit | 100 +++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 80 insertions(+), 20 deletions(-)
diff --git a/bin/dtas-sinkedit b/bin/dtas-sinkedit
index 3cf3a56..3a4bda8 100755
--- a/bin/dtas-sinkedit
+++ b/bin/dtas-sinkedit
@@ -1,42 +1,102 @@
#!/usr/bin/env ruby
# Copyright (C) 2013-2015 all contributors <address@hidden>
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require 'optparse'
require 'dtas/edit_client'
+require 'dtas/sigevent'
+require 'dtas/watchable'
include DTAS::EditClient
c = client_socket
sinks = c.req('sink ls') || "(unknown)"
-usage = "Usage: #{DTAS_PROGNAME} SINKNAME\n" \
+usage = "Usage: #{DTAS_PROGNAME} [OPTIONS] SINKNAME\n" \
"available SINKNAME values: #{sinks}"
+dry_run = verbose = false
+watch = defined?(DTAS::Watchable)
+
+OptionParser.new('', 24, ' ') do |op|
+ op.banner = usage
+ watch and
+ op.on('-N', '--no-watch', 'disable inotify support') { watch = false }
+
+ op.on('-n', '--dry-run', 'only print commands, do not run them') {
+ dry_run = true
+ }
+ op.on('-V', '--verbose', 'print out commands sent to change the sink') {
+ verbose = true
+ }
+ op.on('-h', '--help') { puts(op.to_s); exit }
+ op.parse!(ARGV)
+end
+
ARGV.size == 1 or abort usage
name = ARGV[0]
-tmp = tmpyaml
+st_in = $stdin.stat
+
buf = c.req(%W(sink cat #{name}))
abort(buf) if buf =~ /\AERR/
orig = YAML.load(buf)
-tmp.write(buf << DTAS_DISCLAIMER)
-cmd = "#{editor} #{tmp.path}"
-system(cmd) or abort "#{cmd} failed: #$?"
-sink = YAML.load(File.read(tmp.path))
+commit_update = lambda do |buf|
+ sink = YAML.load(buf)
+ cmd = %W(sink ed #{name})
+ update_cmd_env(cmd, orig, sink)
-cmd = %W(sink ed #{name})
-update_cmd_env(cmd, orig, sink)
+ # both of these default to false
+ %w(nonblock active).each do |field|
+ cmd << "#{field}=#{sink[field] ? 'true' : 'false'}"
+ end
-# both of these default to false
-%w(nonblock active).each do |field|
- cmd << "#{field}=#{sink[field] ? 'true' : 'false'}"
-end
+ %w(prio).each do |field|
+ value = sink[field] and cmd << "#{field}=#{value}"
+ end
-%w(prio).each do |field|
- value = sink[field] and cmd << "#{field}=#{value}"
-end
+ %w(pipe_size).each { |field| cmd << "#{field}=#{sink[field]}" }
-%w(pipe_size).each { |field| cmd << "#{field}=#{sink[field]}" }
+ # nil OK
+ %w(command).each do |field|
+ cmd << "#{field}=#{sink[field]}"
+ end
-# nil OK
-%w(command).each do |field|
- cmd << "#{field}=#{sink[field]}"
+ warn(Shellwords.join(cmd)) if verbose || dry_run
+ c.req_ok(cmd) unless dry_run
+ orig = sink
end
-c.req_ok(cmd)
+if st_in.file? || st_in.pipe?
+ buf = $stdin.read
+ commit_update.call(buf)
+else
+ include DTAS::SpawnFix
+ tmp = tmpyaml
+ tmp_path = tmp.path
+ do_update = lambda { commit_update.call(File.read(tmp_path)) }
+ tmp.write(buf << DTAS_DISCLAIMER)
+ cmd = "#{editor} #{tmp_path}"
+
+ sev = DTAS::Sigevent.new
+ rset = [ sev ]
+ if watch
+ ino = DTAS::Watchable::InotifyReadableIter.new
+ ino.watch_file(tmp_path, do_update)
+ rset << ino
+ end
+
+ trap(:CHLD) { sev.signal }
+ pid = spawn(cmd)
+ begin
+ r = IO.select(rset) or next
+ r[0].each do |io|
+ case io
+ when sev
+ _, status = Process.waitpid2(pid, Process::WNOHANG)
+ status or next
+ status.success? or abort "#{cmd} failed: #{status.inspect}"
+ do_update.call
+ exit
+ when ino
+ ino.readable_iter # calls do_update
+ end
+ end
+ end while true
+end
--
EW
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] dtas-sinkedit: catch up to inotify/pipe changes in sourceedit,
Eric Wong <=