]> git.cworth.org Git - sup/blobdiff - lib/sup/buffer.rb
ask when quitting with unsaved buffers
[sup] / lib / sup / buffer.rb
index 891303e41053dd65a053d36f8a605ae8b8f28679..4785a14e5069ee0bf7610349541534f3d1ce4de3 100644 (file)
@@ -14,7 +14,7 @@ module Ncurses
   end
 
   def mutex; @mutex ||= Mutex.new; end
-  def sync &b; mutex.synchronize &b; end
+  def sync &b; mutex.synchronize(&b); end
 
   ## aaahhh, user input. who would have though that such a simple
   ## idea would be SO FUCKING COMPLICATED?! because apparently
@@ -139,7 +139,7 @@ class BufferManager
     @minibuf_mutex = Mutex.new
     @textfields = {}
     @flash = nil
-    @shelled = false
+    @shelled = @asking = false
 
     self.class.i_am_the_instance self
   end
@@ -217,7 +217,6 @@ class BufferManager
     if true
       buf = @buffers.last
       buf.resize Ncurses.rows - minibuf_lines, Ncurses.cols
-      File.open("asdf.txt", "a") { |f| f.puts "dirty #@dirty, (re)drawing #{buf.mode.name}" }
       @dirty ? buf.draw : buf.redraw
     end
 
@@ -233,7 +232,6 @@ class BufferManager
   ## the mode is expensive, as it often is.
   def spawn_unless_exists title, opts={}
     if @name_map.member? title
-      Redwood::log "buffer '#{title}' already exists, raising to front"
       raise_to_front @name_map[title] unless opts[:hidden]
     else
       mode = yield
@@ -273,6 +271,21 @@ class BufferManager
     b
   end
 
+  def kill_all_buffers_safely
+    until @buffers.empty?
+      ## inbox mode always claims it's unkillable. we'll ignore it.
+      return false unless @buffers.first.mode.is_a?(InboxMode) || @buffers.first.mode.killable?
+      kill_buffer @buffers.first
+    end
+    true
+  end
+
+  def kill_buffer_safely buf
+    return false unless buf.mode.killable?
+    kill_buffer buf
+    true
+  end
+
   def kill_all_buffers
     kill_buffer @buffers.first until @buffers.empty?
   end
@@ -292,7 +305,10 @@ class BufferManager
     end
   end
 
+  ## not really thread safe.
   def ask domain, question, default=nil
+    raise "impossible!" if @asking
+
     @textfields[domain] ||= TextField.new Ncurses.stdscr, Ncurses.rows - 1, 0, Ncurses.cols
     tf = @textfields[domain]
 
@@ -310,7 +326,10 @@ class BufferManager
     ret = nil
     tf.position_cursor
     Ncurses.sync { Ncurses.refresh }
+
+    @asking = true
     while tf.handle_input(Ncurses.nonblocking_getch); end
+    @asking = false
 
     ret = tf.value
     Ncurses.sync { tf.deactivate }
@@ -355,9 +374,9 @@ class BufferManager
     ret
   end
 
+  ## returns true (y), false (n), or nil (ctrl-g / cancel)
   def ask_yes_or_no question
-    r = ask_getch(question, "ynYN")
-    case r
+    case(r = ask_getch question, "ynYN")
     when ?y, ?Y
       true
     when nil
@@ -369,7 +388,9 @@ class BufferManager
 
   def minibuf_lines
     @minibuf_mutex.synchronize do
-      [(@flash ? 1 : 0) + @minibuf_stack.compact.size, 1].max
+      [(@flash ? 1 : 0) + 
+       (@asking ? 1 : 0) +
+       @minibuf_stack.compact.size, 1].max
     end
   end
   
@@ -383,8 +404,9 @@ class BufferManager
 
     Ncurses.mutex.lock unless opts[:sync] == false
     Ncurses.attrset Colormap.color_for(:none)
+    adj = @asking ? 2 : 1
     m.each_with_index do |s, i|
-      Ncurses.mvaddstr Ncurses.rows - i - 1, 0, s + (" " * [Ncurses.cols - s.length, 0].max)
+      Ncurses.mvaddstr Ncurses.rows - i - adj, 0, s + (" " * [Ncurses.cols - s.length, 0].max)
     end
     Ncurses.refresh if opts[:refresh]
     Ncurses.mutex.unlock unless opts[:sync] == false
@@ -392,6 +414,7 @@ class BufferManager
 
   def say s, id=nil
     new_id = nil
+
     @minibuf_mutex.synchronize do
       new_id = id.nil?
       id ||= @minibuf_stack.length
@@ -406,7 +429,7 @@ class BufferManager
 
     if block_given?
       begin
-        yield
+        yield id
       ensure
         clear id
       end