From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by 10.204.141.209 with SMTP id n17cs8880bku; Sat, 26 Jun 2010 09:40:54 -0700 (PDT) Received: by 10.231.121.15 with SMTP id f15mr2530903ibr.171.1277570453262; Sat, 26 Jun 2010 09:40:53 -0700 (PDT) Return-Path: Received: from rubyforge.org (rubyforge.org [205.234.109.19]) by mx.google.com with ESMTP id cn4si163020ibb.42.2010.06.26.09.40.52; Sat, 26 Jun 2010 09:40:53 -0700 (PDT) Received-SPF: pass (google.com: domain of sup-talk-bounces@rubyforge.org designates 205.234.109.19 as permitted sender) client-ip=205.234.109.19; Authentication-Results: mx.google.com; spf=pass (google.com: domain of sup-talk-bounces@rubyforge.org designates 205.234.109.19 as permitted sender) smtp.mail=sup-talk-bounces@rubyforge.org; dkim=neutral (body hash did not verify) header.i=@gmail.com Received: from rubyforge.org (rubyforge.org [127.0.0.1]) by rubyforge.org (Postfix) with ESMTP id 5E42F1858375; Sat, 26 Jun 2010 12:40:52 -0400 (EDT) Received: from mail-gx0-f178.google.com (mail-gx0-f178.google.com [209.85.161.178]) by rubyforge.org (Postfix) with ESMTP id C7F75185835E for ; Sat, 26 Jun 2010 12:30:53 -0400 (EDT) Received: by gxk27 with SMTP id 27so1677946gxk.23 for ; Sat, 26 Jun 2010 09:30:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:sender:received:from:to:cc :subject:date:message-id:x-mailer; bh=/YA9sfJ8hzQZ7ExomCMwi4lqTGxN/LiTjZvaKh7J1ys=; b=ukXB7/B8spb1SnQbdLqnmLo04Hg6+l+lIGJ6NQqUW+MXNXNAjwP5P18qxWZR3fSD4J EjNnIa3/+FKgVXABARoXmSnDmrDqpL3lrX5JWQYYsJy9LsmtjbCthxEQLCnomTxx5luZ jOWtCJ0GX+eN6aZCos1Cbb4+dxJ+My/I1jAHE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:from:to:cc:subject:date:message-id:x-mailer; b=mq1nexjsQVSvNxpGQ6NooZkWF9BziUoFdd3R772I0RYszP8bJcL6xmNUJuO2Hhtl56 IuA3Sgn9D7MjPacH42gUWEoTO3LbWeYQmdQLZ50AsMY8xWGQBNZVgTxx/rtEnuyXq9e2 BcNyRoacusxrK/E/oY5sxIfm/Lc+t1pqw/lnY= Received: by 10.100.26.12 with SMTP id 12mr3056658anz.177.1277569853187; Sat, 26 Jun 2010 09:30:53 -0700 (PDT) Received: from cabinet.magus.is-a-geek.com (99-114-90-58.lightspeed.miamfl.sbcglobal.net [99.114.90.58]) by mx.google.com with ESMTPS id n18sm24227414anl.2.2010.06.26.09.30.51 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 26 Jun 2010 09:30:52 -0700 (PDT) Received: by cabinet.magus.is-a-geek.com (Postfix, from userid 1000) id 579A930C1C8; Sat, 26 Jun 2010 12:30:50 -0400 (EDT) From: Marc Hartstein To: sup-talk@rubyforge.org Date: Sat, 26 Jun 2010 12:30:07 -0400 Message-Id: <1277569807-12085-1-git-send-email-marc.hartstein@alum.vassar.edu> X-Mailer: git-send-email 1.6.4.4 Subject: [sup-talk] [PATCH] mutt-style pipe to interactive process support X-BeenThere: sup-talk@rubyforge.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: User & developer discussion of Sup List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: sup-talk-bounces@rubyforge.org Errors-To: sup-talk-bounces@rubyforge.org Adds a new method maybe_interactive_pipe_message to ThreadViewMode which will pipe a message to a process in the same manner as the mutt mutt_pipe_message command, allowing interactive tools such as 'urlview' to reopen the tty for IO. Terminating your pipe command with the pipe character ('|') for "pipe back to sup" will use the original behavior, capturing the output of the pipeline for display in a sup buffer. Calling maybe_interactive_pipe_message with maybe_interactive=false, or calling pipe_message will always use the old behavior. No keymap is provided in this patch. It is recommended to replace pipe_message on '|' in keybindings.rb using a line like: Redwood::ThreadViewMode::keymap.add! :maybe_interactive_pipe_message, "Pipe message or attachment to an interactive shell command", '|' --- lib/sup/mode.rb | 32 ++++++++++++++++++++++++ lib/sup/modes/thread-view-mode.rb | 48 +++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/lib/sup/mode.rb b/lib/sup/mode.rb index f5aee1c..8d6197d 100644 --- a/lib/sup/mode.rb +++ b/lib/sup/mode.rb @@ -101,6 +101,38 @@ EOS end end + def pipe_to_interactive_process command + read, write = IO.pipe + + child_pid = fork + if child_pid + # main process + begin + read.close + yield write + rescue + warn "error writing to #{command}: #{$!}" + BufferManager.flash "error writing to #{command}: #{$!}" + ensure + write.close + Process.waitpid(child_pid) + end + else + # child + begin + write.close + $stdin.reopen(read) + exec(command) + rescue + # Can't access logger from child process, but can flash an error + BufferManager.flash "error running #{command}: #{$!}" + ensure + read.close + Kernel.exit!(127) + end + end + end + def pipe_to_process command Open3.popen3(command) do |input, output, error| err, data, * = IO.select [error], [input], nil diff --git a/lib/sup/modes/thread-view-mode.rb b/lib/sup/modes/thread-view-mode.rb index 088529b..bd7908c 100644 --- a/lib/sup/modes/thread-view-mode.rb +++ b/lib/sup/modes/thread-view-mode.rb @@ -661,6 +661,10 @@ EOS private :dispatch def pipe_message + maybe_interactive_pipe_message false + end + + def maybe_interactive_pipe_message maybe_interactive=true chunk = @chunk_lines[curpos] chunk = nil unless chunk.is_a?(Chunk::Attachment) message = @message_lines[curpos] unless chunk @@ -669,20 +673,44 @@ EOS command = BufferManager.ask(:shell, "pipe command: ") return if command.nil? || command.empty? + if maybe_interactive and command[-1,1]=="|" + command = command.chop.strip + return if command.empty? + interactive = false + else + interactive = maybe_interactive + end + + if interactive + pipe_to_interactive_process(command) do |stream| + if chunk + stream.print chunk.raw_content + else + message.each_raw_message_line { |l| + begin + stream.print l + rescue + warn "error writing to #{command}: #{$!}" + BufferManager.flash "error writing to #{command}: #{$!}" + break + end } + end + end + else + output = pipe_to_process(command) do |stream| + if chunk + stream.print chunk.raw_content + else + message.each_raw_message_line { |l| stream.print l } + end + end - output = pipe_to_process(command) do |stream| - if chunk - stream.print chunk.raw_content + if output + BufferManager.spawn "Output of '#{command}'", TextMode.new(output.ascii) else - message.each_raw_message_line { |l| stream.print l } + BufferManager.flash "'#{command}' done!" end end - - if output - BufferManager.spawn "Output of '#{command}'", TextMode.new(output.ascii) - else - BufferManager.flash "'#{command}' done!" - end end private -- 1.6.4.4 _______________________________________________ sup-talk mailing list sup-talk@rubyforge.org http://rubyforge.org/mailman/listinfo/sup-talk