]> git.notmuchmail.org Git - sup/blobdiff - lib/sup/buffer.rb
various minor bugfixes
[sup] / lib / sup / buffer.rb
index 2b94d79813b299f02eb0cdbcb7621ceff2d246ba..80eb18e3a22191256c5531f58cbe90cd6cce6abb 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
@@ -50,6 +50,7 @@ module Redwood
 class Buffer
   attr_reader :mode, :x, :y, :width, :height, :title
   bool_reader :dirty
+  bool_accessor :force_to_top
 
   def initialize window, mode, width, height, opts={}
     @w = window
@@ -57,6 +58,7 @@ class Buffer
     @dirty = true
     @focus = false
     @title = opts[:title] || ""
+    @force_to_top = opts[:force_to_top] || false
     @x, @y, @width, @height = 0, 0, width, height
   end
 
@@ -139,7 +141,7 @@ class BufferManager
     @minibuf_mutex = Mutex.new
     @textfields = {}
     @flash = nil
-    @shelled = false
+    @shelled = @asking = false
 
     self.class.i_am_the_instance self
   end
@@ -156,18 +158,33 @@ class BufferManager
 
   def raise_to_front buf
     raise ArgumentError, "buffer not on stack: #{buf.inspect}" unless @buffers.member? buf
+
     @buffers.delete buf
-    @buffers.push buf
-    focus_on buf
+    if @buffers.length > 0 && @buffers.last.force_to_top?
+      @buffers.insert(-2, buf)
+    else
+      @buffers.push buf
+      focus_on buf
+    end
     @dirty = true
   end
 
+  ## we reset force_to_top when rolling buffers. this is so that the
+  ## human can actually still move buffers around, while still
+  ## programmatically being able to pop stuff up in the middle of
+  ## drawing a window without worrying about covering it up.
+  ##
+  ## if we ever start calling roll_buffers programmatically, we will
+  ## have to change this. but it's not clear that we will ever actually
+  ## do that.
   def roll_buffers
+    @buffers.last.force_to_top = false
     raise_to_front @buffers.first
   end
 
   def roll_buffers_backwards
     return unless @buffers.length > 1
+    @buffers.last.force_to_top = false
     raise_to_front @buffers[@buffers.length - 2]
   end
 
@@ -179,6 +196,7 @@ class BufferManager
   def [] n; @name_map[n]; end
   def []= n, b
     raise ArgumentError, "duplicate buffer name" if b && @name_map.member?(n)
+    raise ArgumentError, "title must be a string" unless n.is_a? String
     @name_map[n] = b
   end
 
@@ -241,6 +259,7 @@ class BufferManager
   end
 
   def spawn title, mode, opts={}
+    raise ArgumentError, "title must be a string" unless title.is_a? String
     realtitle = title
     num = 2
     while @name_map.member? realtitle
@@ -258,19 +277,34 @@ class BufferManager
     ## w = Ncurses::WINDOW.new(height, width, (opts[:top] || 0),
     ## (opts[:left] || 0))
     w = Ncurses.stdscr
-    b = Buffer.new w, mode, width, height, :title => realtitle
+    b = Buffer.new w, mode, width, height, :title => realtitle, :force_to_top => (opts[:force_to_top] || false)
     mode.buffer = b
     @name_map[realtitle] = b
+
+    @buffers.unshift b
     if opts[:hidden]
-      @buffers.unshift b
       focus_on b unless @focus_buf
     else
-      @buffers.push b
       raise_to_front b
     end
     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
@@ -359,9 +393,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
@@ -399,6 +433,7 @@ class BufferManager
 
   def say s, id=nil
     new_id = nil
+
     @minibuf_mutex.synchronize do
       new_id = id.nil?
       id ||= @minibuf_stack.length