bahuvrihi-sample_tasks 0.10.0
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/MIT-LICENSE +21 -0
- data/README +28 -0
- data/lib/tap/support/simple_table.rb +99 -0
- data/lib/tap/tasks/concat.rb +78 -0
- data/lib/tap/tasks/copy.rb +53 -0
- data/lib/tap/tasks/grep.rb +54 -0
- data/lib/tap/tasks/print_tree.rb +78 -0
- data/lib/tap/tasks/table_task.rb +24 -0
- data/tap.yml +0 -0
- metadata +70 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2006-2008, Regents of the University of Colorado.
|
2
|
+
Developer:: Simon Chiang, Biomolecular Structure Program, Hansen Lab
|
3
|
+
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
6
|
+
software and associated documentation files (the "Software"), to deal in the Software
|
7
|
+
without restriction, including without limitation the rights to use, copy, modify, merge,
|
8
|
+
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
9
|
+
to whom the Software is furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in all copies or
|
12
|
+
substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
18
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
19
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
21
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
= Sample Tasks
|
2
|
+
|
3
|
+
A set of generally-useful sample tap[http://tap.rubyforge.org] tasks.
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
Sample tasks is a library of tap[http://tap.rubyforge.org] tasks that are both
|
8
|
+
instructive and generally useful. Currently consists of a few file tasks for
|
9
|
+
concatenation, searching, copying, etc.
|
10
|
+
|
11
|
+
* Website[http://tap.rubyforge.org]
|
12
|
+
* Rubyforge[http://rubyforge.org/projects/tap]
|
13
|
+
* Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/14735-sample-tasks/overview]
|
14
|
+
* Github[http://github.com/bahuvrihi/sample_tasks/tree/master]
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
The sample_tasks gem is available through RubyForge[http://rubyforge.org/projects/tap]. Use:
|
19
|
+
|
20
|
+
% gem install sample_tasks
|
21
|
+
|
22
|
+
== Info
|
23
|
+
|
24
|
+
Copyright (c) 2006-2008, Regents of the University of Colorado.
|
25
|
+
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com], {Biomolecular Structure Program}[http://biomol.uchsc.edu/], {Hansen Lab}[http://hsc-proteomics.uchsc.edu/hansenlab/]
|
26
|
+
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
27
|
+
Licence:: MIT-Style
|
28
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Tap
|
2
|
+
module Support
|
3
|
+
|
4
|
+
# SimpleTable represents a simple table where each row has
|
5
|
+
# the same number of columns. Provides accessors of column
|
6
|
+
# data, and supports headers.
|
7
|
+
#
|
8
|
+
class SimpleTable
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Parses the string into an array of table data, using the
|
12
|
+
# specified row and column delimiters.
|
13
|
+
def parse_data(string, row_delimiter=/\r?\n/, col_delimiter="\t")
|
14
|
+
string.split(row_delimiter).collect do |row|
|
15
|
+
row.split(col_delimiter)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# An array of table data. Each entry (row) is an array of column
|
21
|
+
# data padded to a uniform length (n_columns) using default_value.
|
22
|
+
attr_reader :data
|
23
|
+
|
24
|
+
# The default value for empty cells
|
25
|
+
attr_reader :default_value
|
26
|
+
|
27
|
+
# The number of columns in self
|
28
|
+
attr_reader :n_columns
|
29
|
+
|
30
|
+
# An array of headers, padded to n_columns.
|
31
|
+
attr_reader :headers
|
32
|
+
|
33
|
+
def initialize(data, options={})
|
34
|
+
@data = data
|
35
|
+
@default_value = options[:default_value] || nil
|
36
|
+
@headers = case options[:header_row]
|
37
|
+
when true
|
38
|
+
if @data.length == 0
|
39
|
+
raise "no header row available"
|
40
|
+
end
|
41
|
+
|
42
|
+
@data.shift
|
43
|
+
else []
|
44
|
+
end
|
45
|
+
|
46
|
+
normalize!
|
47
|
+
end
|
48
|
+
|
49
|
+
def normalize!
|
50
|
+
# Determine the number of columns in self.
|
51
|
+
@n_columns = data.inject(0) do |max, column|
|
52
|
+
max > column.length ? max : column.length
|
53
|
+
end
|
54
|
+
|
55
|
+
# Normalize the data rows to the number of columns.
|
56
|
+
@data = data.collect {|row| normalize_row(row) }
|
57
|
+
@headers = normalize_row(@headers)
|
58
|
+
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# The number of rows in self.
|
63
|
+
def n_rows
|
64
|
+
@data.length
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns an array of n_columns length and default_value
|
68
|
+
def blank_row
|
69
|
+
Array.new(n_columns, default_value)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns column data for the specified index.
|
73
|
+
def column(index)
|
74
|
+
data.collect {|row| row[index] }
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns column data for the specified header.
|
78
|
+
def column_by_header(header)
|
79
|
+
index = headers.index(header)
|
80
|
+
raise "could not find header: #{header}" if index == nil
|
81
|
+
|
82
|
+
column(index)
|
83
|
+
end
|
84
|
+
|
85
|
+
def join(row_delimiter="\n", col_delimiter="\t", include_headers=true)
|
86
|
+
(include_headers ? headers.join(col_delimiter) + row_delimiter : "") +
|
87
|
+
data.collect do |row|
|
88
|
+
row.join(col_delimiter)
|
89
|
+
end.join(row_delimiter)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def normalize_row(array)
|
95
|
+
array + Array.new(n_columns - array.length, default_value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::manifest concatenate files with formatting
|
6
|
+
#
|
7
|
+
# Concatenates a list of files into the specified target. Raises an error
|
8
|
+
# for non-existant, non-file inputs. Concat allows a variety configurable
|
9
|
+
# separators to be specified. These strings are formatted using ERB so
|
10
|
+
# that you can concat and insert text at the same time. For instance
|
11
|
+
# with source files:
|
12
|
+
#
|
13
|
+
# [one.txt]
|
14
|
+
# contents of file one
|
15
|
+
#
|
16
|
+
# [two.txt]
|
17
|
+
# contents of file two
|
18
|
+
#
|
19
|
+
# And configurations:
|
20
|
+
#
|
21
|
+
# pre: "# <%= File.basename(source) %>\n"
|
22
|
+
# post: "\n"
|
23
|
+
#
|
24
|
+
# You obtain the following:
|
25
|
+
#
|
26
|
+
# [concat.txt]
|
27
|
+
# # one.txt
|
28
|
+
# contents of file one
|
29
|
+
#
|
30
|
+
# # two.txt
|
31
|
+
# contents of file two
|
32
|
+
#
|
33
|
+
# The ERB binding (and hence each insert configuration) has access to all
|
34
|
+
# task methods and the following variables:
|
35
|
+
# target the target file
|
36
|
+
# source the current source
|
37
|
+
# sources an array of the source files
|
38
|
+
#
|
39
|
+
class Concat < Tap::FileTask
|
40
|
+
config :before, "", &c.string # string before all entries
|
41
|
+
config :pre, "", &c.string # separator before each entry
|
42
|
+
config :post, "", &c.string # separator after each entry
|
43
|
+
config :after, "", &c.string # string after all entries
|
44
|
+
|
45
|
+
# Alias for self. Allows self to be accessed within separator ERB.
|
46
|
+
def task
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def process(target, *sources)
|
51
|
+
# prepare backs up the target to allow rollback on error,
|
52
|
+
# and ensures the target parent directory exists.
|
53
|
+
prepare(target)
|
54
|
+
log_basename :prepare, target
|
55
|
+
|
56
|
+
# open the output file and read the file contents
|
57
|
+
# of each input file into the output
|
58
|
+
File.open(target, "wb" ) do |output|
|
59
|
+
output << ERB.new(before).result(binding) unless before.empty?
|
60
|
+
|
61
|
+
sources.each do |source|
|
62
|
+
raise "Not a file: #{source}" unless File.exists?(source) && File.file?(source)
|
63
|
+
|
64
|
+
log_basename :concat, source
|
65
|
+
output << ERB.new(pre).result(binding) unless pre.empty?
|
66
|
+
output << File.read(source)
|
67
|
+
output << ERB.new(post).result(binding) unless post.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
output << ERB.new(after).result(binding) unless after.empty?
|
71
|
+
end
|
72
|
+
|
73
|
+
# return the concatenated file
|
74
|
+
target
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Tap
|
2
|
+
module Tasks
|
3
|
+
# :startdoc::manifest copies files
|
4
|
+
#
|
5
|
+
# Copies a list of files to the specified directory. The files will
|
6
|
+
# be copied using the relative filepath from Dir.pwd, or the file
|
7
|
+
# basename if the filepath is not relative to Dir.pwd. For example:
|
8
|
+
# when copying to '/target_dir' from Dir.pwd = '/dir':
|
9
|
+
#
|
10
|
+
# source path target path
|
11
|
+
# /dir/path/to/file.txt /target_dir/path/to/file.txt
|
12
|
+
# /path/to/file.txt /target_dir/file.txt
|
13
|
+
#
|
14
|
+
# Existing files are backed up as '<file>_before_<timestamp>'
|
15
|
+
# into the standard backup directory. Up-to-date files are not copied.
|
16
|
+
# Raises an error for non-existing and non-file input files, as well
|
17
|
+
# as a non-directory target_dir.
|
18
|
+
#
|
19
|
+
class Copy < Tap::FileTask
|
20
|
+
|
21
|
+
# Determines the copy filepath using the target_dir and the
|
22
|
+
# relative filepath from Dir.pwd to path. Uses the basename
|
23
|
+
# of path if path is not relative to Dir.pwd.
|
24
|
+
def copy_filepath(target_dir, path)
|
25
|
+
relative_path = Root.relative_filepath(Dir.pwd, path) || File.basename(path)
|
26
|
+
File.join(target_dir, relative_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Determines a backup filepath by adding a timestamp to the input path.
|
30
|
+
def backup_filepath(path)
|
31
|
+
extname = File.extname(path)
|
32
|
+
File.expand_path("#{path.chomp(extname)}_before_#{Time.now.strftime(timestamp)}#{extname}")
|
33
|
+
end
|
34
|
+
|
35
|
+
def process(target_dir, *filepaths)
|
36
|
+
filepaths.collect do |filepath|
|
37
|
+
target = copy_filepath(target_dir, filepath)
|
38
|
+
|
39
|
+
if uptodate?(target, filepath)
|
40
|
+
log_basename :skip, filepath, Logger::DEBUG
|
41
|
+
else
|
42
|
+
prepare target
|
43
|
+
|
44
|
+
log_basename :cp, filepath
|
45
|
+
FileUtils.cp(filepath, target)
|
46
|
+
end
|
47
|
+
|
48
|
+
target
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Tap
|
2
|
+
module Tasks
|
3
|
+
# :startdoc::manifest search for lines matching a pattern
|
4
|
+
#
|
5
|
+
# A simple line-matching task patterned after the *nix grep utility.
|
6
|
+
# Grep find and prints all lines matching the regexp pattern in files
|
7
|
+
# matched by the globs.
|
8
|
+
#
|
9
|
+
class Grep < Tap::Task
|
10
|
+
|
11
|
+
config :case_insensitive, false, :short => :i, &c.switch # set case-insensitive matching
|
12
|
+
config :extended, false, :short => :e, &c.switch # set extended matching
|
13
|
+
config :multiline, false, :short => :m, &c.switch # set multiline matching
|
14
|
+
config :escape, false, &c.flag # escape pattern beforehand
|
15
|
+
|
16
|
+
# Returns an array of the regexp options specified by the config.
|
17
|
+
def regexp_options
|
18
|
+
[ case_insensitive ? Regexp::IGNORECASE : nil,
|
19
|
+
extended ? Regexp::EXTENDED : nil,
|
20
|
+
multiline ? Regexp::MULTILINE : nil
|
21
|
+
].compact
|
22
|
+
end
|
23
|
+
|
24
|
+
def process(pattern, *globs)
|
25
|
+
pattern = Regexp.escape(pattern) if escape
|
26
|
+
regexp = Regexp.new(pattern, *regexp_options)
|
27
|
+
|
28
|
+
input_files = Tap::Root.glob(*globs)
|
29
|
+
input_files.each do |input_file|
|
30
|
+
next unless File.exists?(input_file) && File.file?(input_file)
|
31
|
+
|
32
|
+
File.open(input_file) do |file|
|
33
|
+
line_num = -1
|
34
|
+
file.each_line do |line|
|
35
|
+
line_num += 1
|
36
|
+
next unless line =~ regexp
|
37
|
+
task_block.call(self, input_file, line_num, line)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
input_files
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def default_task_block # :nodoc:
|
48
|
+
lambda do |task, filepath, line_num, line|
|
49
|
+
task.log "#{File.basename(filepath)} (#{line_num})", line.strip
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::manifest print a directory tree
|
6
|
+
#
|
7
|
+
# Prints a directory tree using a nice algorithm from
|
8
|
+
# http://www.xxeo.com/archives/2007/06/06/a-simple-directory-tree-printer-in-ruby.html
|
9
|
+
#
|
10
|
+
# The output format is like this:
|
11
|
+
#
|
12
|
+
# sample
|
13
|
+
# |- MIT-LICENSE
|
14
|
+
# |- README
|
15
|
+
# |- Rakefile
|
16
|
+
# |- lib
|
17
|
+
# | `- sample.rb
|
18
|
+
# |- sample.gemspec
|
19
|
+
# |- tap.yml
|
20
|
+
# `- test
|
21
|
+
# |- sample_test.rb
|
22
|
+
# |- tap_test_helper.rb
|
23
|
+
# `- tap_test_suite.rb
|
24
|
+
#
|
25
|
+
#
|
26
|
+
class PrintTree < Tap::Task
|
27
|
+
ARM_MAP = Hash.new("| ")
|
28
|
+
ARM_MAP[""] = ""
|
29
|
+
ARM_MAP["`"] = " "
|
30
|
+
|
31
|
+
config :hidden_files, false, &c.switch # Flag to print hidden files.
|
32
|
+
|
33
|
+
def process(*paths)
|
34
|
+
paths << "." if paths.empty?
|
35
|
+
paths.map { |path| visit(Pathname.new("."), "", "", "", Pathname.new(path)) }
|
36
|
+
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns true if the path is hidden. If the hidden_files
|
41
|
+
# config is specified as true, then hidden? always returns
|
42
|
+
# false, indicating that under these conditions no path
|
43
|
+
# is considered hidden.
|
44
|
+
def hidden?(path)
|
45
|
+
!hidden_files && path.to_s =~ /^\.[^\.]/
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def default_task_block # :nodoc:
|
51
|
+
lambda {|line| puts line }
|
52
|
+
end
|
53
|
+
|
54
|
+
# slightly modified from the original algorithm
|
55
|
+
def visit(path, leader, tie, arm, node) # :nodoc:
|
56
|
+
task_block.call("#{leader}#{arm}#{tie}#{node}\n") unless hidden?(node)
|
57
|
+
visitChildren(path + node, leader + ARM_MAP[arm])
|
58
|
+
end
|
59
|
+
|
60
|
+
# slightly modified from the original algorithm
|
61
|
+
def visitChildren(path, leader) # :nodoc:
|
62
|
+
return unless FileTest.directory? path
|
63
|
+
return unless FileTest.readable? path
|
64
|
+
return if hidden?(path.basename)
|
65
|
+
|
66
|
+
files = path.children(false).sort #false = return name, not full path
|
67
|
+
|
68
|
+
return if files.empty?
|
69
|
+
|
70
|
+
arms = Array.new(files.length - 1, "|") << "`"
|
71
|
+
|
72
|
+
pairs = files.zip(arms)
|
73
|
+
pairs.each { |e| visit(path, leader, "- ", e[1], e[0]) }
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'tap/support/simple_table'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
|
6
|
+
# TableTask is a base class for table-related FileTasks.
|
7
|
+
class TableTask < Tap::FileTask
|
8
|
+
SimpleTable = Support::SimpleTable
|
9
|
+
|
10
|
+
config :header_row, false, &c.flag # indicates a header row
|
11
|
+
config :row_sep, "\n", &c.string # row delimiter
|
12
|
+
config :col_sep, "\t", &c.string # column delimiter
|
13
|
+
config :default_value, nil, &c.string_or_nil # a default value for empty cells
|
14
|
+
|
15
|
+
# Parses a Tap::Support::SimpleTable from the string using the
|
16
|
+
# table configurations.
|
17
|
+
def parse_table(str)
|
18
|
+
data = SimpleTable.parse_data(str, row_sep, col_sep)
|
19
|
+
SimpleTable.new(data, :default_value => default_value, :header_row => header_row)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/tap.yml
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bahuvrihi-sample_tasks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Simon Chiang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-08 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: tap
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.10.0
|
23
|
+
version:
|
24
|
+
description:
|
25
|
+
email: simon.chiang@uchsc.edu
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- README
|
32
|
+
- MIT-LICENSE
|
33
|
+
files:
|
34
|
+
- MIT-LICENSE
|
35
|
+
- README
|
36
|
+
- lib/tap/support/simple_table.rb
|
37
|
+
- lib/tap/tasks/concat.rb
|
38
|
+
- lib/tap/tasks/copy.rb
|
39
|
+
- lib/tap/tasks/grep.rb
|
40
|
+
- lib/tap/tasks/print_tree.rb
|
41
|
+
- lib/tap/tasks/table_task.rb
|
42
|
+
- tap.yml
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://tap.rubyforge.org/sample_tasks/
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: tap
|
65
|
+
rubygems_version: 1.2.0
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: Sample Tap Tasks
|
69
|
+
test_files: []
|
70
|
+
|