inmake 2.0.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.
- checksums.yaml +7 -0
- data/bin/inmake +26 -0
- data/lib/inmake/config.rb +184 -0
- data/lib/inmake/runner.rb +125 -0
- data/lib/inmake.rb +4 -0
- metadata +48 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: c37126d894a3decaab96aee33fd26d3ee070ce37
|
|
4
|
+
data.tar.gz: ede65f7ae76d41696c33b3be97f0b3fdc53b12b2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: bee4047a60a0f4e645fedc5554090fa9e46de37abb9a422413253f5b950aa5dc2bc86e237f6f404a6a872599053fb5073bea1209f1f4ff098cafd8e6e174f9a7
|
|
7
|
+
data.tar.gz: add2a6a9c6baaaf90f5901469657cc84d8ddaa7a2afb835bf76f22c3029664f698d94035fb3561713d454d83c11e74554adce77f1decdb0b884e554298cb724d
|
data/bin/inmake
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'inmake'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
begin
|
|
7
|
+
# Generate a config from command-line arguments and resolve all files to
|
|
8
|
+
# absolute paths
|
|
9
|
+
cfg = Inmake::Config.fromArguments
|
|
10
|
+
cfg = Inmake::Config.resolveFiles cfg
|
|
11
|
+
|
|
12
|
+
# Run inmake on all files found
|
|
13
|
+
runner = Inmake::Runner.new cfg
|
|
14
|
+
|
|
15
|
+
runner.run
|
|
16
|
+
rescue Inmake::NoFilesGiven => e
|
|
17
|
+
abort e.message
|
|
18
|
+
rescue Inmake::InvalidDirMode => e
|
|
19
|
+
abort e.message
|
|
20
|
+
rescue Inmake::InvalidVarDefinition => e
|
|
21
|
+
abort e.message
|
|
22
|
+
rescue Inmake::MultipleModeException => e
|
|
23
|
+
abort e.message
|
|
24
|
+
rescue Inmake::CommandNotFound => e
|
|
25
|
+
abort e.message
|
|
26
|
+
end
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# echo hi from Inmake::Config!
|
|
3
|
+
require 'inmake/version'
|
|
4
|
+
module Inmake
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# Stores inmake configuration options.
|
|
8
|
+
#
|
|
9
|
+
class Config
|
|
10
|
+
attr_reader :dirMode, :searchMode, :searchArgument, :stripMatched,
|
|
11
|
+
:variables, :files, :variablesDisabled, :ignoreNonmatches
|
|
12
|
+
attr_writer :variables, :files
|
|
13
|
+
def initialize opts
|
|
14
|
+
# How we treat directories that have been passed to the file list.
|
|
15
|
+
# Possible values are :acceptDirs, :ignoreDirs
|
|
16
|
+
# :acceptDirs => directories are accepted and recursed into
|
|
17
|
+
# :ignoreDirs => directories are ignored
|
|
18
|
+
@dirMode = opts[:dirMode]
|
|
19
|
+
# A list of all the files that inmake will act on.
|
|
20
|
+
# This may include directories or relative paths.
|
|
21
|
+
@files = opts[:files]
|
|
22
|
+
# How inmake looks for the build command inside the file. Possible values
|
|
23
|
+
# are :prefix, :suffix, :regex, :secondLine
|
|
24
|
+
# :prefix => search each line start for a prefix
|
|
25
|
+
# :suffix => search each line ending for a suffix
|
|
26
|
+
# :regex => search each line via an actual regex
|
|
27
|
+
# :secondLine => use the second line (or third if the second looks like an
|
|
28
|
+
# encoding line like Python)
|
|
29
|
+
@searchMode = opts[:searchMode]
|
|
30
|
+
# An additional argument to specify the thing that the search mode uses
|
|
31
|
+
# to look for the build command. AKA, the actual prefix string or suffix
|
|
32
|
+
# string or the regex object.
|
|
33
|
+
@searchArgument = opts[:searchArgument]
|
|
34
|
+
# Do we strip all found parts of the regex from the build command?
|
|
35
|
+
@stripMatched = opts[:stripMatched]
|
|
36
|
+
# Hash of variables that can be replaced in the build command
|
|
37
|
+
@variables = opts[:variables]
|
|
38
|
+
# Are variables disabled overall? Even the builtins that is...
|
|
39
|
+
@variablesDisabled = opts[:variablesDisabled]
|
|
40
|
+
# Do we stop when a file didn't have a command inside?
|
|
41
|
+
@ignoreNonmatches = opts[:ignoreNonmatches]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.fromArguments
|
|
45
|
+
require 'optparse'
|
|
46
|
+
|
|
47
|
+
opts = {}
|
|
48
|
+
opts[:files] = []
|
|
49
|
+
opts[:variables] = {}
|
|
50
|
+
|
|
51
|
+
# Parse special arguments
|
|
52
|
+
OptionParser.new do |parser|
|
|
53
|
+
parser.banner = INMAKE_BANNER
|
|
54
|
+
|
|
55
|
+
parser.on('-f', '--file FILENAME', 'Specify a target file.') do |filename|
|
|
56
|
+
opts[:files] << filename
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
parser.on('-p', '--prefix PREFIX', 'Find the build command by a prefix.') do |prefix|
|
|
60
|
+
unless opts[:searchMode]
|
|
61
|
+
opts[:searchMode] = :prefix
|
|
62
|
+
opts[:searchArgument] = prefix
|
|
63
|
+
else
|
|
64
|
+
raise MultipleModeException, "Multiple search mode definitions!"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
parser.on('-s', '--suffix SUFFIX', 'Find the build command by a suffix.') do |suffix|
|
|
69
|
+
unless opts[:searchMode]
|
|
70
|
+
opts[:searchMode] = :suffix
|
|
71
|
+
opts[:searchArgument] = suffix
|
|
72
|
+
else
|
|
73
|
+
raise MultipleModeException, "Multiple search mode definitions!"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
okDirModes = [:acceptDirs, :ignoreDirs]
|
|
79
|
+
parser.on('-d', '--dir-mode MODE', "Define behavior when dealing with a directory. (default: acceptDirs) Accepted values are: #{okDirModes.join ', '}") do |dm|
|
|
80
|
+
dm = dm.to_sym
|
|
81
|
+
raise InvalidDirMode, "Not a valid directory mode: #{dm}" unless okDirModes.include? dm
|
|
82
|
+
opts[:dirMode] = dm
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
parser.on('-x', '--regex REGEX', 'Specify a regular expression to match the build command.') do |rx|
|
|
86
|
+
unless opts[:searchMode]
|
|
87
|
+
re = Regexp.compile rx
|
|
88
|
+
opts[:searchMode] = :regex
|
|
89
|
+
opts[:searchArgument] = re
|
|
90
|
+
else
|
|
91
|
+
raise MultipleModeException, "Multiple search mode definitions!"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
parser.on('--[no-]strip-matched', 'Strip all found matches on a regex search (default: false)') do |f|
|
|
96
|
+
opts[:stripMatched] = f
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
parser.on('--[no-]ignore-nonmatched', 'Silently continue if a file does not seem to have a build command (default: true)') do |f|
|
|
100
|
+
opts[:ignoreNonmatches] = f
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
parser.on('--no-vars', 'Disable all replacement variables, even the builtin ones (default: false)') do |v|
|
|
104
|
+
opts[:variablesDisabled] = v
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
parser.on('-a', '--add-var KEY=VALUE', 'Add a replacement from {{KEY}} (always allcaps!) to VALUE, much like a C preprocessor definition') do |var|
|
|
108
|
+
key, value = var.split '='
|
|
109
|
+
raise InvalidVarDefinition, "Invalid variable definition syntax: `#{var}`" unless key and value
|
|
110
|
+
|
|
111
|
+
opts[:variables][key.upcase] = value
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end.parse!
|
|
115
|
+
|
|
116
|
+
# any arguments that weren't flags are just treated as file names
|
|
117
|
+
unless ARGV.empty?
|
|
118
|
+
opts[:files].concat ARGV
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# The default search mode is to find the build command on the second line of
|
|
122
|
+
# the source code.
|
|
123
|
+
opts[:searchMode] ||= :secondLine
|
|
124
|
+
|
|
125
|
+
# The default file mode means that if a directory is encountered, we recurse
|
|
126
|
+
# on all its files.
|
|
127
|
+
opts[:dirMode] ||= :acceptDirs
|
|
128
|
+
|
|
129
|
+
# Variables are enabled by default.
|
|
130
|
+
opts[:variablesDisabled] ||= false
|
|
131
|
+
|
|
132
|
+
# By default, we do not strip the matched string.
|
|
133
|
+
opts[:stripMatched] ||= false
|
|
134
|
+
|
|
135
|
+
opts[:ignoreNonmatched] = true unless defined? opts[:ignoreNonmatched]
|
|
136
|
+
|
|
137
|
+
# Can't run without ANY files...
|
|
138
|
+
raise NoFilesGiven, "No input files specified! Use #{$0} --help for how to add input files." if opts[:files].empty?
|
|
139
|
+
|
|
140
|
+
# return a new Config object
|
|
141
|
+
return Config.new opts
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def self.resolveFiles cfg
|
|
146
|
+
newFiles = []
|
|
147
|
+
cfg.files.each do |f|
|
|
148
|
+
if File.exist? f
|
|
149
|
+
if File.file? f
|
|
150
|
+
newFiles << f
|
|
151
|
+
elsif File.directory? f and cfg.dirMode == :acceptDirs
|
|
152
|
+
newFiles.concat Dir[File.join(f, '**/*.*')].select {|x| File.file? x }
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
cfg.files = newFiles.map { |x| File.expand_path x }
|
|
158
|
+
cfg
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# Multiple search modes were defined when reading definitions from the
|
|
164
|
+
# command line (eg regex and prefix at the same time)
|
|
165
|
+
class MultipleModeException < StandardError; end
|
|
166
|
+
##
|
|
167
|
+
# A variable was defined with wrong syntax when on the command line!
|
|
168
|
+
# (not something=something)
|
|
169
|
+
class InvalidVarDefinition < StandardError; end
|
|
170
|
+
##
|
|
171
|
+
# No files added
|
|
172
|
+
class NoFilesGiven < StandardError; end
|
|
173
|
+
##
|
|
174
|
+
# The directory handling mode was invalid!
|
|
175
|
+
class InvalidDirMode < StandardError; end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
INMAKE_BANNER = <<-EOF
|
|
179
|
+
inmake v#{Inmake::VERSION} - the inline build command runner
|
|
180
|
+
Runs commands directly embedded inside your source code.
|
|
181
|
+
Usage: #{$0} [options...] [files]
|
|
182
|
+
Options:
|
|
183
|
+
|
|
184
|
+
EOF
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# echo Hi from Inmake::Runner!
|
|
3
|
+
module Inmake
|
|
4
|
+
##
|
|
5
|
+
# = Inmake Command Runner
|
|
6
|
+
#
|
|
7
|
+
# Finds and runs the commands inside all of the files.
|
|
8
|
+
# The same search mode is used for every file.
|
|
9
|
+
class Runner
|
|
10
|
+
|
|
11
|
+
# Set up a runner with a configuration object defined earlier.
|
|
12
|
+
def initialize cfg
|
|
13
|
+
@config = cfg
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Run inmake on each of the files defined in the configuration
|
|
17
|
+
def run
|
|
18
|
+
@config.files.each do |x|
|
|
19
|
+
begin
|
|
20
|
+
dispatch x
|
|
21
|
+
rescue CommandNotFound => e
|
|
22
|
+
raise unless @config.ignoreNonmatches
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Find and run a command in a given file, depending on the search mode
|
|
28
|
+
def dispatch file
|
|
29
|
+
File.open(file) do |fd|
|
|
30
|
+
fd.flock File::LOCK_EX
|
|
31
|
+
if @config.searchMode == :prefix
|
|
32
|
+
runPrefix fd
|
|
33
|
+
elsif @config.searchMode == :suffix
|
|
34
|
+
runSuffix fd
|
|
35
|
+
elsif @config.searchMode == :regex
|
|
36
|
+
runRegex fd
|
|
37
|
+
elsif @config.searchMode == :secondLine
|
|
38
|
+
runSecondLine fd
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Apply variables and then run the found build command
|
|
44
|
+
def applyCommand cmd, fd
|
|
45
|
+
|
|
46
|
+
unless @config.variablesDisabled
|
|
47
|
+
@config.variables.each do |k, v|
|
|
48
|
+
cmd.gsub! '{{'+k.to_s+'}}', v
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
cmd.gsub! '{{f}}', fd.path
|
|
52
|
+
cmd.gsub! '{{bn}}', File.basename(fd.path)
|
|
53
|
+
cmd.gsub! '{{bn1}}', File.basename(fd.path, '.*')
|
|
54
|
+
cmd.gsub! '{{ext}}', File.extname(fd.path)
|
|
55
|
+
cmd.gsub! '{{dn}}', File.dirname(fd.path)
|
|
56
|
+
st = fd.stat
|
|
57
|
+
cmd.gsub! '{{mode}}', st.mode.to_s
|
|
58
|
+
cmd.gsub! '{{mtime}}', st.mtime.to_i.to_s
|
|
59
|
+
cmd.gsub! '{{ctime}}', st.ctime.to_i.to_s
|
|
60
|
+
cmd.gsub! '{{size}}', st.size.to_s
|
|
61
|
+
end
|
|
62
|
+
fd.flock File::LOCK_UN
|
|
63
|
+
system cmd
|
|
64
|
+
puts cmd
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Find a given prefix in a file and apply the build command on match
|
|
68
|
+
def runPrefix fd
|
|
69
|
+
rx = /^\s*#{Regexp.escape @config.searchArgument}\s*/
|
|
70
|
+
command = fd.each_line.detect do |line|
|
|
71
|
+
rx.match line
|
|
72
|
+
end
|
|
73
|
+
raise CommandNotFound, "Did not find a prefixed command in file `#{fd.path}`" unless command
|
|
74
|
+
command.gsub!(rx, '')
|
|
75
|
+
|
|
76
|
+
applyCommand command, fd
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Find a given suffix in a file and apply the build command when matched
|
|
80
|
+
# Raises CommandNotFound if no command was found in a file
|
|
81
|
+
def runSuffix fd
|
|
82
|
+
rx = /#{Regexp.escape @config.searchArgument}\s*$/
|
|
83
|
+
command = fd.each_line.detect do |line|
|
|
84
|
+
rx.match line
|
|
85
|
+
end
|
|
86
|
+
raise CommandNotFound, "Did not find a suffixed command in file `#{fd.path}`" unless command
|
|
87
|
+
command.gsub!(rx, '') if @config.stripMatched
|
|
88
|
+
|
|
89
|
+
applyCommand command, fd
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Find a given regex in a file and apply the build command when matched
|
|
93
|
+
# Raises CommandNotFound if no command was found in a file
|
|
94
|
+
def runRegex fd
|
|
95
|
+
rx = @config.searchArgument
|
|
96
|
+
command = fd.each_line.detect do |line|
|
|
97
|
+
rx.match line
|
|
98
|
+
end
|
|
99
|
+
raise CommandNotFound, "Did not find a regex-ed command in file `#{fd.path}`" unless command
|
|
100
|
+
command.gsub!(rx, '') if @config.stripMatched
|
|
101
|
+
|
|
102
|
+
applyCommand command, fd
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Run the second line of code. This is the default option.
|
|
106
|
+
def runSecondLine fd
|
|
107
|
+
isEncodingLine = /coding[:=]\s*([-\w.]+)/
|
|
108
|
+
fd.gets
|
|
109
|
+
secondLine = fd.gets
|
|
110
|
+
|
|
111
|
+
raise CommandNotFound, "There wasn't enough data in the file `#{fd.path}` for two lines!" if $_.nil?
|
|
112
|
+
|
|
113
|
+
if isEncodingLine =~ secondLine
|
|
114
|
+
secondLine = fd.gets
|
|
115
|
+
raise CommandNotFound, "There wasn't enough data in the file `#{fd.path}` for three lines!" if $_.nil?
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Strip stuff until the first whitespace
|
|
119
|
+
command = secondLine[(secondLine =~ /\s/)...secondLine.length].strip
|
|
120
|
+
|
|
121
|
+
applyCommand command, fd
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
class CommandNotFound < StandardError; end
|
|
125
|
+
end
|
data/lib/inmake.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: inmake
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- boxmein
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-07-06 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Inline build command runner for any kind of projects.
|
|
14
|
+
email: boxmein@boxmein.net
|
|
15
|
+
executables:
|
|
16
|
+
- inmake
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- bin/inmake
|
|
21
|
+
- lib/inmake.rb
|
|
22
|
+
- lib/inmake/config.rb
|
|
23
|
+
- lib/inmake/runner.rb
|
|
24
|
+
homepage: https://github.com/boxmein/inmake
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata: {}
|
|
28
|
+
post_install_message:
|
|
29
|
+
rdoc_options: []
|
|
30
|
+
require_paths:
|
|
31
|
+
- lib
|
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
|
+
requirements:
|
|
34
|
+
- - '>='
|
|
35
|
+
- !ruby/object:Gem::Version
|
|
36
|
+
version: '0'
|
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - '>='
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubyforge_project:
|
|
44
|
+
rubygems_version: 2.4.1
|
|
45
|
+
signing_key:
|
|
46
|
+
specification_version: 4
|
|
47
|
+
summary: Inline Build Commands
|
|
48
|
+
test_files: []
|