]> git.cworth.org Git - sup/blobdiff - lib/sup/buffer.rb
yet another sig pattern :(
[sup] / lib / sup / buffer.rb
index 47a844a499947eea4b1c44013f395a44b3eb397e..3a696824a444873870c72c723fbb5be8c856e22d 100644 (file)
@@ -1,6 +1,8 @@
 require 'etc'
 require 'thread'
+require 'ncurses'
 
+if defined? Ncurses
 module Ncurses
   def rows
     lame, lamer = [], []
@@ -14,6 +16,12 @@ module Ncurses
     lamer.first
   end
 
+  def curx
+    lame, lamer = [], []
+    stdscr.getyx lame, lamer
+    lamer.first
+  end
+
   def mutex; @mutex ||= Mutex.new; end
   def sync &b; mutex.synchronize(&b); end
 
@@ -27,12 +35,16 @@ module Ncurses
     end
   end
 
-  module_function :rows, :cols, :nonblocking_getch, :mutex, :sync
+  module_function :rows, :cols, :curx, :nonblocking_getch, :mutex, :sync
+
+  remove_const :KEY_ENTER
+  remove_const :KEY_CANCEL
 
   KEY_ENTER = 10
-  KEY_CANCEL = ?\a # ctrl-g
+  KEY_CANCEL = 7 # ctrl-g
   KEY_TAB = 9
 end
+end
 
 module Redwood
 
@@ -328,12 +340,29 @@ class BufferManager
 
   def ask_with_completions domain, question, completions, default=nil
     ask domain, question, default do |s|
-      completions.select { |x| x =~ /^#{s}/i }.map { |x| [x, x] }
+      completions.select { |x| x =~ /^#{s}/i }.map { |x| [x.downcase, x] }
+    end
+  end
+
+  def ask_many_with_completions domain, question, completions, default=nil, sep=" "
+    ask domain, question, default do |partial|
+      prefix, target = 
+        case partial#.gsub(/#{sep}+/, sep)
+        when /^\s*$/
+          ["", ""]
+        when /^(.+#{sep})$/
+          [$1, ""]
+        when /^(.*#{sep})?(.+?)$/
+          [$1 || "", $2]
+        else
+          raise "william screwed up completion: #{partial.inspect}"
+        end
+
+      completions.select { |x| x =~ /^#{target}/i }.map { |x| [prefix + x, x] }
     end
   end
 
-  ## returns an ARRAY of filenames!
-  def ask_for_filenames domain, question, default=nil
+  def ask_for_filename domain, question, default=nil
     answer = ask domain, question, default do |s|
       if s =~ /(~([^\s\/]*))/ # twiddle directory expansion
         full = $1
@@ -361,13 +390,53 @@ class BufferManager
         elsif File.directory?(answer)
           spawn_modal "file browser", FileBrowserMode.new(answer)
         else
-          [answer]
+          answer
         end
     end
 
-    answer || []
+    answer
+  end
+
+  ## returns an array of labels
+  def ask_for_labels domain, question, default_labels, forbidden_labels=[]
+    default_labels = default_labels - forbidden_labels - LabelManager::RESERVED_LABELS
+    default = default_labels.join(" ")
+    default += " " unless default.empty?
+
+    applyable_labels = (LabelManager.applyable_labels - forbidden_labels).map { |l| LabelManager.string_for l }.sort_by { |s| s.downcase }
+
+    answer = ask_many_with_completions domain, question, applyable_labels, default
+
+    return unless answer
+
+    user_labels = answer.split(/\s+/).map { |l| l.intern }
+    user_labels.each do |l|
+      if forbidden_labels.include?(l) || LabelManager::RESERVED_LABELS.include?(l)
+        BufferManager.flash "'#{l}' is a reserved label!"
+        return
+      end
+    end
+    user_labels
+  end
+
+  def ask_for_contacts domain, question, default_contacts=[]
+    default = default_contacts.map { |s| s.to_s }.join(" ")
+    default += " " unless default.empty?
+    
+    recent = Index.load_contacts(AccountManager.user_emails, :num => 10).map { |c| [c.longname, c.email] }
+    contacts = ContactManager.contacts.map { |c| [ContactManager.alias_for(c), c.longname, c.email] }
+
+    Redwood::log "recent: #{recent.inspect}"
+
+    completions = (recent + contacts).flatten.uniq.sort
+    answer = BufferManager.ask_many_with_completions domain, question, completions, default, /\s*,\s*/
+
+    if answer
+      answer.split_on_commas.map { |x| ContactManager.contact_for(x.downcase) || PersonManager.person_for(x) }
+    end
   end
 
+
   def ask domain, question, default=nil, &block
     raise "impossible!" if @asking
     @asking = true
@@ -393,27 +462,22 @@ class BufferManager
 
     while true
       c = Ncurses.nonblocking_getch
-      next unless c  # getch timeout
+      next unless c # getch timeout
       break unless tf.handle_input c # process keystroke
 
       if tf.new_completions?
         kill_buffer completion_buf if completion_buf
         
-        prefix_len =
-          if tf.value =~ /\/$/
-            0
-          else
-            File.basename(tf.value).length
-          end
+        shorts = tf.completions.map { |full, short| short }
+        prefix_len = shorts.shared_prefix.length
 
-        mode = CompletionMode.new tf.completions.map { |full, short| short }, :header => "Possible completions for \"#{tf.value}\": ", :prefix_len => prefix_len
+        mode = CompletionMode.new shorts, :header => "Possible completions for \"#{tf.value}\": ", :prefix_len => prefix_len
         completion_buf = spawn "<completions>", mode, :height => 10
 
         draw_screen :skip_minibuf => true
         tf.position_cursor
       elsif tf.roll_completions?
         completion_buf.mode.roll
-
         draw_screen :skip_minibuf => true
         tf.position_cursor
       end