zeiger 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c01cd920ba6af86d17bd79b07e648d5e1bb37ad2
4
- data.tar.gz: d90ce8ed808e1853aad0175d6fa862d0b3ff2a29
3
+ metadata.gz: 7ca514e457ea27de32736575f07c6aabcd63e097
4
+ data.tar.gz: d01654cdb2af19a41953a1726ddf114fafc3db9e
5
5
  SHA512:
6
- metadata.gz: 5c24d14cba4ac6840aa2ec817c22a608bc98a476289643bdaa6b06fcd50649f82a189f45fdc5c14ef882a7cb815bdcd900c4f387d2d3baa2f4ffeb8edb90b223
7
- data.tar.gz: 491a7131fc1f5b5ba29b207d31d2c5b232ed9307650a17aecd6d9383f101debefd6f7e5366c79a2e8e456e82f3d52b3fa6c799a7282b64b4ff5ab2bd683e9aff
6
+ metadata.gz: 0d61f59cd5a5b1d56dee4555bddc4c3b7573c37ebb6f52aa76a09ce6f80bc7f39b2a04db0d9ac463c6cbc439db8b312ac172ae09d4c5c696853fafeb72690c04
7
+ data.tar.gz: 5fa8f50cbefcff8298cc2896ff4053ab81d4bc360eb5f2c3dcd94196b8d97e844a6075630fa1b34d5b589ccd1290688ad25dc98c3417c61d73c21a9bc037904b
data/.zeiger.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  search:
2
- - bin
3
- - lib
2
+ - "bin/**/*"
3
+ - "lib/**/*"
4
4
  ignore:
5
5
  - .gz$
6
6
  - .png$
data/README.md CHANGED
@@ -1,30 +1,31 @@
1
1
  # Zeiger
2
2
 
3
- Zeiger is the German word for "pointer", "indicator", "index", "locator". This gem is built in the "index" sense : run
3
+ Zeiger is the German word for "pointer", "indicator", "index", "locator". This gem is built in the "index" sense. To install,
4
4
 
5
5
  ```
6
- cd myproject
7
- zeiger server
6
+ gem install zeiger
8
7
  ```
9
8
 
10
- and this gem will create an in-memory index of all text in the filesystem subtree rooted in the current directory.
9
+ In a terminal, run
10
+
11
+ ```
12
+ zeiger server
13
+ ```
11
14
 
12
- Query the index thus:
15
+ Zeiger will open a unix-socket under `/tmp` and listen for search and file-list requests. Run this in a terminal:
13
16
 
14
17
  ```
15
18
  cd myproject
16
19
  zeiger search "muppets"
17
20
  ```
18
21
 
19
- This example returns one line for each line in your projects containing the word "muppets". Output is in the same format as `grep` (so you can hook it up with your emacs for quick project browsing).
22
+ (Replace "myproject" with something meaningful!)
20
23
 
21
- ## Installation
24
+ Zeiger will index the current directory if it is not already indexed, then search for lines containing "muppets". Output is in the same format as `grep` (so you can hook it up with your emacs for quick project browsing).
25
+
26
+ Zeiger will rescan files in the current directory every ten seconds so the index is mostly up-to-date.
22
27
 
23
- ```
24
- gem install 'zeiger'
25
- ```
26
28
 
27
- This is built as a standalone commandline tool ; I don't have any use-cases for integrating it directly into a larger project. But if you do, I'm all ears.
28
29
 
29
30
  ## Usage
30
31
 
@@ -32,11 +33,11 @@ This is built as a standalone commandline tool ; I don't have any use-cases for
32
33
 
33
34
  `zeiger search "foo"` writes the query to the socket and displays the result
34
35
 
35
- `zeiger files "xed"` asks for the list of filenames corresponding to the argument ("xed"). With no argument, return all filenames.
36
+ `zeiger files "xed"` asks for the list of filenames corresponding to the argument ("xed"). With no argument, return all filenames. Files are sorted by length of filename. This sounds odd, but works nicely with 'completing-read in emacs: you will find the file you want in fewer keystrokes.
36
37
 
37
38
  By default, Zeiger searches only in these subdirectories : %w{ app bin config lib spec test }, and excludes filenames matching these patterns: %w{ .gz$ .png$ .jpg$ .pdf$ }.
38
39
 
39
- To override, create a file in your working directory with the following format:
40
+ To override, create a file called `.zeiger.yml` in your project root with the following format:
40
41
 
41
42
  ```yaml
42
43
  search:
@@ -53,6 +54,12 @@ ignore:
53
54
  - .mpg$
54
55
  ```
55
56
 
57
+ You should change the contents to suit your indexing needs. The `search` key is a list of regexps, zeiger will index only those files whose name matches at least one of these regexps. The `ignore` key is likewise a list of regexps, zeiger will not index any file whose name matches any of these regexps. The `ignore` rule supercedes the `search` rule.
58
+
59
+ When you invoke `zeiger search ...` or `zeiger files ...`, zeiger will consider whether an index already exists for the current directory. If not, and the current directory is a project root, it will create an index for the current directory. If there is no index, and the current directory is not a project root, it moves up one directory and tries again.
60
+
61
+ Zeiger considers a project root any directory containing any one of the following: `%w{ .zeiger.yml .git .hg Makefile Rakefile Gemfile build.xml }` (see `ROOT_FILES` constant in `index.rb`)
62
+
56
63
 
57
64
  ## Contributing
58
65
 
data/bin/zeiger CHANGED
@@ -3,14 +3,13 @@
3
3
  require 'socket'
4
4
  require 'zeiger'
5
5
 
6
- SOCKET_NAME = "./zeiger-index"
7
-
6
+ pwd = `pwd`.strip
8
7
  command = $*[0]
9
8
 
10
9
  case command
11
- when "server" ; Zeiger::Server.run *$*
12
- when "search" ; Zeiger::QueryClient.run *$*
13
- when "files" ; Zeiger::FileListClient.run *$*
10
+ when "server" ; Zeiger::Server.new.run *$*
11
+ when "search" ; Zeiger::QueryClient.run pwd, *$*
12
+ when "files" ; Zeiger::FileListClient.run pwd, *$*
14
13
  end
15
14
 
16
15
  # define file groups
@@ -9,7 +9,7 @@ module Zeiger
9
9
  end
10
10
 
11
11
  def local_filename
12
- filename.gsub(/^#{Regexp.escape dir}\//, "")
12
+ @_local_filename ||= filename.gsub(/^#{Regexp.escape dir}\//, "")
13
13
  end
14
14
 
15
15
  def match regex
@@ -1,8 +1,11 @@
1
1
  module Zeiger
2
2
  class FileListClient
3
- def self.run command, q=nil, *args
3
+ def self.run pwd, command, q=nil, *args
4
4
  Socket.unix(SOCKET_NAME) { |sock|
5
- sock.puts("FILES: #{q}")
5
+ s = YAML.dump({ pwd: pwd, files: q })
6
+ sock.write([s.bytesize].pack("I"))
7
+ sock.write(s)
8
+
6
9
  while !sock.eof?
7
10
  puts sock.readline
8
11
  end
data/lib/zeiger/index.rb CHANGED
@@ -1,14 +1,27 @@
1
1
  module Zeiger
2
+ INDICES = { }
3
+
2
4
  class Index
5
+ ROOT_FILES = %w{ .zeiger.yml .git .hg Makefile Rakefile Gemfile build.xml }
3
6
  NGRAM_SIZE = 3
4
7
 
5
- attr_accessor :index, :dir, :includes, :ignore, :files
8
+ attr_accessor :index, :dir, :includes, :ignore, :files, :monitor
6
9
 
7
10
  def initialize dir
8
11
  attrs = File.exist?(".zeiger.yml") ? YAML.load(File.read ".zeiger.yml") : { }
9
12
  self.dir = File.expand_path dir
10
13
  self.index = Hash.new { |h, k| h[k] = [] }
11
14
  self.files = Hash.new
15
+ self.monitor = Monitor.new dir, self
16
+ rescan
17
+ end
18
+
19
+ def self.from_path path
20
+ raise "no path! #{path.inspect}" if path == nil || path.strip == ''
21
+ return INDICES[path] if INDICES[path]
22
+ return nil if path == '/'
23
+ return (INDICES[path] = new(path)) if ROOT_FILES.any? { |f| File.exist?(File.join path, f) }
24
+ return from_path(File.dirname path)
12
25
  end
13
26
 
14
27
  def remove_from_index file
@@ -32,19 +45,24 @@ module Zeiger
32
45
  }
33
46
  end
34
47
 
35
- def exec_query regex, ngrams
36
- ngrams.map { |ngram| index[ngram] }.reduce(&:&).select { |line| line.matches? regex }
37
- end
48
+ def rescan ; monitor.build_index ; end
49
+ def get_ngram_lines ngrams ; ngrams.map { |ngram| result = index[ngram] || [] }.reduce(&:&) ; end
50
+ def exec_query regex, ngrams ; get_ngram_lines(ngrams).select { |line| line.matches? regex } ; end
51
+ def sort_by_filename lines ; lines.sort_by { |line| line.file.local_filename } ; end
38
52
 
39
53
  def query txt
40
54
  puts "got query #{txt.inspect}"
41
- exec_query Regexp.compile(txt), txt.ngrams(NGRAM_SIZE)
55
+ sort_by_filename exec_query Regexp.compile(Regexp.escape txt), txt.ngrams(NGRAM_SIZE)
42
56
  end
43
57
 
44
58
  def file_list name
45
- r = Regexp.compile name
46
- puts "file names matching #{r.inspect}"
47
- files.values.select { |f| f.match r }
59
+ if name
60
+ r = Regexp.compile name
61
+ puts "file names matching #{r.inspect}"
62
+ files.values.select { |f| f.match r }
63
+ else
64
+ files.values
65
+ end.sort_by { |f| f.local_filename.length }
48
66
  end
49
67
  end
50
68
  end
@@ -4,9 +4,19 @@ module Zeiger
4
4
 
5
5
  def initialize dir, index
6
6
  @dir, @index, @stat = dir, index, Hash.new
7
- attrs = File.exist?(".zeiger.yml") ? YAML.load(File.read ".zeiger.yml") : { }
8
- @includes = attrs["includes"] || %w{ app bin config lib spec test }
9
- @ignore = attrs["ignore"] || %w{ .gz$ .png$ .jpg$ .pdf$ }
7
+ attrs = load_config
8
+ @includes = attrs["search"] || %w{ app/**/* bin/**/* config/**/* lib/**/* spec/**/* test/**/* }
9
+ @ignore = attrs["ignore"] || %w{ .gz$ .png$ .jpg$ .pdf$ }
10
+ end
11
+
12
+ def load_config
13
+ conf_file = File.join dir, ".zeiger.yml"
14
+ if File.exist?(conf_file)
15
+ puts "reading config from #{conf_file.inspect}"
16
+ YAML.load(File.read conf_file)
17
+ else
18
+ { }
19
+ end
10
20
  end
11
21
 
12
22
  def ignore? filename
@@ -21,7 +31,7 @@ module Zeiger
21
31
  started = Time.now
22
32
  files = Set.new
23
33
  includes.each do |inc|
24
- Dir.glob(File.join(dir, inc, "**", "*")).sort.each do |file|
34
+ Dir.glob(File.join(dir, inc)).sort.each do |file|
25
35
  if File.file?(file) && !ignore?(file)
26
36
  files << file
27
37
  mtime = File.stat(file).mtime
@@ -1,8 +1,11 @@
1
1
  module Zeiger
2
2
  class QueryClient
3
- def self.run command, q, *args
3
+ def self.run pwd, command, q, *args
4
4
  Socket.unix(SOCKET_NAME) { |sock|
5
- sock.puts("SEARCH: #{q}")
5
+ s = YAML.dump({ pwd: pwd, search: q })
6
+ sock.write([s.bytesize].pack("I"))
7
+ sock.write(s)
8
+
6
9
  while !sock.eof?
7
10
  puts sock.readline
8
11
  end
data/lib/zeiger/server.rb CHANGED
@@ -1,17 +1,18 @@
1
+ require 'yaml'
2
+
1
3
  module Zeiger
2
- class Server
3
- def self.run command, *args
4
- dir = File.expand_path(".")
5
- z = Zeiger::Index.new dir
4
+ SOCKET_NAME = "/tmp/zeiger-index"
6
5
 
6
+ class Server
7
+ def run command, *args
7
8
  Thread.new do
8
9
  begin
9
- puts "monitor thread"
10
- monitor = Zeiger::Monitor.new dir, z
11
- puts "created monitor"
12
10
  while true do
13
- puts "scanning..."
14
- monitor.build_index
11
+ indices = Zeiger::INDICES.values
12
+ indices.each do |index|
13
+ puts "scanning #{index.dir}"
14
+ index.rescan
15
+ end
15
16
  sleep 10
16
17
  end
17
18
  rescue Exception => e
@@ -20,18 +21,23 @@ module Zeiger
20
21
  end
21
22
  end
22
23
 
23
- puts "query thread..."
24
-
25
24
  Socket.unix_server_loop(SOCKET_NAME) { |sock, client|
26
25
  puts "query thread: server loop"
27
26
  begin
28
- incoming = sock.readline.strip.split(/:/, 2).map &:strip
29
- case incoming[0]
30
- when "SEARCH"
31
- z.query(incoming[1]).each { |res| sock.puts res.to_s }
32
- when "FILES"
33
- z.file_list(incoming[1]).each { |f| sock.puts f.local_filename }
27
+ length = sock.read(4).unpack("I")[0]
28
+ query = sock.read(length)
29
+ incoming = YAML.load(query)
30
+ puts incoming.to_yaml
31
+
32
+ index = Index.from_path incoming[:pwd]
33
+ puts "querying index at #{index.dir}"
34
+
35
+ if incoming[:search]
36
+ index.query(incoming[:search]).each { |res| sock.puts res.to_s }
37
+ elsif incoming.key? :files
38
+ index.file_list(incoming[:files]).each { |f| sock.puts f.local_filename }
34
39
  end
40
+
35
41
  ensure
36
42
  sock.close
37
43
  end
@@ -1,3 +1,3 @@
1
1
  module Zeiger
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zeiger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - conanite
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler