Blux 0.0.4 → 0.0.5

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.
data.tar.gz.sig CHANGED
Binary file
@@ -2,18 +2,18 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{Blux}
5
- s.version = "0.0.4"
5
+ s.version = "0.0.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Louis Salin"]
9
9
  s.cert_chain = ["/home/louis/Documents/gem_keys/gem-public_cert.pem"]
10
- s.date = %q{2010-10-23}
10
+ s.date = %q{2010-11-06}
11
11
  s.default_executable = %q{blux}
12
12
  s.description = %q{An offline blog manager}
13
13
  s.email = %q{louis.phil@gmail.com}
14
14
  s.executables = ["blux"]
15
- s.extra_rdoc_files = ["COPYING", "README.markdown", "bin/blux", "lib/textile_to_html.rb", "lib/wp_publish.rb", "lib/blog_manager.rb", "lib/blux_config_reader.rb", "lib/blux_option_parser.rb", "lib/draft_manager.rb", "lib/indexer.rb"]
16
- s.files = ["COPYING", "Manifest", "README.markdown", "Rakefile", "bin/blux", "lib/textile_to_html.rb", "lib/wp_publish.rb", "lib/blog_manager.rb", "lib/blux_config_reader.rb", "lib/blux_option_parser.rb", "lib/draft_manager.rb", "lib/indexer.rb", "spec/blog_manager_spec.rb", "spec/blux_config_reader_spec.rb", "spec/draft_manager_spec.rb", "Blux.gemspec"]
15
+ s.extra_rdoc_files = ["COPYING", "README.markdown", "bin/blux", "lib/textile_to_html.rb", "lib/blog_manager.rb", "lib/blux_config_reader.rb", "lib/blux_option_parser.rb", "lib/draft_manager.rb", "lib/indexer.rb", "lib/publishing/wp_publish.rb", "lib/publishing/wp_options.rb"]
16
+ s.files = ["COPYING", "Manifest", "README.markdown", "Rakefile", "bin/blux", "lib/textile_to_html.rb", "lib/blog_manager.rb", "lib/blux_config_reader.rb", "lib/blux_option_parser.rb", "lib/draft_manager.rb", "lib/indexer.rb", "lib/publishing/wp_publish.rb", "lib/publishing/wp_options.rb", "spec/blog_manager_spec.rb", "spec/blux_config_reader_spec.rb", "spec/draft_manager_spec.rb", "Blux.gemspec"]
17
17
  s.homepage = %q{http://github.com/louissalin/blux}
18
18
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Blux", "--main", "README.markdown"]
19
19
  s.require_paths = ["lib"]
data/Manifest CHANGED
@@ -4,12 +4,13 @@ README.markdown
4
4
  Rakefile
5
5
  bin/blux
6
6
  lib/textile_to_html.rb
7
- lib/wp_publish.rb
8
7
  lib/blog_manager.rb
9
8
  lib/blux_config_reader.rb
10
9
  lib/blux_option_parser.rb
11
10
  lib/draft_manager.rb
12
11
  lib/indexer.rb
12
+ lib/publishing/wp_publish.rb
13
+ lib/publishing/wp_options.rb
13
14
  spec/blog_manager_spec.rb
14
15
  spec/blux_config_reader_spec.rb
15
16
  spec/draft_manager_spec.rb
@@ -74,5 +74,17 @@ use this command to edit a draft
74
74
 
75
75
  when using the --verbose option, Blux will output a lot of extra information to the screen as it works
76
76
 
77
+ > $ blux -p (--publish) [--latest, --title <a title>, --file <filename>]
78
+
79
+ this command will publish your draft. It will publish either the latest draft, or a draft with a specific title, or a draft with a specific filename, as specified in the command.
80
+
81
+ > $ blux -u (--update) [--latest, --title <a title>, --file <filename>]
82
+
83
+ this command will update an exisiting published blog post. It will update either the latest draft, or a draft with a specific title, or a draft with a specific filename, as specified in the command.
84
+
85
+ > $ blux -d (--delete) [--latest, --title <a title>, --file <filename>]
86
+
87
+ this command will delete a published blog post and mark the associated draft as deleted. The draft will still exist, but Blux will not take it into consideration anymore.
88
+
77
89
  ## community
78
90
  feel free to post your comments or questions to the Blux Google group here: blux_manager@googlegroups.com
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('Blux', '0.0.4') do |p|
5
+ Echoe.new('Blux', '0.0.5') do |p|
6
6
  p.description = 'An offline blog manager'
7
7
  p.url = 'http://github.com/louissalin/blux'
8
8
  p.author = 'Louis Salin'
data/bin/blux CHANGED
@@ -57,6 +57,43 @@ def check_filename(options, blog_manager)
57
57
  end
58
58
  end
59
59
 
60
+ def build_post_info(options)
61
+ switch = nil
62
+ entry = Array.new
63
+ response = Array.new
64
+ url = ""
65
+
66
+ ARGF.each do |line|
67
+ if line == "--entry--\n"
68
+ switch = :entry
69
+ next
70
+ elsif line == "--response--\n"
71
+ switch = :response
72
+ next
73
+ elsif line == "--url--\n"
74
+ switch = :url
75
+ next
76
+ end
77
+
78
+ case (switch)
79
+ when :entry
80
+ entry << line
81
+ when :response
82
+ response << line
83
+ when :url
84
+ url = line
85
+ end
86
+ end
87
+
88
+ entry_text = entry.join
89
+ response_text = response.join
90
+
91
+ msg = "Error communicating with the publishing script. Exiting..."
92
+ raise RuntimeError, msg if response.length == 0
93
+
94
+ return entry, response, url
95
+ end
96
+
60
97
  begin
61
98
  validate_command(BluxOptionParser.parse(ARGV)) do |options|
62
99
  draft_manager = DraftManager.new
@@ -84,6 +121,10 @@ begin
84
121
  mgr.draft_manager.set_attribute(filename, attribute, value)
85
122
  end
86
123
  end
124
+ when :unset
125
+ check_filename(options, mgr) do |filename|
126
+ mgr.draft_manager.delete_attribute(filename, options.attribute)
127
+ end
87
128
  when :out
88
129
  check_filename(options, mgr) do |filename|
89
130
  STDOUT.puts(mgr.draft_manager.output filename)
@@ -103,47 +144,42 @@ begin
103
144
  puts "updating" if options.verbose
104
145
  mgr.update filename
105
146
  end
106
- when :set_edit_url
147
+ when :delete
107
148
  check_filename(options, mgr) do |filename|
108
- switch = nil
109
- entry = Array.new
110
- response = Array.new
111
- url = ""
112
-
113
- ARGF.each do |line|
114
- if line == "--entry--\n"
115
- switch = :entry
116
- next
117
- elsif line == "--response--\n"
118
- switch = :response
119
- next
120
- elsif line == "--url--\n"
121
- switch = :url
122
- next
123
- end
124
-
125
- case (switch)
126
- when :entry
127
- entry << line
128
- when :response
129
- response << line
130
- when :url
131
- url = line
132
- end
149
+ puts "deleting" if options.verbose
150
+ mgr.delete filename
151
+ end
152
+ when :show_post_info
153
+ entry, response, url = build_post_info(options)
154
+ if options.verbose
155
+ puts "entry:"
156
+ puts entry
157
+
158
+ puts "response:"
159
+ puts response
160
+
161
+ puts "edit url:"
162
+ puts url
133
163
  end
164
+ when :set_edit_url
165
+ check_filename(options, mgr) do |filename|
166
+ entry, response, url = build_post_info(options)
167
+
168
+ if options.verbose
169
+ puts "entry:"
170
+ puts entry
134
171
 
135
- entry_text = entry.join
136
- puts "entry:" if options.verbose
137
- puts entry_text if options.verbose
172
+ puts "response:"
173
+ puts response
174
+
175
+ puts "edit url:"
176
+ puts url
177
+ end
138
178
 
139
- response_text = response.join
140
- puts "response:" if options.verbose
141
- puts response_text if options.verbose
142
-
143
- mgr.set_attribute(filename, 'edit_url', url.strip)
179
+ mgr.draft_manager.set_attribute(filename, 'edit_url', url.strip)
144
180
  end
145
181
  when :version
146
- puts "0.0.4"
182
+ puts "0.0.5"
147
183
  end
148
184
  end
149
185
  rescue
@@ -19,13 +19,12 @@
19
19
  require "#{File.dirname(__FILE__)}/draft_manager"
20
20
  require "#{File.dirname(__FILE__)}/blux_config_reader"
21
21
  require "#{File.dirname(__FILE__)}/indexer"
22
+ require 'timeout'
22
23
 
23
24
  class BlogManager
24
25
  attr_accessor :home, :blux_dir, :blux_rc, :blux_tmp_dir, :draft_dir
25
26
  attr_accessor :draft_manager
26
27
  attr_accessor :config
27
- attr_accessor :index
28
- attr_accessor :index_file
29
28
 
30
29
  include BluxIndexer
31
30
 
@@ -38,7 +37,6 @@ class BlogManager
38
37
  @draft_dir = "#{@blux_dir}/draft"
39
38
  @blux_tmp_dir = "#{@blux_dir}/tmp"
40
39
  @blux_rc = "#{@home}/.bluxrc"
41
- @index_file = "#{@blux_dir}/.published"
42
40
 
43
41
  @draft_manager = draft_manager
44
42
  end
@@ -55,10 +53,6 @@ class BlogManager
55
53
  unless Dir.exists?(@blux_tmp_dir)
56
54
  Dir.mkdir(@blux_tmp_dir)
57
55
  end
58
-
59
- load_index
60
- puts "blog index:\n" if @verbose
61
- print_index if @verbose
62
56
  end
63
57
 
64
58
  def load_config
@@ -69,48 +63,71 @@ class BlogManager
69
63
  end
70
64
 
71
65
  def publish(filename)
66
+ raise "this draft has already been published" if published?(filename)
67
+
72
68
  title = @draft_manager.get_attribute(filename, "title") || 'no title'
69
+ categories = @draft_manager.get_attribute(filename, "categories")
73
70
 
74
71
  convert_cmd = "blux --convert -f #{filename}"
75
- publish_cmd = "ruby #{File.dirname(__FILE__)}/wp_publish.rb -t \"#{title}\" --config #{@blux_rc}"
72
+ categories_cmd = categories ? "-c \"#{categories}\"" : ""
73
+ publish_cmd = "ruby #{File.dirname(__FILE__)}/publishing/wp_publish.rb -t \"#{title}\" --config #{@blux_rc} #{categories_cmd}"
76
74
  set_url_cmd = "blux --set_edit_url -f #{filename}"
77
75
 
78
76
  cmd = "#{convert_cmd} | #{publish_cmd} | #{set_url_cmd}"
79
77
  cmd = cmd + " --verbose" if @verbose
80
78
 
81
- if system cmd
82
- load_index
83
- set_attribute(filename, :published_time, Time.now)
84
- else
85
- msg = "failed to publish...\n"
86
- msg = msg + ' use the --verbose option for more information' if !@verbose
87
-
88
- raise SystemExit, msg
79
+ send_publish_command(cmd, filename, "failed to publish...") do
80
+ @draft_manager.set_attribute(filename, "published_time", Time.now)
89
81
  end
90
-
91
- puts "blog index:\n" if @verbose
92
- print_index if @verbose
93
82
  end
94
83
 
95
84
  def update(filename)
96
85
  title = @draft_manager.get_attribute(filename, "title") || 'no title'
97
- url = get_attribute(filename, "edit_url")
86
+ categories = @draft_manager.get_attribute(filename, "categories")
87
+ url = @draft_manager.get_attribute(filename, "edit_url")
88
+
89
+ raise "couldn't find an edit url for the draft: #{filename}" unless url
90
+
91
+ publish_cmd = "ruby #{File.dirname(__FILE__)}/publishing/wp_publish.rb"
92
+ categories_cmd = categories ? "-c \"#{categories}\"" : ""
93
+ post_cmd = "blux --post-cmd"
94
+ cmd = "blux --convert -f #{filename} | #{publish_cmd} -t \"#{title}\" --update #{url} --config #{@blux_rc} #{categories_cmd} | #{post_cmd}"
95
+ cmd = cmd + " --verbose" if @verbose
98
96
 
97
+ send_publish_command(cmd, filename, "failed to update...") do
98
+ @draft_manager.set_attribute(filename, "published_time", Time.now)
99
+ end
100
+ end
101
+
102
+ def delete(filename)
103
+ url = @draft_manager.get_attribute(filename, "edit_url")
99
104
  raise "couldn't find an edit url for the draft: #{filename}" unless url
100
105
 
101
- publish_cmd = "ruby #{File.dirname(__FILE__)}/wp_publish.rb"
102
- cmd = "blux --convert -f #{filename} | #{publish_cmd} -t \"#{title}\" --update #{url} --config #{@blux_rc}"
106
+ publish_cmd = "ruby #{File.dirname(__FILE__)}/publishing/wp_publish.rb"
107
+ post_cmd = "blux --post-cmd"
108
+ cmd = "#{publish_cmd} --delete #{url} --config #{@blux_rc} | #{post_cmd}"
109
+ cmd = cmd + " --verbose" if @verbose
103
110
 
104
- if system cmd
105
- set_attribute(filename, :published_time, Time.now)
111
+ send_publish_command(cmd, filename, "failed to delete...") do
112
+ @draft_manager.delete_draft(filename)
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def published?(filename)
119
+ @draft_manager.get_attribute(filename, "published_time") != nil
120
+ end
121
+
122
+ def send_publish_command(cmd, filename, error_msg)
123
+ status = Timeout::timeout(10) { system cmd }
124
+ if status
125
+ yield
106
126
  else
107
- msg = "failed to update...\n"
127
+ msg = "#{error_msg}\n"
108
128
  msg = msg + ' use the --verbose option for more information' if !@verbose
109
129
 
110
130
  raise SystemExit, msg
111
131
  end
112
-
113
- puts "blog index:\n" if @verbose
114
- print_index if @verbose
115
132
  end
116
133
  end
@@ -44,6 +44,11 @@ class BluxOptionParser
44
44
  opts.on("-s", "--set", "set an attribute on a draft") do
45
45
  options.command = :set
46
46
  end
47
+
48
+ opts.on("--unset ATTR", "delete an attribute on a draft") do |attr|
49
+ options.command = :unset
50
+ options.attribute = attr
51
+ end
47
52
 
48
53
  opts.on("-c", "--convert", "convert a draft to html") do
49
54
  options.command = :convert
@@ -61,6 +66,10 @@ class BluxOptionParser
61
66
  options.command = :update
62
67
  end
63
68
 
69
+ opts.on("-d", "--delete", "mark a draft as deleted") do
70
+ options.command = :delete
71
+ end
72
+
64
73
  opts.on("--latest", "work on the latest draft") do
65
74
  options.use_latest = true
66
75
  end
@@ -78,6 +87,10 @@ class BluxOptionParser
78
87
  options.command = :set_edit_url
79
88
  end
80
89
 
90
+ opts.on("--post-cmd", "shows post publishing info: request & response") do
91
+ options.command = :show_post_info
92
+ end
93
+
81
94
  opts.on("--with-preview", "show a preview of each draft while listing") do
82
95
  options.list_preview = true
83
96
  end
@@ -25,7 +25,6 @@ require "#{File.dirname(__FILE__)}/indexer"
25
25
  class DraftManager
26
26
  attr_reader :launch_editor_cmd
27
27
  attr_reader :temp_dir, :draft_dir
28
- attr_reader :index
29
28
  attr_reader :index_file
30
29
 
31
30
  include BluxIndexer
@@ -42,7 +41,6 @@ class DraftManager
42
41
  value = system "touch #{@index_file}" unless File.exists? @index_file
43
42
 
44
43
  if value
45
- load_index
46
44
  print_index if @verbose
47
45
  else
48
46
  msg = 'could not create the draft index file'
@@ -69,8 +67,7 @@ class DraftManager
69
67
  def move_temp_file(tempfile)
70
68
  if system "mv #{tempfile} #{@draft_dir}"
71
69
  index_key = File.basename(tempfile)
72
- @index[index_key] = {:creation_time => Time.now.to_s}
73
- save_index
70
+ set_attribute(index_key, "creation_time", Time.now.to_s)
74
71
  else
75
72
  msg = "failed to move the temp file to the draft folder"
76
73
  raise RuntimeError, msg
@@ -90,12 +87,24 @@ class DraftManager
90
87
  print_index if @verbose
91
88
  end
92
89
 
90
+ def delete_draft(filename)
91
+ set_attribute(filename, "deleted", Time.now.to_s)
92
+ print_index if @verbose
93
+ end
94
+
93
95
  def list
94
- Dir.entries(@draft_dir).reject {|i| i[0] == '.'}
96
+ block = Enumerator.new do |g|
97
+ index = load_index
98
+ index.keys.each do |k|
99
+ g << k if index[k]["deleted"] == nil
100
+ end
101
+ end
102
+
103
+ block
95
104
  end
96
105
 
97
106
  def show_info(filename)
98
- check_index(filename) do |index|
107
+ check_index(filename) do |full_index, index|
99
108
  index.to_json
100
109
  end
101
110
  end
@@ -114,6 +123,7 @@ class DraftManager
114
123
  end
115
124
 
116
125
  def output(filename)
126
+ ensure_not_deleted filename
117
127
  check_filename(filename) do |draft_filename|
118
128
  File.open(draft_filename, 'r') do |f|
119
129
  if f.eof?
@@ -132,7 +142,10 @@ class DraftManager
132
142
 
133
143
  def get_latest_created_draft
134
144
  check_count do
135
- @index.sort do |a,b|
145
+ index = load_index
146
+ index.reject do |key, val|
147
+ val["deleted"] != nil
148
+ end.sort do |a,b|
136
149
  Time.parse(a[1]["creation_time"]) <=> Time.parse(b[1]["creation_time"])
137
150
  end[-1][0]
138
151
  end
@@ -140,8 +153,9 @@ class DraftManager
140
153
 
141
154
  def get_draft_by_title(title)
142
155
  check_count do
143
- @index.keys.each do |key|
144
- draft_title = @index[key]["title"]
156
+ index = load_index
157
+ index.keys.each do |key|
158
+ draft_title = index[key]["title"]
145
159
  return key if draft_title == title
146
160
  end
147
161
  end
@@ -19,11 +19,12 @@
19
19
  module BluxIndexer
20
20
  def check_index(filename)
21
21
  check_filename(filename) do
22
- @index[filename] ||= {}
23
- yield @index[filename]
22
+ full_index = load_index
23
+ full_index[filename] ||= {}
24
+ yield full_index, full_index[filename]
24
25
  end
25
26
  end
26
-
27
+
27
28
  def check_filename(filename)
28
29
  draft_filename = "#{self.draft_dir}/#{filename}"
29
30
 
@@ -35,48 +36,80 @@ module BluxIndexer
35
36
  end
36
37
  end
37
38
 
38
- def check_title(filename, attr_key, attr_val)
39
- return true unless attr_key.to_s == "title"
40
-
41
- unique_title = true
42
- @index.keys.reject{|k| k == filename}.each do |key|
43
- unique_title = false if (@index[key][attr_key.to_s] == attr_val)
44
- end
45
-
46
- STDERR << "warning: title '#{attr_val}' is not unique\n" unless unique_title
47
- true
48
- end
49
-
50
39
  def set_attribute(filename, key, val)
51
- check_index(filename) do |index|
52
- if check_title(filename, key, val)
40
+ check_index(filename) do |full_index, index|
41
+ case key
42
+ when "title"
43
+ unique_title = true
44
+ full_index.keys.reject{|k| k == filename}.each do |other_key|
45
+ unique_title = false if (full_index[other_key.to_s][key] == val)
46
+ end
47
+
48
+ STDERR << "warning: title '#{val}' is not unique\n" unless unique_title
49
+
50
+ index[key.to_s] = val
51
+ when "categories"
52
+ values = Array.new
53
+ values << index[key.to_s] unless index[key.to_s] == nil
54
+ values << val
55
+
56
+ index[key.to_s] = values.join(',')
57
+ else
53
58
  index[key.to_s] = val
54
- save_index
55
59
  end
60
+
61
+ save_index(full_index)
56
62
  end
57
63
  end
58
64
 
59
65
  def delete_attribute(filename, attr_name)
60
- check_index(filename) do |index|
61
- index.delete(attr_name.to_s)
62
- save_index
66
+ check_index(filename) do |full_index, index|
67
+ case attr_name
68
+ when "categories"
69
+ if block_given?
70
+ categories = yield
71
+ categories_to_remove = categories.split(',')
72
+
73
+ values = index[attr_name.to_s].split(',')
74
+
75
+ new_values = values.reject{|i| categories_to_remove.include?(i)}.join(',')
76
+
77
+ if new_values.length > 0
78
+ index[attr_name.to_s] = new_values
79
+ else
80
+ index.delete(attr_name.to_s)
81
+ end
82
+ else
83
+ index.delete(attr_name.to_s)
84
+ end
85
+ else
86
+ index.delete(attr_name.to_s)
87
+ end
88
+
89
+ save_index(full_index)
63
90
  end
64
91
  end
65
92
 
66
93
  def get_attribute(filename, attribute)
67
- check_index(filename) do |index|
94
+ check_index(filename) do |full_index, index|
68
95
  index[attribute]
69
96
  end
70
97
  end
71
98
 
72
99
  def check_count
73
- if @index.keys.length > 0
100
+ index = load_index
101
+ if index.keys.length > 0
74
102
  yield
75
103
  else
76
104
  msg = "there is currently no saved index"
77
105
  raise RuntimeError, msg
78
106
  end
79
107
  end
108
+
109
+ def delete_index(filename)
110
+ index = load_index
111
+ save_index if index.delete filename
112
+ end
80
113
 
81
114
  def load_index
82
115
  system "touch #{@index_file}" unless File.exists? @index_file
@@ -86,16 +119,24 @@ module BluxIndexer
86
119
  f.each_line {|l| str += l}
87
120
  end
88
121
 
89
- @index = str.length > 0 ? JSON.parse(str) : {}
122
+ return str.length > 0 ? JSON.parse(str) : {}
90
123
  end
91
124
 
92
- def save_index
125
+ def save_index(index)
93
126
  File.open(@index_file, 'w') do |f|
94
- f.write(@index.to_json) if @index
127
+ f.write(index.to_json) if index
95
128
  end
96
129
  end
97
130
 
98
131
  def print_index
99
- puts @index.to_json + "\n" if @verbose
132
+ index = load_index
133
+ puts index.to_json + "\n" if @verbose
134
+ end
135
+
136
+ def ensure_not_deleted(filename)
137
+ check_index(filename) do |full_index, index|
138
+ msg = "draft filename #{filename} has been deleted"
139
+ raise RuntimeError, msg if index["deleted"]
140
+ end
100
141
  end
101
142
  end