qwandry 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +33 -0
- data/Rakefile +33 -0
- data/TODO +7 -0
- data/VERSION +1 -0
- data/bin/qw +87 -0
- data/lib/qwandry.rb +24 -0
- data/lib/qwandry/flat_repository.rb +17 -0
- data/lib/qwandry/launcher.rb +99 -0
- data/lib/qwandry/library_repository.rb +22 -0
- data/lib/qwandry/package.rb +13 -0
- data/lib/qwandry/repository.rb +39 -0
- metadata +78 -0
data/README.markdown
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Qwandry, a questionable tool
|
2
|
+
=============================
|
3
|
+
|
4
|
+
Why spend time trying to remember where libraries, projects, and packages are
|
5
|
+
lurking when your computer can do it faster?
|
6
|
+
|
7
|
+
qw matrix # opens ruby's matrix class in your editor
|
8
|
+
qw rails # will ask you which version of rails you want to open
|
9
|
+
qw activerec 3.1 # will find the gem activerecord 3.1 and open it
|
10
|
+
|
11
|
+
Installation
|
12
|
+
------------
|
13
|
+
Qwandry is a standard ruby gem, on any system with ruby installed already
|
14
|
+
simply install with:
|
15
|
+
|
16
|
+
gem install qwandry
|
17
|
+
|
18
|
+
Usage
|
19
|
+
-----
|
20
|
+
Just type `qw` and the first few letters of what you're looking for. By
|
21
|
+
default Qwandry is set up for locating and editing ruby libraries.
|
22
|
+
|
23
|
+
qw date # opens ruby's date library
|
24
|
+
|
25
|
+
Want to use Qwandry with Python, Perl, or other languages?
|
26
|
+
|
27
|
+
qw --customize
|
28
|
+
|
29
|
+
Contact
|
30
|
+
-------
|
31
|
+
Adam Sanderson, netghost@gmail.com
|
32
|
+
|
33
|
+
Issues and Source: https://github.com/adamsanderson/qwandry
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "qwandry"
|
9
|
+
s.summary = "Qwandry lets you quickly edit ruby gems and libraries"
|
10
|
+
s.description = <<-DESC
|
11
|
+
Open a gem or library's source directory with your default editor.
|
12
|
+
DESC
|
13
|
+
s.email = "netghost@gmail.com"
|
14
|
+
s.homepage = "http://github.com/adamsanderson/qwandry"
|
15
|
+
s.authors = ["Adam Sanderson"]
|
16
|
+
s.has_rdoc = false
|
17
|
+
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
18
|
+
|
19
|
+
# Testing
|
20
|
+
s.test_files = FileList["test/**/*_test.rb"]
|
21
|
+
end
|
22
|
+
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler not available. Install it for jeweler-related tasks with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
25
|
+
end
|
26
|
+
|
27
|
+
Rake::TestTask.new do |t|
|
28
|
+
t.libs << 'lib'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
task :default => :test
|
data/TODO
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
TODO, or perhaps not...
|
2
|
+
|
3
|
+
- Differentiate multiple similar matches (show path or repository label)
|
4
|
+
- Allow better customization of repositories
|
5
|
+
- Customize collection phase (see LibraryRepository)
|
6
|
+
- Customize naming phase
|
7
|
+
- Match multiword args, ie: 'activerec 3.' => 'activerec*3.*' => 'activerecord-3.0.3' @done
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/qw
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Add qwandry's library to the load path
|
3
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
4
|
+
# Require it
|
5
|
+
require "qwandry.rb"
|
6
|
+
|
7
|
+
# Create launcher
|
8
|
+
@qwandry = Qwandry::Launcher.new
|
9
|
+
|
10
|
+
opts = OptionParser.new do |opts|
|
11
|
+
opts.banner = "Usage: qwandry [options] name"
|
12
|
+
opts.separator ""
|
13
|
+
|
14
|
+
opts.on("-r", "--repo LABELS", Array, "Search in LABELS, default: #{@qwandry.active.to_a.join(',')}","Available Repositories:", *@qwandry.repositories.keys.map{|k| " #{k}"}) do |labels|
|
15
|
+
@qwandry.active.replace(labels)
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.separator ""
|
19
|
+
opts.on("-e", "--editor EDITOR", "Use EDITOR to open the package") do |editor|
|
20
|
+
@editor = editor
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.separator "Additional Commands"
|
24
|
+
|
25
|
+
opts.on("--paths", "Prints all repositories and their paths") do
|
26
|
+
@qwandry.repositories.each do |label, entries|
|
27
|
+
puts "#{label} #{"[default]" if @qwandry.active.include? label}"
|
28
|
+
entries.each do |repo|
|
29
|
+
puts "\t#{repo.path} (#{repo.class.to_s.split('::').last})"
|
30
|
+
end
|
31
|
+
puts ""
|
32
|
+
end
|
33
|
+
exit(0)
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("--customize", "Create and edit files for customizing Qwandry") do
|
37
|
+
dir = ENV['HOME'] && ENV['HOME'] + '/.qwandry/'
|
38
|
+
if !dir
|
39
|
+
puts "Home directory must be defined."
|
40
|
+
exit(1)
|
41
|
+
else
|
42
|
+
FileUtils.mkdir(dir, :verbose=>true) unless File.exist?(dir)
|
43
|
+
Dir[File.dirname(__FILE__) + '/../templates/*'].each do |path|
|
44
|
+
FileUtils.cp(path, dir, :verbose=>true, :preserve=>true)
|
45
|
+
end
|
46
|
+
@qwandry.launch dir
|
47
|
+
end
|
48
|
+
exit(0)
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
52
|
+
puts opts
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.parse! ARGV
|
58
|
+
if ARGV.length == 0
|
59
|
+
puts opts
|
60
|
+
exit(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Configure default values
|
64
|
+
@qwandry.editor = @editor if @editor
|
65
|
+
|
66
|
+
name = ARGV.join(' ')
|
67
|
+
packages = @qwandry.find(*ARGV)
|
68
|
+
ARGV.clear # for the gets below
|
69
|
+
|
70
|
+
package = nil
|
71
|
+
case packages.length
|
72
|
+
when 0
|
73
|
+
puts "No packages matched '#{name}'"
|
74
|
+
exit 404 # Package not found -- hehe, super lame.
|
75
|
+
when 1
|
76
|
+
package = packages.first
|
77
|
+
else
|
78
|
+
packages.each_with_index do |package, index|
|
79
|
+
puts "%3d. %s" % [index+1, package.name]
|
80
|
+
end
|
81
|
+
|
82
|
+
print ">> "
|
83
|
+
index = gets.to_i - 1
|
84
|
+
package = packages[index]
|
85
|
+
end
|
86
|
+
|
87
|
+
@qwandry.launch(package) if package
|
data/lib/qwandry.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'set'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
# Informal Spec:
|
7
|
+
#
|
8
|
+
# A User may have multiple Repositories
|
9
|
+
# A Repositories contains Packages
|
10
|
+
#
|
11
|
+
# A User will search for a repository giving a name and optional version
|
12
|
+
# Each Repository will be scanned for matching Packages
|
13
|
+
# If only one Package matches, that Package will be opened
|
14
|
+
# If more than one Package matches, then the user will be prompted to pick one
|
15
|
+
# While any two Packages share the same name their parent dir is appended
|
16
|
+
# If no Repository matches, then qwandry will exit with a 404 (repo not found)
|
17
|
+
#
|
18
|
+
module Qwandry
|
19
|
+
autoload :Launcher, "qwandry/launcher"
|
20
|
+
autoload :Repository, "qwandry/repository"
|
21
|
+
autoload :FlatRepository, "qwandry/flat_repository"
|
22
|
+
autoload :LibraryRepository, "qwandry/library_repository"
|
23
|
+
autoload :Package, "qwandry/package"
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Qwandry
|
2
|
+
# Directories look like:
|
3
|
+
# ./lib-0.1
|
4
|
+
# ./lib-0.2
|
5
|
+
class FlatRepository < Qwandry::Repository
|
6
|
+
def scan(pattern)
|
7
|
+
results = []
|
8
|
+
all_paths.select do |path|
|
9
|
+
if File.fnmatch?(pattern, File.basename(path))
|
10
|
+
results << package(File.basename(path), [path])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
results
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Launcher is the core Qwandry class, it coordinates finding and launching
|
2
|
+
# a package. It is driven externaly by a UI, for instance the `bin/qw`.
|
3
|
+
module Qwandry
|
4
|
+
class Launcher
|
5
|
+
# The default editor to be used by Qwandry#launch.
|
6
|
+
attr_accessor :editor
|
7
|
+
|
8
|
+
# The set of active repositories
|
9
|
+
attr_reader :active
|
10
|
+
|
11
|
+
# Returns the repositories the Launcher will use.
|
12
|
+
attr_reader :repositories
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@repositories = Hash.new{|h,k| h[k] = []}
|
16
|
+
@active = Set.new
|
17
|
+
configure_repositories!
|
18
|
+
custom_configuration!
|
19
|
+
end
|
20
|
+
|
21
|
+
# Adds a repository path to Qwandry's Launcher. `label` is used to label packages residing in the folder `path`.
|
22
|
+
#
|
23
|
+
# The `options` can be used to customize the repository.
|
24
|
+
#
|
25
|
+
# [:class] Repository class, defaults to Qwandry::FlatRepository
|
26
|
+
# [:accept] Filters paths, only keeping ones matching the accept option
|
27
|
+
# [:reject] Filters paths, rejecting any paths matching the reject option
|
28
|
+
#
|
29
|
+
# `:accept` and `:reject` take patterns such as '*.py[oc]', procs, and regular expressions.
|
30
|
+
def add(label, path, options={})
|
31
|
+
if path.is_a?(Array)
|
32
|
+
path.each{|p| add label, p, options}
|
33
|
+
else
|
34
|
+
repository_class = options[:class] || Qwandry::FlatRepository
|
35
|
+
label = label.to_s
|
36
|
+
@repositories[label] << repository_class.new(label, File.expand_path(path), options)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def activate(*labels)
|
41
|
+
labels.each{|label| @active.add label.to_s}
|
42
|
+
end
|
43
|
+
|
44
|
+
def deactivate(*labels)
|
45
|
+
labels.each{|label| @active.delete label.to_s}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Searches all of the loaded repositories for `name`
|
49
|
+
def find(*pattern)
|
50
|
+
pattern = pattern.join('*')
|
51
|
+
pattern << '*' unless pattern =~ /\*$/
|
52
|
+
|
53
|
+
packages = []
|
54
|
+
@repositories.select{|label,_| @active.include? label }.each do |label, repos|
|
55
|
+
repos.each do |repo|
|
56
|
+
packages.concat(repo.scan(pattern))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
packages
|
60
|
+
end
|
61
|
+
|
62
|
+
# Launches a Package or path represented by a String. Unless `editor` will
|
63
|
+
# check against the environment by default.
|
64
|
+
def launch(package, editor=nil)
|
65
|
+
editor ||= @editor || ENV['VISUAL'] || ENV['EDITOR']
|
66
|
+
paths = package.is_a?(String) ? [package] : package.paths
|
67
|
+
system editor, *paths
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def configure_repositories!
|
72
|
+
# Get all the paths on ruby's load path:
|
73
|
+
paths = $:
|
74
|
+
|
75
|
+
# Reject binary paths, we only want ruby sources:
|
76
|
+
paths = paths.reject{|path| path =~ /#{RUBY_PLATFORM}$/}
|
77
|
+
|
78
|
+
# Add ruby standard libraries:
|
79
|
+
paths.grep(/lib\/ruby/).each do |path|
|
80
|
+
add :ruby, path, :class=>Qwandry::LibraryRepository
|
81
|
+
end
|
82
|
+
|
83
|
+
# Add gem repositories:
|
84
|
+
($:).grep(/gems/).map{|p| p[/.+\/gems\//]}.uniq.each do |path|
|
85
|
+
add :gem, path
|
86
|
+
end
|
87
|
+
|
88
|
+
activate :ruby, :gem
|
89
|
+
end
|
90
|
+
|
91
|
+
def custom_configuration!
|
92
|
+
custom_path = ENV['HOME'] && ENV['HOME'] + '/.qwandry/init.rb'
|
93
|
+
if File.exist? custom_path
|
94
|
+
eval IO.read(custom_path)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Qwandry
|
2
|
+
# Directories look like:
|
3
|
+
# lib1.rb
|
4
|
+
# lib1/...
|
5
|
+
# lib2.py
|
6
|
+
# lib2/...
|
7
|
+
class LibraryRepository < Qwandry::Repository
|
8
|
+
def scan(pattern)
|
9
|
+
results = Hash.new{|h,k| h[k] = package(k)}
|
10
|
+
all_paths.select do |path|
|
11
|
+
basename = File.basename(path)
|
12
|
+
if File.fnmatch?(pattern, basename)
|
13
|
+
# strip any file extension
|
14
|
+
basename.sub! /\.\w+$/,'' unless File.directory?(path)
|
15
|
+
results[basename].paths << path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
results.values.sort_by{|package| package.name}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Qwandry
|
2
|
+
class Repository
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :path
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(name, path, options={})
|
8
|
+
@name = name
|
9
|
+
@path = path.chomp('/')
|
10
|
+
@options = options
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def scan(name)
|
15
|
+
[]
|
16
|
+
end
|
17
|
+
|
18
|
+
def all_paths
|
19
|
+
paths = Dir["#{@path}/*"]
|
20
|
+
paths = paths.select(&matcher(options[:accept])) if options[:accept]
|
21
|
+
paths = paths.reject(&matcher(options[:reject])) if options[:reject]
|
22
|
+
paths
|
23
|
+
end
|
24
|
+
|
25
|
+
def package(name, paths=[])
|
26
|
+
Package.new(name, paths, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def matcher(pattern)
|
31
|
+
case pattern
|
32
|
+
when Regexp then lambda{|p| p =~ pattern}
|
33
|
+
when String then lambda{|p| File.fnmatch?(pattern, p)}
|
34
|
+
when Proc then pattern
|
35
|
+
else raise ArgumentError, "Expected a Regexp, String, or Proc"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qwandry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Adam Sanderson
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-07 00:00:00 -08:00
|
19
|
+
default_executable: qw
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: " Open a gem or library's source directory with your default editor.\n"
|
23
|
+
email: netghost@gmail.com
|
24
|
+
executables:
|
25
|
+
- qw
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.markdown
|
30
|
+
- TODO
|
31
|
+
files:
|
32
|
+
- README.markdown
|
33
|
+
- Rakefile
|
34
|
+
- TODO
|
35
|
+
- VERSION
|
36
|
+
- bin/qw
|
37
|
+
- lib/qwandry.rb
|
38
|
+
- lib/qwandry/flat_repository.rb
|
39
|
+
- lib/qwandry/launcher.rb
|
40
|
+
- lib/qwandry/library_repository.rb
|
41
|
+
- lib/qwandry/package.rb
|
42
|
+
- lib/qwandry/repository.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/adamsanderson/qwandry
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options:
|
49
|
+
- --charset=UTF-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
hash: 3
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.7
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Qwandry lets you quickly edit ruby gems and libraries
|
77
|
+
test_files: []
|
78
|
+
|