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 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
+