[kupfer] plugin.locate: Respond quicker with first results



commit a52fb68f0b4c152c07c3dd0713bc5265b56cb991
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sat Oct 24 14:59:16 2009 +0200

    plugin.locate: Respond quicker with first results
    
    Locate does not streamingly output to stdout if it is connected to a
    PIPE, so we launch two locate processes -- one with limit 10 and one
    that goes to the maximum limit.
    
    This way, we can show the first results relatively quickly, instead of
    waiting for locate to return the maximum number of results.

 kupfer/plugin/locate.py |   32 ++++++++++++++++++++++++--------
 1 files changed, 24 insertions(+), 8 deletions(-)
---
diff --git a/kupfer/plugin/locate.py b/kupfer/plugin/locate.py
index 75f9318..1942ee5 100644
--- a/kupfer/plugin/locate.py
+++ b/kupfer/plugin/locate.py
@@ -1,4 +1,5 @@
 import os
+import subprocess
 
 from kupfer.objects import Action, Source, Leaf
 from kupfer.objects import (TextLeaf, ConstructFileLeaf, FileLeaf)
@@ -45,16 +46,31 @@ class LocateQuerySource (Source):
 		self.query = query
 		self.max_items = 500
 
+	def is_dynamic(self):
+		return True
+
 	def get_items(self):
 		ignore_case = '--ignore-case' if __kupfer_settings__["ignore_case"] else ''
-		command = "locate --quiet --null --limit %d %s '%s'" % \
-				(self.max_items, ignore_case, self.query)
-		locate_output = os.popen(command).read()
-		files = locate_output.split("\x00")[:-1]
-		for filestr in files:
-			yield ConstructFileLeaf(filestr)
-		if len(files) == self.max_items:
-			self.output_debug("Found maximum number of files for", self.query)
+		# Start two processes, one to take the first 10 hits, one
+		# to take the remaining up to maximum. We start both at the same time
+		# (regrettably, locate wont output streamingly to stdout)
+		# but we ask the second for results only after iterating the first 10
+		first_num = 10
+		first_command = ("locate --quiet --null --limit %d %s '%s'" %
+				(first_num, ignore_case, self.query))
+		full_command = ("locate --quiet --null --limit %d %s '%s'" %
+				(self.max_items, ignore_case, self.query))
+		p1 = subprocess.Popen(first_command, shell=True, stdout=subprocess.PIPE)
+		p2 = subprocess.Popen(full_command, shell=True, stdout=subprocess.PIPE)
+
+		def get_locate_output(proc, offset=0):
+			out, ignored_err = proc.communicate()
+			return (ConstructFileLeaf(f) for f in out.split("\x00")[offset:-1])
+
+		for F in get_locate_output(p1, 0):
+			yield F
+		for F in get_locate_output(p2, 10):
+			yield F
 
 	def get_gicon(self):
 		return icons.ComposedIcon("gnome-terminal", "gtk-find")



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]