boom 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,14 @@
1
1
  # boom changes
2
2
  ## head
3
+
4
+ ## 0.3.0
5
+ - 0.3 removes all the Storage nonsense in favor of clean and easy JSON. Less
6
+ code is best code.
7
+ - It also removes all the Ruby tests and instead does them in shell with roundup.
8
+ - It also changes delete to use `--delete` so there's conceptually less of a
9
+ problem.
10
+
11
+ ## 0.2.4
3
12
  - [@Dlom](https://github.com/Dlom) fixed some troubles in #49.
4
13
  - Some additional test coverage added by
5
14
  [@nickhammond](https://github.com/nickhammond).
@@ -66,8 +75,8 @@
66
75
  scripts and junk! Thanks [bschaeffer](https://github.com/bschaeffer).
67
76
 
68
77
  ## 0.0.9
69
- - Backport `Symbol#to_proc` for 1.8.6 support (thanks
70
- [kastner](https://github.com/kastner) and
78
+ - Backport `Symbol#to_proc` for 1.8.6 support (thanks
79
+ [kastner](https://github.com/kastner) and
71
80
  [DeMarko](https://github.com/DeMarko)).
72
81
 
73
82
  ## 0.0.8
@@ -81,7 +90,7 @@
81
90
  (thanks [jimmycuadra](https://github.com/jimmycuadra)).
82
91
  - Output is a bit cleaner with a constrained `name` column.
83
92
  - Adds items from stdin (thanks
84
- [MichaelXavier](https://github.com/MichaelXavier)).
93
+ [MichaelXavier](https://github.com/MichaelXavier)).
85
94
 
86
95
  ## 0.0.5
87
96
  - Item deletes are now scoped by list rather than GLOBAL DESTRUCTION! (thanks
data/Gemfile.lock CHANGED
@@ -1,17 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- boom (0.2.3)
5
- json_pure (~> 1.5.3)
6
- multi_json (~> 1.0.3)
4
+ boom (0.2.4)
5
+ yajl-ruby (~> 1.1.0)
7
6
 
8
7
  GEM
9
8
  remote: http://rubygems.org/
10
9
  specs:
11
- json_pure (1.5.3)
12
10
  mocha (0.9.12)
13
- multi_json (1.0.3)
14
11
  rake (0.9.2)
12
+ yajl-ruby (1.1.0)
15
13
 
16
14
  PLATFORMS
17
15
  ruby
File without changes
@@ -2,12 +2,12 @@
2
2
 
3
3
  ## About
4
4
 
5
- boom manages your text snippets. On the command line. I just blew your mind.
5
+ boom manages your text snippets on your command line. You can stash away text
6
+ like URLs, canned responses, and important notes and then quickly copy them
7
+ onto your clipboard, ready for pasting.
6
8
 
7
9
  For more details about what boom is and how it works, check out
8
- [boom's website](http://holman.github.com/boom). For full usage details
9
- (including a complete list of commands), check out
10
- [boom's wiki](https://github.com/holman/boom/wiki).
10
+ [boom's website](http://holman.github.com/boom).
11
11
 
12
12
  ## Install
13
13
 
@@ -18,11 +18,11 @@ For more details about what boom is and how it works, check out
18
18
  $ boom gifs
19
19
  Boom! Created a new list called "gifs".
20
20
 
21
- $ boom gifs melissa http://cl.ly/3pAn/animated.gif
22
- Boom! "melissa" in "gifs" is "http://cl.ly/3pAn/animated.gif". Got it.
21
+ $ boom gifs shirt http://cl.ly/NwCS/shirt.gif
22
+ Boom! "shirt" in "gifs" is "http://cl.ly/NwCS/shirt.gif". Got it.
23
23
 
24
- $ boom melissa
25
- Boom! Just copied http://cl.ly/3pAn/animated.gif to your clipboard.
24
+ $ boom shirt
25
+ Boom! Just copied http://cl.ly/NwCS/shirt.gif to your clipboard.
26
26
 
27
27
  And that's just a taste! I know, you're salivating, I can hear you from here.
28
28
  (Why your saliva is noisy is beyond me.) Check out the [full list of
@@ -37,8 +37,11 @@ your contributions, friend.
37
37
  Clone this repository, then run `bundle install`. That'll install all the gem
38
38
  dependencies. Make sure your methods are [TomDoc](http://tomdoc.org)'d
39
39
  properly, that existing tests pass (`rake`), and that any new functionality
40
- includes appropriate tests. Bonus points if you're not updating the gemspec or
41
- bumping boom's version.
40
+ includes appropriate tests.
41
+
42
+ The tests are written in shell for
43
+ [roundup](https://github.com/bmizerany/roundup), since boom is basically just
44
+ Ruby pretending to be shell. `rake` should run them all for you just fine.
42
45
 
43
46
  All good? Cool! Then [send me a pull request](https://github.com/holman/boom/pull/new/master)!
44
47
 
@@ -48,4 +51,4 @@ All good? Cool! Then [send me a pull request](https://github.com/holman/boom/pul
48
51
  [@holman](http://twitter.com/holman) — if you're having issues, want me to
49
52
  merge in your pull request, or are using boom in a cool way. I'm kind of hoping
50
53
  this is generic enough that people do some fun things with it. First one to use
51
- `boom` to calculate their tax liability wins.
54
+ `boom` to calculate their tax liability wins.
data/Rakefile CHANGED
@@ -45,11 +45,9 @@ end
45
45
 
46
46
  task :default => :test
47
47
 
48
- require 'rake/testtask'
49
- Rake::TestTask.new(:test) do |test|
50
- test.libs << 'lib' << 'test'
51
- test.pattern = 'test/**/test_*.rb'
52
- test.verbose = true
48
+ desc "Run tests for boom"
49
+ task :test do
50
+ exec "test/run"
53
51
  end
54
52
 
55
53
  desc "Open an irb session preloaded with this library"
data/boom.gemspec CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'boom'
16
- s.version = '0.2.4'
17
- s.date = '2013-03-15'
16
+ s.version = '0.3.0'
17
+ s.date = '2013-03-29'
18
18
  s.rubyforge_project = 'boom'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  ## better to set the email to an email list or something. If you don't have
33
33
  ## a custom homepage, consider using your GitHub URL or the like.
34
34
  s.authors = ["Zach Holman"]
35
- s.email = 'github.com@zachholman.com'
35
+ s.email = 'zach@zachholman.com'
36
36
  s.homepage = 'https://github.com/holman/boom'
37
37
 
38
38
  ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
@@ -50,12 +50,11 @@ Gem::Specification.new do |s|
50
50
  ## Specify any RDoc options here. You'll want to add your README and
51
51
  ## LICENSE files to the extra_rdoc_files list.
52
52
  s.rdoc_options = ["--charset=UTF-8"]
53
- s.extra_rdoc_files = %w[README.markdown LICENSE.markdown]
53
+ s.extra_rdoc_files = %w[README.md LICENSE.md]
54
54
 
55
55
  ## List your runtime dependencies here. Runtime dependencies are those
56
56
  ## that are needed for an end user to actually USE your code.
57
- s.add_dependency('multi_json', "~> 1.0.3")
58
- s.add_dependency('json_pure', "~> 1.5.3")
57
+ s.add_dependency('yajl-ruby', "~> 1.1.0")
59
58
 
60
59
  ## List your development dependencies here. Development dependencies are
61
60
  ## those that are only needed during development
@@ -67,11 +66,11 @@ Gem::Specification.new do |s|
67
66
  ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
68
67
  # = MANIFEST =
69
68
  s.files = %w[
70
- CHANGELOG.markdown
69
+ CHANGELOG.md
71
70
  Gemfile
72
71
  Gemfile.lock
73
- LICENSE.markdown
74
- README.markdown
72
+ LICENSE.md
73
+ README.md
75
74
  Rakefile
76
75
  bin/boom
77
76
  boom.gemspec
@@ -81,28 +80,17 @@ Gem::Specification.new do |s|
81
80
  lib/boom.rb
82
81
  lib/boom/color.rb
83
82
  lib/boom/command.rb
84
- lib/boom/config.rb
85
83
  lib/boom/core_ext/symbol.rb
86
84
  lib/boom/item.rb
87
85
  lib/boom/list.rb
88
86
  lib/boom/platform.rb
89
87
  lib/boom/storage.rb
90
- lib/boom/storage/base.rb
91
- lib/boom/storage/gist.rb
92
- lib/boom/storage/json.rb
93
- lib/boom/storage/keychain.rb
94
- lib/boom/storage/mongodb.rb
95
- lib/boom/storage/redis.rb
96
- test/examples/config_json.json
97
- test/examples/test_json.json
98
- test/examples/urls.json
99
- test/helper.rb
100
- test/test_color.rb
101
- test/test_command.rb
102
- test/test_config.rb
103
- test/test_item.rb
104
- test/test_list.rb
105
- test/test_platform.rb
88
+ test/cli.sh
89
+ test/examples/data.json
90
+ test/item.sh
91
+ test/list.sh
92
+ test/roundup
93
+ test/run
106
94
  ]
107
95
  # = MANIFEST =
108
96
 
data/lib/boom/command.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
3
  # Command is the main point of entry for boom commands; shell arguments are
4
- # passd through to Command, which then filters and parses through individual
4
+ # passed through to Command, which then filters and parses through individual
5
5
  # commands and reroutes them to constituent object classes.
6
6
  #
7
7
  # Command also keeps track of one connection to Storage, which is how new data
@@ -87,8 +87,6 @@ module Boom
87
87
  def delegate(command, major, minor)
88
88
  return all if command == 'all'
89
89
  return edit if command == 'edit'
90
- return switch(major) if command == 'switch'
91
- return show_storage if command == 'storage'
92
90
  return version if command == "-v"
93
91
  return version if command == "--version"
94
92
  return help if command == 'help'
@@ -99,16 +97,16 @@ module Boom
99
97
 
100
98
  # if we're operating on a List
101
99
  if storage.list_exists?(command)
102
- return delete_list(command) if major == 'delete'
100
+ return delete_list(command) if major == '--delete'
103
101
  return detail_list(command) unless major
104
- unless minor == 'delete'
102
+ unless minor == '--delete'
105
103
  return add_item(command,major,minor) if minor
106
104
  return add_item(command,major,stdin.read) if stdin.stat.size > 0
107
105
  return search_list_for_item(command, major)
108
106
  end
109
107
  end
110
108
 
111
- if minor == 'delete' and storage.item_exists?(major)
109
+ if minor == '--delete' and storage.item_exists?(major)
112
110
  return delete_item(command, major)
113
111
  end
114
112
 
@@ -118,25 +116,6 @@ module Boom
118
116
  return create_list(command, major, minor)
119
117
  end
120
118
 
121
- # Public: shows the current user's storage.
122
- #
123
- # Returns nothing.
124
- def show_storage
125
- output "You're currently using #{Boom.config.attributes['backend']}."
126
- end
127
-
128
- # Public: switch to a new backend.
129
- #
130
- # backend - the String of the backend desired
131
- #
132
- # Returns nothing.
133
- def switch(backend)
134
- Storage.backend = backend
135
- output "We've switched you over to #{backend}."
136
- rescue NameError
137
- output "We couldn't find that storage engine. Check the name and try again."
138
- end
139
-
140
119
  # Public: prints all Items over a List.
141
120
  #
142
121
  # name - the List object to iterate over
@@ -234,7 +213,7 @@ module Boom
234
213
  #
235
214
  # Returns nothing.
236
215
  def delete_list(name)
237
- output "You sure you want to delete everything in #{yellow(name)}? (y/n):"
216
+ printf "You sure you want to delete everything in #{yellow(name)}? (y/n): "
238
217
  if $stdin.gets.chomp == 'y'
239
218
  List.delete(name)
240
219
  output "#{cyan("Boom!")} Deleted all your #{yellow(name)}."
@@ -336,11 +315,7 @@ module Boom
336
315
  #
337
316
  # Returns nothing.
338
317
  def edit
339
- if storage.respond_to?("json_file")
340
- output "#{cyan("Boom!")} #{Platform.edit(storage.json_file)}"
341
- else
342
- output "This storage backend does not store #{cyan("Boom!")} data on your computer"
343
- end
318
+ output "#{cyan("Boom!")} #{Platform.edit(storage.json_file)}"
344
319
  end
345
320
 
346
321
  # Public: prints all the commands of boom.
@@ -354,12 +329,10 @@ module Boom
354
329
  boom all show all items in all lists
355
330
  boom edit edit the boom JSON file in $EDITOR
356
331
  boom help this help text
357
- boom storage shows which storage backend you're using
358
- boom switch <storage> switches to a different storage backend
359
332
 
360
333
  boom <list> create a new list
361
334
  boom <list> show items for a list
362
- boom <list> delete deletes a list
335
+ boom <list> --delete deletes a list
363
336
 
364
337
  boom <list> <name> <value> create a new list item
365
338
  boom <name> copy item's value to clipboard
@@ -370,7 +343,7 @@ module Boom
370
343
  boom random <list> open a random item's url for a list in browser
371
344
  boom echo <name> echo the item's value without copying
372
345
  boom echo <list> <name> echo the item's value without copying
373
- boom <list> <name> delete deletes an item
346
+ boom <list> <name> --delete deletes an item
374
347
 
375
348
  all other documentation is located at:
376
349
  https://github.com/holman/boom
data/lib/boom/item.rb CHANGED
@@ -6,7 +6,6 @@
6
6
  #
7
7
  module Boom
8
8
  class Item
9
-
10
9
  # Public: the String name of the Item
11
10
  attr_accessor :name
12
11
 
@@ -54,7 +53,7 @@ module Boom
54
53
  end
55
54
 
56
55
  # Public: only return url part of value - if no url has been
57
- # detected returns value.
56
+ # detected it'll return the value.
58
57
  #
59
58
  # Returns a String which preferably is a URL.
60
59
  def url
@@ -67,6 +66,5 @@ module Boom
67
66
  def to_hash
68
67
  { @name => @value }
69
68
  end
70
-
71
69
  end
72
- end
70
+ end
data/lib/boom/list.rb CHANGED
@@ -81,7 +81,7 @@ module Boom
81
81
  #
82
82
  # name - String name of the Item to find
83
83
  #
84
- # Returns the found item
84
+ # Returns the found item.
85
85
  def find_item(name)
86
86
  items.find do |item|
87
87
  item.name == name ||
data/lib/boom/storage.rb CHANGED
@@ -1,22 +1,124 @@
1
- # coding: utf-8
2
-
3
1
  #
4
2
  # Storage is the interface between multiple Backends. You can use Storage
5
3
  # directly without having to worry about which Backend is in use.
6
4
  #
7
5
  module Boom
8
- module Storage
9
-
10
- def self.backend=(backend)
11
- backend = backend.capitalize
12
- Boom::Storage.const_get(backend)
13
- Boom.config.attributes['backend'] = backend.downcase
14
- Boom.config.save
6
+ class Storage
7
+ JSON_FILE = "#{ENV['HOME']}/.boom"
8
+
9
+ # Public: the path to the Json file used by boom.
10
+ #
11
+ # Returns the String path of boom's Json representation.
12
+ def json_file
13
+ ENV['BOOMFILE'] || JSON_FILE
14
+ end
15
+
16
+ # Public: initializes a Storage instance by loading in your persisted data from adapter.
17
+ #
18
+ # Returns the Storage instance.
19
+ def initialize
20
+ @lists = []
21
+ bootstrap
22
+ populate
23
+ end
24
+
25
+ # Public: the in-memory collection of all Lists attached to this Storage
26
+ # instance.
27
+ #
28
+ # lists - an Array of individual List items
29
+ #
30
+ # Returns nothing.
31
+ attr_writer :lists
32
+
33
+ # Public: the list of Lists in your JSON data, sorted by number of items
34
+ # descending.
35
+ #
36
+ # Returns an Array of List objects.
37
+ def lists
38
+ @lists.sort_by { |list| -list.items.size }
39
+ end
40
+
41
+ # Public: tests whether a named List exists.
42
+ #
43
+ # name - the String name of a List
44
+ #
45
+ # Returns true if found, false if not.
46
+ def list_exists?(name)
47
+ @lists.detect { |list| list.name == name }
48
+ end
49
+
50
+ # Public: all Items in storage.
51
+ #
52
+ # Returns an Array of all Items.
53
+ def items
54
+ @lists.collect(&:items).flatten
15
55
  end
16
56
 
17
- def self.backend
18
- Boom::Storage.const_get(Boom.config.attributes['backend'].capitalize).new
57
+ # Public: tests whether a named Item exists.
58
+ #
59
+ # name - the String name of an Item
60
+ #
61
+ # Returns true if found, false if not.
62
+ def item_exists?(name)
63
+ items.detect { |item| item.name == name }
19
64
  end
20
65
 
66
+ # Public: creates a Hash of the representation of the in-memory data
67
+ # structure. This percolates down to Items by calling to_hash on the List,
68
+ # which in tern calls to_hash on individual Items.
69
+ #
70
+ # Returns a Hash of the entire data set.
71
+ def to_hash
72
+ { :lists => lists.collect(&:to_hash) }
73
+ end
74
+
75
+ # Takes care of bootstrapping the Json file, both in terms of creating the
76
+ # file and in terms of creating a skeleton Json schema.
77
+ #
78
+ # Return true if successfully saved.
79
+ def bootstrap
80
+ return if File.exist?(json_file)
81
+ FileUtils.touch json_file
82
+ File.open(json_file, 'w') {|f| f.write(to_json) }
83
+ save
84
+ end
85
+
86
+ # Take a JSON representation of data and explode it out into the consituent
87
+ # Lists and Items for the given Storage instance.
88
+ #
89
+ # Returns nothing.
90
+ def populate
91
+ file = File.new(json_file, 'r')
92
+ storage = Yajl::Parser.parse(file)
93
+
94
+ storage['lists'].each do |lists|
95
+ lists.each do |list_name, items|
96
+ @lists << list = List.new(list_name)
97
+
98
+ items.each do |item|
99
+ item.each do |name,value|
100
+ list.add_item(Item.new(name,value))
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ # Public: persists your in-memory objects to disk in Json format.
108
+ #
109
+ # lists_Json - list in Json format
110
+ #
111
+ # Returns true if successful, false if unsuccessful.
112
+ def save
113
+ File.open(json_file, 'w') {|f| f.write(to_json) }
114
+ end
115
+
116
+ # Public: the Json representation of the current List and Item assortment
117
+ # attached to the Storage instance.
118
+ #
119
+ # Returns a String Json representation of its Lists and their Items.
120
+ def to_json
121
+ Yajl::Encoder.encode(to_hash, :pretty => true)
122
+ end
21
123
  end
22
- end
124
+ end
data/lib/boom.rb CHANGED
@@ -6,38 +6,23 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  require 'fileutils'
9
- require 'multi_json'
9
+ require 'yajl'
10
10
 
11
11
  $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
12
12
 
13
13
  require 'boom/color'
14
14
  require 'boom/platform'
15
15
  require 'boom/command'
16
- require 'boom/config'
17
16
  require 'boom/item'
18
17
  require 'boom/list'
19
-
20
18
  require 'boom/storage'
21
- require 'boom/storage/base'
22
- require 'boom/storage/json'
23
- require 'boom/storage/redis'
24
- require 'boom/storage/mongodb'
25
- require 'boom/storage/keychain'
26
- require 'boom/storage/gist'
27
19
 
28
20
  require 'boom/core_ext/symbol'
29
21
 
30
22
  module Boom
31
- VERSION = '0.2.4'
32
-
33
- extend self
34
-
35
- def storage
36
- @storage ||= Boom::Storage.backend
37
- end
23
+ VERSION = '0.3.0'
38
24
 
39
- def config
40
- @config ||= Boom::Config.new
25
+ def self.storage
26
+ @storage ||= Storage.new
41
27
  end
42
-
43
- end
28
+ end
data/test/cli.sh ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env roundup
2
+ export BOOMFILE=test/examples/data.json
3
+ boom="./bin/boom"
4
+
5
+ describe "cli"
6
+
7
+ it_shows_help() {
8
+ $boom help | grep "boom: help"
9
+ }
10
+
11
+ it_shows_a_version() {
12
+ $boom --version | grep "running boom"
13
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "lists": [
3
+ {
4
+ "urls": [
5
+ { "blog": "https://github.com/holman" },
6
+ { "twitter": "https://twitter.com/holman"},
7
+ { "site": "http://zachholman.com"}
8
+ ]
9
+ },
10
+ {
11
+ "jokes": [
12
+ { "none": "What do you call a cow with no legs? Ground beef." },
13
+ { "three": "What do you call a cow with three legs? Lean beef." }
14
+ ]
15
+ }
16
+ ]
17
+ }
data/test/item.sh ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env roundup
2
+ export BOOMFILE=test/examples/data.json
3
+ boom="./bin/boom"
4
+
5
+ describe "items"
6
+
7
+ it_adds_an_item() {
8
+ $boom urls google 'http://google.com'
9
+ $boom urls | grep google.com
10
+ }
11
+
12
+ it_deletes_an_item() {
13
+ yes | $boom urls google --delete | grep 'gone forever'
14
+ $boom urls google | grep 'not found'
15
+ }
16
+
17
+ it_echos_an_item() {
18
+ $boom echo site | grep 'zachholman.com'
19
+ }
data/test/list.sh ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env roundup
2
+ export BOOMFILE=test/examples/data.json
3
+ boom="./bin/boom"
4
+
5
+ describe "lists"
6
+
7
+ it_shows_all_lists_by_default() {
8
+ $boom | grep "urls"
9
+ $boom | grep "jokes"
10
+ }
11
+
12
+ it_adds_a_list() {
13
+ $boom enemies | grep "Created a new list"
14
+ $boom | grep "enemies (0)"
15
+ }
16
+
17
+ it_adds_a_list_with_a_duplicate_name() {
18
+ $boom urls github 'http://github.com/about'
19
+ $boom github | grep '/about'
20
+ }
21
+
22
+ it_shows_a_list() {
23
+ $boom urls | grep 'zachholman'
24
+ }
25
+
26
+ it_deletes_a_list() {
27
+ $boom | grep "enemies"
28
+ yes | $boom enemies --delete | grep "Deleted"
29
+ ! $boom | grep "enemies"
30
+ }