pad_utils 1.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f6939b46b2b13a5954d87a24eebe598fd044e4af
4
+ data.tar.gz: 4d803c5b1fac23443d42b84e15a4e4b0e14d2dc3
5
+ SHA512:
6
+ metadata.gz: 2f759bb5c6e0e96b5ce794df6301cf3cb3bd2002451a652680a799e1e4e48a5eda6081c328fdf78d5803dc3eef9979e3375ad24bd748f4c9bdfad1d78983c0b4
7
+ data.tar.gz: 64ef8ed6c014074b66c5eb63fc55cec26f2706e1c41aad78cc384ad9ebedb320319e30af515fa39a3fac627ea93a04b934238bd8676df4ef39725e04cfa0eb0f
data/LICENSE.txt ADDED
@@ -0,0 +1,177 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
data/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # PadUtils
2
+
3
+ PadUtils is a simple gem containing common utilities and shortcuts. It is used in the [Padstone](http://padstone.io) app builder but can be embedded in any other Ruby project.
4
+
5
+ ## Installation
6
+
7
+ It's a Ruby gem. Install it like any other gem!
8
+
9
+ `gem install pad_utils`
10
+
11
+ ## Usage
12
+
13
+ Just `require 'pad_utils'` within your code to access the following methods.
14
+
15
+ ### Build CLI menus
16
+
17
+ #### 1. Yes/No menu
18
+
19
+ Prompt user with a cli yes/no menu. Returns `true` or `false`.
20
+
21
+ * `question`: the question to ask
22
+ * `default`: the default answer
23
+
24
+ `PadUtils.yes_no_menu(question: "Question?", default: "y")`
25
+
26
+ #### 2. Open question menu
27
+
28
+ Prompt user with a cli open question menu. Returns a `string`.
29
+
30
+ `PadUtils.question_menu(question)`
31
+
32
+ #### 3. Multiple choice menu
33
+
34
+ Prompt user with a multiple choice menu. Returns a `symbol`.
35
+
36
+ * `question`: the question to ask
37
+ * `choices`: hash of choices (e.g. `{b: "blue", r: "red"}`)
38
+ * `default`: symbol representing the default value. If none provided, last value in choices hash will be used.
39
+
40
+ `PadUtils.choice_menu(question: "Question?", choices: {}, default: nil)`
41
+
42
+
43
+ ### Work with text
44
+
45
+ #### 1. Convert a string to a Rubified name
46
+
47
+ Convert a string into a proper "rubified" name. For example, 'app_name' will be converted to 'AppName'. Returns a `string`.
48
+
49
+ `PadUtils.convert_to_ruby_name(value)`
50
+
51
+ #### 2. Sanitize a string
52
+
53
+ Sanitize a string by replacing special characters (including spaces) with underscores. Returns a `string`.
54
+
55
+ `PadUtils.sanitize(value)`
56
+
57
+ #### 3. Replace a string in a file
58
+
59
+ Replace text within a file. `old_text` can either be a `string` or a `regex`. Doesn't return anything, overwrites `file`.
60
+
61
+ `PadUtils.replace_in_file(file, old_text, new_text)`
62
+
63
+ #### 4. Insert text before first occurence
64
+
65
+ Insert text in a string or a file before the first occurence of a string. Returns a `string`. If `is_file` is `true`, overwrites `original` file.
66
+
67
+ * `original`: the original string or filename
68
+ * `tag`: occurence of string to find
69
+ * `text`: string to insert
70
+ * `is_file`: `true` if `original` is a filename (default), `false` if it's a `string`
71
+
72
+ `PadUtils.insert_before_first(original: nil, tag: nil, text: nil, is_file: true)`
73
+
74
+ #### 5. Insert text before last occurence
75
+
76
+ Insert text in a string or a file before the last occurence of a string. Returns a `string`. If `is_file` is `true`, overwrites `original` file.
77
+
78
+ * `original`: the original string or filename
79
+ * `tag`: occurence of string to find
80
+ * `text`: string to insert
81
+ * `is_file`: `true` if `original` is a filename (default), `false` if it's a `string`
82
+
83
+ `PadUtils.insert_before_last(original: nil, tag: nil, text: nil, is_file: true)`
84
+
85
+ #### 6. Insert text after first occurence
86
+
87
+ Insert text in a string or a file after the first occurence of a string. Returns a `string`. If `is_file` is `true`, overwrites `original` file.
88
+
89
+ * `original`: the original string or filename
90
+ * `tag`: occurence of string to find
91
+ * `text`: string to insert
92
+ * `is_file`: `true` if `original` is a filename (default), `false` if it's a `string`
93
+
94
+ `PadUtils.insert_after_first(original: nil, tag: nil, text: nil, is_file: true)`
95
+
96
+ #### 7. Insert text after last occurence
97
+
98
+ Insert text in a string or a file after the last occurence of a string. Returns a `string`. If `is_file` is `true`, overwrites `original` file.
99
+
100
+ * `original`: the original string or filename
101
+ * `tag`: occurence of string to find
102
+ * `text`: string to insert
103
+ * `is_file`: `true` if `original` is a filename (default), `false` if it's a `string`
104
+
105
+ `PadUtils.insert_after_last(original: nil, tag: nil, text: nil, is_file: true)`
106
+
107
+ ### JSON and Hash
108
+
109
+ Few methods to convert JSON to deep symbolized hash and back.
110
+
111
+ #### 1. Symbolize all keys in a hash
112
+
113
+ Convert all keys and sub-keys to symbols in a hash. Emulates the `deep_symbolize_keys` found in [Rails](http://apidock.com/rails/Hash/deep_symbolize_keys). Returns a `Hash`.
114
+
115
+ `PadUtils.deep_symbolize_hash_keys(hash)`
116
+
117
+ #### 2. Convert a JSON string to a symbolized hash
118
+
119
+ Returns a `Hash`.
120
+
121
+ `PadUtils.json_to_hash(json)`
122
+
123
+ #### 3. Load a JSON file and convert it to a symbolized hash
124
+
125
+ Returns a `Hash`.
126
+
127
+ `PadUtils.json_file_to_hash(json_filename)`
128
+
129
+ #### 4. Convert a hash to JSON
130
+
131
+ *Alias method on `to_json` for consistency.*
132
+
133
+ Returns a `string`.
134
+
135
+ `PadUtils.hash_to_json(hash)`
136
+
137
+ #### 5. Write a hash to a JSON file
138
+
139
+ Returns the file content as a `string`.
140
+
141
+ `PadUtils..hash_to_json_file(filename, hash)`
142
+
143
+ ### Work with files
144
+
145
+ Mostly, these are convenience methods aliasing existing Ruby methods. Implemented for consistency.
146
+
147
+ #### 1. Delete a file
148
+
149
+ Delete a file. If not found, doesn't raise any error.
150
+
151
+ `delete_file(file_path)`
152
+
153
+ #### 2. Does a file exist?
154
+
155
+ Returns `true` or `false`.
156
+
157
+ `PadUtils.file_exist?(file_path)`
158
+
159
+ #### 3. Copy a file
160
+
161
+ **Will override file if it already exists!**
162
+
163
+ `PadUtils.copy_file(file_path, dest_dir)`
164
+
165
+ #### 4. Move a file
166
+
167
+ **Will not throw an error if original file doesn't exist!**
168
+
169
+ `PadUtils.move_file(file_path, dest_file)`
170
+
171
+ #### 5. Copy multiple files
172
+
173
+ `PadUtils.copy_files(files_array, dest_dir)`
174
+
175
+ #### 6. Copy all files
176
+
177
+ Copy all files from a directory to another. *Will create destination if it doesn't exist*.
178
+
179
+ `PadUtils.copy_all_files(source_dir, dest_dir)`
180
+
181
+ #### 7. Create a directory
182
+
183
+ Create a directory and subdirectories. **Won't complain if it already exists. Won't override content**.
184
+
185
+ `PadUtils.create_directory(dir_name)`
186
+
187
+ #### 8. Delete a directory and its content
188
+
189
+ `PadUtils.delete_directory(dir_name)`
190
+
191
+ #### 9. Read content of a file
192
+
193
+ Returns a `string`.
194
+
195
+ `PadUtils.get_file_content(filepath)`
196
+
197
+ #### 10. Write to a file
198
+
199
+ Write content to a file. Create it if it doesn't exist. **Overwrites it if it already exists!**.
200
+
201
+ `PadUtils.write_to_file(filepath, content)`
202
+
203
+ #### 11. Append to a file
204
+
205
+ Append content to the end of a file. Create it if it doesn't exist.
206
+
207
+ **It will write a newline character first. If you don't want that,
208
+ set the `new_line` option to `false`**.
209
+
210
+ `PadUtils.append_to_file(filepath, content, new_line = true)`
211
+
212
+ ### Logging
213
+
214
+ By default, logs will go to `~/pad_logs/logs.txt`.
215
+
216
+ * Change default path: `PadUtils.log_path = "/new/path/to/logs"`
217
+ * Change default file name: `PadUtils.log_file = "my_logs.txt"`
218
+
219
+ To log a message, you call `log` and pass it a `message` string. Optionally, you can also pass an `Exception` object in the parameters:
220
+
221
+ `PadUtils.log(message, e = nil)`
222
+
223
+ ### Some time methods
224
+
225
+ #### 1. Time to string timestamp
226
+
227
+ Returns a `string` timestamp with the format `YYYYMMDDHHmmss` from a `Time` object.
228
+
229
+ `PadUtils.time_to_stamp(val)`
230
+
231
+ #### 2. String to time
232
+
233
+ Returns a `Time` object from a timestamp with the format `YYYYMMDDHHmmss`
234
+
235
+ `PadUtils.stamp_to_time(val)`
236
+
237
+ #### 3. Time to readable string
238
+
239
+ Returns a `string` readable timestamp with format `YYYY-MM-DD HH:mm:ss` from a `Time` object.
240
+
241
+ `PadUtils.time_to_readable_stamp(val)`
242
+
243
+ #### 4. Readable timestamp to time
244
+
245
+ Returns a `Time` object from a readable timestamp `string` with format `YYYY-MM-DD HH:mm:ss`
246
+
247
+ `PadUtils.readable_stamp_to_time(val)`
248
+
249
+ ## Contribute
250
+
251
+ [Get in touch](https://twitter.com/nicoschuele) before submitting a pull request, I don't want to waste your time by rejecting it!
252
+
253
+ ## Testing
254
+
255
+ The test suite for PadUtils is currently outside of the gem itself. I may add it if I have time.
256
+
257
+ ## License
258
+
259
+ Copyright 2016 - Nico Schuele
260
+
261
+ Licensed under the Apache License, Version 2.0 (the "License");
262
+ you may not use this file except in compliance with the License.
263
+ You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
264
+
265
+ Unless required by applicable law or agreed to in writing, software
266
+ distributed under the License is distributed on an "AS IS" BASIS,
267
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
268
+ See the License for the specific language governing permissions and
269
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :spec
data/bin/padutils ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/pad_utils"
4
+
5
+ PadUtils::main ARGV
@@ -0,0 +1,80 @@
1
+ require "fileutils"
2
+
3
+ module PadUtils
4
+
5
+ # The following methods are just here for convenience and consistency.
6
+ # Most are wrappers on FileUtils existing methods. Having them here,
7
+ # a user of PadUtils doesn't have to remember names and parameters.
8
+
9
+ # Delete a file. If not found, doesn't raise any error.
10
+ def self.delete_file(file_path)
11
+ FileUtils.rm(file_path, force: true)
12
+ end
13
+
14
+ # Just a wrapper on File.exist? for consistency.
15
+ def self.file_exist?(file_path)
16
+ File.exist?(file_path)
17
+ end
18
+
19
+ # Just a wrapper on FileUtils.cp for consistency.
20
+ # Will override file if it already exists!
21
+ def self.copy_file(file_path, dest_dir)
22
+ FileUtils.cp(file_path, dest_dir)
23
+ end
24
+
25
+ # Just a wrapper on FileUtils.mv for consistency.
26
+ # Will not throw an error if original file doesn't exist
27
+ def self.move_file(file_path, dest_file)
28
+ FileUtils.mv(file_path, dest_file, force: true)
29
+ end
30
+
31
+ # Copy an array of files
32
+ def self.copy_files(files, dest_dir)
33
+ files.each do |f|
34
+ copy_file(f, dest_dir)
35
+ end
36
+ end
37
+
38
+ # Copy all files from a directory to another.
39
+ # Will create destination if it doesn't exist
40
+ def self.copy_all_files(orig_dir, dest_dir)
41
+ FileUtils.copy_entry(orig_dir, dest_dir)
42
+ end
43
+
44
+ # Create a directory and subdirectories
45
+ # Won't complain if it already exists. Won't override content.
46
+ def self.create_directory(dir_name)
47
+ FileUtils.mkdir_p(dir_name)
48
+ end
49
+
50
+ # Delete a directory and its content.
51
+ # Just a wrapper for consistency.
52
+ def self.delete_directory(dir_name)
53
+ FileUtils.rm_r(dir_name)
54
+ end
55
+
56
+ # Reads content of a file. Method created for consistency.
57
+ def self.get_file_content(filepath)
58
+ File.read(filepath)
59
+ rescue Exception => e
60
+ PadUtils.log("Error in get_file_content", e)
61
+ end
62
+
63
+ # Write content to a file. Create it if it doesn't exist.
64
+ def self.write_to_file(filepath, content)
65
+ File.open(filepath, 'w') { |f| f.write(content)}
66
+ rescue Exception => e
67
+ PadUtils.log("Error in write_to_file", e)
68
+ end
69
+
70
+ # Append content to the end of a file. Create it if it doesn't exist.
71
+ # It will write a newline character first. If you don't want that,
72
+ # set the new_line option to false.
73
+ def self.append_to_file(filepath, content, new_line = true)
74
+ content = "\n#{content}" if new_line
75
+ File.open(filepath, 'a') { |f| f.write("#{content}")}
76
+ rescue Exception => e
77
+ PadUtils.log("Error in append_to_file", e)
78
+ end
79
+
80
+ end
@@ -0,0 +1,44 @@
1
+ require 'json'
2
+
3
+ module PadUtils
4
+
5
+ # Convert all keys and sub-keys to symbols in a hash.
6
+ # Emulates the deep_symbolize_keys found in Rails.
7
+ # Returns a Hash.
8
+ def self.deep_symbolize_hash_keys(hash)
9
+ return hash.collect { |e| deep_symbolize_hash_keys(e) } if hash.is_a?(Array)
10
+ return hash.inject({}) { |sh,(k,v)| sh[k.to_sym] = deep_symbolize_hash_keys(v); sh } if hash.is_a?(Hash)
11
+ hash
12
+ end
13
+
14
+ # Convert a JSON string to a symbolized hash.
15
+ # Returns a hash.
16
+ def self.json_to_hash(json)
17
+ h = JSON.parse(json)
18
+ self.deep_symbolize_hash_keys(h)
19
+ end
20
+
21
+ # Load a JSON file and convert it to a symbolized hash.
22
+ # Returns a hash.
23
+ def self.json_file_to_hash(json_file)
24
+ jfile = PadUtils.get_file_content(json_file)
25
+ h = JSON.parse(jfile)
26
+ self.deep_symbolize_hash_keys(h)
27
+ end
28
+
29
+ # Convert a hash to JSON. Alias method for consistency.
30
+ # Returns a string
31
+ def self.hash_to_json(hash)
32
+ hash.to_json
33
+ end
34
+
35
+ # Write a hash to a json file.
36
+ # Returns the file content as a string.
37
+ def self.hash_to_json_file(filename, hash)
38
+ json = hash.to_json
39
+ PadUtils.write_to_file(filename, json)
40
+ json
41
+ end
42
+
43
+
44
+ end
@@ -0,0 +1,44 @@
1
+ module PadUtils
2
+
3
+ # Module variable holding the log path. By default,
4
+ # logs will go in ~/pad_logs/
5
+ @@log_path = "#{ENV["HOME"]}/pad_logs"
6
+
7
+ # Module variable holding the log file. By default,
8
+ # logs will go in @@log_path/logs.txt
9
+ @@log_file = "logs.txt"
10
+
11
+ # Set another log path
12
+ def self.set_log_path(val)
13
+ @@log_path = val
14
+ end
15
+
16
+ # Set another log file
17
+ def self.set_log_file(val)
18
+ @@log_file = val
19
+ end
20
+
21
+ # Log a message
22
+ def self.log(message, e = nil)
23
+ # Create the log directory if it doesn't exist
24
+ PadUtils.create_directory(@@log_path)
25
+
26
+ # Add a timestamp to the message
27
+ message = "#{PadUtils.time_to_stamp(Time.now)}: #{message}"
28
+
29
+ # If an error is added, add its inner message to the message
30
+ # as well as the whole stack
31
+ if e != nil
32
+ message = "#{message}\n\tError: #{e.message} (#{e.class.name})"
33
+ stack = e.backtrace.inspect.split(",")
34
+ stack.each do |s|
35
+ message = "#{message}\n\t\t#{s}"
36
+ end
37
+ message = "#{message}\n"
38
+ end
39
+
40
+ # Adds the message to the log file
41
+ PadUtils.append_to_file("#{@@log_path}/#{@@log_file}", message)
42
+ end
43
+
44
+ end
@@ -0,0 +1,55 @@
1
+ module PadUtils
2
+
3
+ # Prompt user with a cli yes/no menu. Returns true or false.
4
+ # question: the question to ask
5
+ # default: the default answer
6
+ def self.yes_no_menu(question: "Question?", default: "y")
7
+ default_answer = default == "y" ? "(Y/n)" : "(y/N)"
8
+ STDOUT.print "#{question} #{default_answer}: "
9
+ answer = STDIN.gets.chomp.strip.downcase
10
+ answer = default if answer.length < 1
11
+ answer == "y"
12
+
13
+ rescue Exception => e
14
+ PadUtils.log("Error in yes/no menu", e)
15
+ end
16
+
17
+ # Prompt user with a cli open question menu. Returns a string.
18
+ def self.question_menu(question)
19
+ STDOUT.print "#{question}: "
20
+ STDIN.gets.chomp.strip
21
+ end
22
+
23
+ # Prompt user with a multiple choice menu. Returns a symbol. Always!
24
+ # question: the question to ask
25
+ # choices: hash of choices (e.g. {b: "blue", r: "red"})
26
+ # default: symbol representing the default value. If none provided, last
27
+ # value in choices hash will be used.
28
+ def self.choice_menu(question: "Question?", choices: {}, default: nil)
29
+ STDOUT.puts
30
+ STDOUT.puts "- #{question}"
31
+ default ||= choices.keys.last
32
+ default = default.to_sym
33
+
34
+ i = 0
35
+ choices.each do |key, value|
36
+ i += 1
37
+ STDOUT.print "#{i}. #{value}"
38
+ STDOUT.print " (default)" if key.to_s == default.to_s
39
+ STDOUT.print "\n"
40
+ end
41
+
42
+ STDOUT.print "Your choice (1-#{choices.length}): "
43
+ answer = STDIN.gets.chomp.strip.to_i
44
+ STDOUT.puts
45
+ if answer == 0 || answer > choices.length
46
+ return default
47
+ else
48
+ return choices.keys[answer - 1].to_sym
49
+ end
50
+
51
+ rescue Exception => e
52
+ PadUtils.log("Error in choice menu", e)
53
+ end
54
+
55
+ end
@@ -0,0 +1,181 @@
1
+ module PadUtils
2
+
3
+ # Convert a string into a proper Ruby name.
4
+ # For example, 'app_name' will be converted to 'AppName'
5
+ def self.convert_to_ruby_name(value)
6
+ if value.scan(/\_|\-/).size > 0
7
+ value.split(/\_|\-/).map(&:capitalize).join
8
+ else
9
+ value.slice(0,1).capitalize + value.slice(1..-1)
10
+ end
11
+ end
12
+
13
+ # Convert a string to only alphanumeric and underscores
14
+ def self.sanitize(value)
15
+ value.tr('^A-Za-z0-9', '_')
16
+ end
17
+
18
+ # Replace text within a file.
19
+ # old_text can be a regex or a string
20
+ def self.replace_in_file(file, old_text, new_text)
21
+ text_update = PadUtils.get_file_content(file)
22
+ text_update = text_update.gsub(old_text, new_text)
23
+
24
+ PadUtils.write_to_file(file, text_update)
25
+ rescue Exception => e
26
+ PadUtils.log("Error replacing #{old_text} in #{file} with #{new_text}", e)
27
+ end
28
+
29
+ # Insert text in a string or a file before the first occurence of a string.
30
+ # original: the original string or filename
31
+ # tag: occurence of string to find
32
+ # text: string to insert
33
+ # is_file: say if original is a file (default: true) or a string
34
+ def self.insert_before_first(original: nil, tag: nil, text: nil, is_file: true)
35
+ # The new text will be consolidated in content
36
+ content = ""
37
+
38
+ # If coming from a file, read original into content
39
+ if is_file
40
+ content = PadUtils.get_file_content(original)
41
+ else
42
+ content = original
43
+ end
44
+
45
+ # Iterate line by line. If a position is found, insert the text
46
+ # and set found to true to prevent further insertions
47
+ found = false
48
+ new_content = ""
49
+ content.each_line do |line|
50
+ position = line.index(/#{tag}/)
51
+ if position && !found
52
+ new_content += "#{text}#{line}"
53
+ found = true
54
+ else
55
+ new_content += line
56
+ end
57
+ end
58
+
59
+ # If coming from a file, write result in same file. If not,
60
+ # simply return content
61
+ if is_file
62
+ PadUtils.write_to_file(original, new_content)
63
+ return new_content
64
+ else
65
+ return new_content
66
+ end
67
+
68
+ rescue Exception => e
69
+ PadUtils.log("Error in insert_before_first", e)
70
+ end
71
+
72
+ # Insert text in a string or a file before the last occurence of a string.
73
+ # original: the original string or filename
74
+ # tag: occurence of string to find
75
+ # text: string to insert
76
+ # is_file: say if original is a file (default: true) or a string
77
+ def self.insert_before_last(original: nil, tag: nil, text: nil, is_file: true)
78
+ # The new text will be consolidated in content
79
+ content = ""
80
+
81
+ # If coming from a file, read original into content
82
+ if is_file
83
+ content = PadUtils.get_file_content(original)
84
+ else
85
+ content = original
86
+ end
87
+
88
+ # Find the position of tag in the string array and insert the text
89
+ positions = content.enum_for(:scan, /#{tag}/).map { Regexp.last_match.begin(0) }
90
+ content[positions.last - 1] = "#{text}"
91
+
92
+ # If coming from a file, write result in same file. If not,
93
+ # simply return content
94
+ if is_file
95
+ PadUtils.write_to_file(original, content)
96
+ return content
97
+ else
98
+ return content
99
+ end
100
+
101
+ rescue Exception => e
102
+ PadUtils.log("Error in insert_before_last", e)
103
+ end
104
+
105
+ # Insert text in a string or a file after the first occurence of a string.
106
+ # original: the original string or filename
107
+ # tag: occurence of string to find
108
+ # text: string to insert
109
+ # is_file: say if original is a file (default: true) or a string
110
+ def self.insert_after_first(original: nil, tag: nil, text: nil, is_file: true)
111
+ # The new text will be consolidated in content
112
+ content = ""
113
+
114
+ # If coming from a file, read original into content
115
+ if is_file
116
+ content = PadUtils.get_file_content(original)
117
+ else
118
+ content = original
119
+ end
120
+
121
+ # Iterate line by line. If a position is found, insert the text
122
+ # and set found to true to prevent further insertions
123
+ found = false
124
+ new_content = ""
125
+ content.each_line do |line|
126
+ position = line.index(/#{tag}/)
127
+ if position && !found
128
+ new_content += "#{line}#{text}"
129
+ found = true
130
+ else
131
+ new_content += line
132
+ end
133
+ end
134
+
135
+ # If coming from a file, write result in same file. If not,
136
+ # simply return content
137
+ if is_file
138
+ PadUtils.write_to_file(original, new_content)
139
+ return new_content
140
+ else
141
+ return new_content
142
+ end
143
+
144
+ rescue Exception => e
145
+ PadUtils.log("Error in insert_after_first", e)
146
+ end
147
+
148
+ # Insert text in a string or a file after the last occurence of a string.
149
+ # original: the original string or filename
150
+ # tag: occurence of string to find
151
+ # text: string to insert
152
+ # is_file: say if original is a file (default: true) or a string
153
+ def self.insert_after_last(original: nil, tag: nil, text: nil, is_file: true)
154
+ # The new text will be consolidated in content
155
+ content = ""
156
+
157
+ # If coming from a file, read original into content
158
+ if is_file
159
+ content = PadUtils.get_file_content(original)
160
+ else
161
+ content = original
162
+ end
163
+
164
+ # Find the position of tag in the string array and insert the text
165
+ positions = content.enum_for(:scan, /#{tag}/).map { Regexp.last_match.begin(0) }
166
+ content[positions.last + tag.length] = "#{text}"
167
+
168
+ # If coming from a file, write result in same file. If not,
169
+ # simply return content
170
+ if is_file
171
+ PadUtils.write_to_file(original, content)
172
+ return content
173
+ else
174
+ return content
175
+ end
176
+
177
+ rescue Exception => e
178
+ PadUtils.log("Error in insert_after_last", e)
179
+ end
180
+
181
+ end
@@ -0,0 +1,30 @@
1
+ require "time"
2
+
3
+ module PadUtils
4
+
5
+ # Return a string timestamp with the format: YYYYMMDDHHmmss
6
+ def self.time_to_stamp(val)
7
+ val.strftime("%Y%m%d%H%M%S")
8
+ end
9
+
10
+ # Return a Time object from a timestamp with the format: YYYYMMDDHHmmss
11
+ def self.stamp_to_time(val)
12
+ Time.parse "#{val[0..3]}-#{val[4..5]}-#{val[6..7]} #{val[8..9]}:#{val[10..11]}:#{val[12..13]}"
13
+ rescue Exception => e
14
+ PadUtils.log("Error in stamp_to_time", e)
15
+ end
16
+
17
+ # Return a string readable timestamp with format: YYYY-MM-DD HH:mm:ss
18
+ def self.time_to_readable_stamp(val)
19
+ val.strftime("%Y-%m-%d %H:%M:%S")
20
+ end
21
+
22
+ # Return a Time object from a PadUtils readable timestamp
23
+ # with format: YYYY-MM-DD HH:mm:ss
24
+ def self.readable_stamp_to_time(val)
25
+ Time.parse val
26
+ rescue Exception => e
27
+ PadUtils.log("Error in readable_stamp_to_time", e)
28
+ end
29
+
30
+ end
@@ -0,0 +1,3 @@
1
+ module PadUtils
2
+ VERSION = "1.1.1"
3
+ end
data/lib/pad_utils.rb ADDED
@@ -0,0 +1,22 @@
1
+ require_relative "pad_utils/version"
2
+ require_relative "pad_utils/pad_files"
3
+ require_relative "pad_utils/pad_text"
4
+ require_relative "pad_utils/pad_time"
5
+ require_relative "pad_utils/pad_logger"
6
+ require_relative "pad_utils/pad_menu"
7
+ require_relative "pad_utils/pad_json"
8
+
9
+ module PadUtils
10
+ # TODO: Add a cli coloring feature
11
+
12
+ def self.main(arg)
13
+ puts
14
+ puts "PadUtils v.#{PadUtils::VERSION}"
15
+ puts
16
+ puts "Part of the Padstone app builder (http://padstone.io)"
17
+ puts
18
+ puts "Copyright 2016 - Nico Schuele"
19
+ puts "Licensed under the Apache License, Version 2.0"
20
+ puts
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pad_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Nico Schuele
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: PadUtils is a simple gem containing common utilities and shortcuts. It
14
+ is used in the [Padstone](http://padstone.io) app builder but can be embedded in
15
+ any other Ruby project.
16
+ email:
17
+ - help@padstone.io
18
+ executables:
19
+ - padutils
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - bin/padutils
27
+ - lib/pad_utils.rb
28
+ - lib/pad_utils/pad_files.rb
29
+ - lib/pad_utils/pad_json.rb
30
+ - lib/pad_utils/pad_logger.rb
31
+ - lib/pad_utils/pad_menu.rb
32
+ - lib/pad_utils/pad_text.rb
33
+ - lib/pad_utils/pad_time.rb
34
+ - lib/pad_utils/version.rb
35
+ homepage: http://padstone.io
36
+ licenses:
37
+ - Apache-2.0
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 2.5.1
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: PadUtils is a simple gem containing common utilities and shortcuts
59
+ test_files: []