sample_tasks 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +71 -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,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 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-08-08 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: tap
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.0
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: simon.chiang@uchsc.edu
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- MIT-LICENSE
|
34
|
+
files:
|
35
|
+
- MIT-LICENSE
|
36
|
+
- README
|
37
|
+
- lib/tap/support/simple_table.rb
|
38
|
+
- lib/tap/tasks/concat.rb
|
39
|
+
- lib/tap/tasks/copy.rb
|
40
|
+
- lib/tap/tasks/grep.rb
|
41
|
+
- lib/tap/tasks/print_tree.rb
|
42
|
+
- lib/tap/tasks/table_task.rb
|
43
|
+
- tap.yml
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://tap.rubyforge.org/sample_tasks/
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project: tap
|
66
|
+
rubygems_version: 1.2.0
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: Sample Tap Tasks
|
70
|
+
test_files: []
|
71
|
+
|