runeblog 0.0.45 → 0.0.48

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f1e459ba25edc955fe31efb2e59f314c3049347c
4
- data.tar.gz: 5eb31fa2ca94d0caa3980fb846a90ba8bad6ecbf
3
+ metadata.gz: acf9dddd4d4831cf3be7477a5dfa9835cf9bc02f
4
+ data.tar.gz: 4a55905bf1eaf9b00b3aa0cdcf17d352c99a3108
5
5
  SHA512:
6
- metadata.gz: ea2bf26873cceedfc76cf85f8ac8721b8140877aa33781f8b2b9ecfcd5e4f81505528a4e2cf32cfc2cc63abde263778842bf692092de56aff79352018e8fcd42
7
- data.tar.gz: e2c050a292b68017a1ec0bbd5bbb97bae042ca7bc9f2c414e9b608b89d24f52e5e4c089d3ab6ab0635eee228ae10df7cc804a2de1d809a528d2469a60541d128
6
+ metadata.gz: e5a6c7faf63b9e3564df736b747637d7f0d2256cf8f1f59a660fb268151151b7dfd26161e159b5bb89dcd5b2d2768a3e0ff64ccd2efce2b8ceeb7ec22ba3302e
7
+ data.tar.gz: 2ac106c905e58b85948a2adb85b636a0bb9e1ca72bee6d2bf192b83a214508cb34a680211aaf2ae1b5d28227edcb93c8c9223948ad5771ede2ef979ad064c945
data/bin/blog CHANGED
@@ -22,28 +22,25 @@ STDOUT.sync = true
22
22
 
23
23
  cmd, arg = get_argv
24
24
 
25
- read_config
25
+ open_blog
26
26
 
27
27
  puts red("\n RuneBlog v #{RuneBlog::VERSION}")
28
28
 
29
29
  if cmd.nil? # REPL
30
30
  puts
31
31
  loop do
32
- print red("blog> ")
33
- begin
34
- cmd = gets.chomp
35
- meth, params = Command.choose_method(cmd)
36
- rescue => err
37
- puts err
38
- next
39
- end
32
+ print red("\nblog> ")
33
+ cmd = gets
34
+ cmd_quit([]) if cmd.nil? # ^D
35
+ cmd.chomp!
36
+ meth, params = RuneBlog::Command.choose_method(cmd)
40
37
  send(meth, params)
41
38
  end
42
39
  else # one command
43
40
  raise "Not working right now"
44
41
  file = File.open("/dev/tty")
45
42
  STDIN.reopen(file) # avoid ARGF dumbness
46
- meth, params = Command.choose_method(cmd)
43
+ meth, params = RuneBlog::Command.choose_method(cmd)
47
44
  parse_cmd(ARGV.join(" "))
48
45
  execute_command
49
46
  end
data/data/VERSION CHANGED
@@ -1 +1 @@
1
- RuneBlog v 0.0.45 2018-08-27
1
+ RuneBlog v 0.0.48 2018-08-30
File without changes
data/lib/blogcmds.rb CHANGED
@@ -1,12 +1,11 @@
1
- # help
2
- # list views
3
- # new view $viewname
4
-
5
- class Command
1
+ class RuneBlog::Command
6
2
  Patterns =
7
3
  {"help" => :cmd_help,
8
4
  "h" => :cmd_help,
9
5
 
6
+ "version" => :cmd_version,
7
+ "v" => :cmd_version,
8
+
10
9
  "list views" => :cmd_list_views,
11
10
  "lsv" => :cmd_list_views,
12
11
 
@@ -16,8 +15,9 @@ class Command
16
15
  "p" => :cmd_new_post,
17
16
  "post" => :cmd_new_post,
18
17
 
19
- "change view $name" => :cmd_change_views,
20
- "cv $name" => :cmd_change_views,
18
+ "change view $name" => :cmd_change_view,
19
+ "cv $name" => :cmd_change_view,
20
+ "cv" => :cmd_change_view, # 0-arity must come second
21
21
 
22
22
  "list posts" => :cmd_list_posts,
23
23
  "lsp" => :cmd_list_posts,
@@ -56,12 +56,13 @@ class Command
56
56
  rx = Regexp.new(rx)
57
57
  Regexes[rx] = meth
58
58
  end
59
-
59
+
60
60
  def self.choose_method(cmd)
61
61
  found = nil
62
62
  params = []
63
63
  Regexes.each_pair do |rx, meth|
64
64
  m = cmd.match(rx)
65
+ # puts "#{rx} =~ #{cmd.inspect} --> #{m.to_a.inspect}"
65
66
  result = m ? m.to_a : nil
66
67
  next unless result
67
68
  found = meth
@@ -73,23 +74,3 @@ class Command
73
74
  end
74
75
  end
75
76
 
76
- # test_cmds = [
77
- # "fake cmd foo bar",
78
- # "help",
79
- # "h",
80
- # "list views",
81
- # "lsv",
82
- # "new view foo",
83
- # "not valid",
84
- # "help invalid",
85
- # "new view",
86
- # "new view too many args"]
87
- #
88
- # loop do
89
- # print "\nCmd = "
90
- # cmd = gets.chomp.strip
91
- # meth, params = Command.choose_method(cmd)
92
- # puts " Calling: #{meth}(#{params.inspect})"
93
- # end
94
-
95
-
@@ -0,0 +1,106 @@
1
+ require 'find'
2
+ require 'yaml'
3
+ require 'livetext'
4
+
5
+ class RuneBlog
6
+ VERSION = "0.0.45"
7
+
8
+ Path = File.expand_path(File.join(File.dirname(__FILE__)))
9
+ DefaultData = Path + "/../data"
10
+
11
+ BlogHeaderPath = DefaultData + "/custom/blog_header.html"
12
+ BlogTrailerPath = DefaultData + "/custom/blog_trailer.html"
13
+
14
+ BlogHeader = File.read(BlogHeaderPath) rescue "not found"
15
+ BlogTrailer = File.read(BlogTrailerPath) rescue "not found"
16
+ end
17
+
18
+ # Continued below...
19
+
20
+ class RuneBlog::Config
21
+ attr_reader :root, :views, :view, :sequence
22
+ attr_writer :view # FIXME
23
+
24
+ def self.create(cfg_file = ".blog")
25
+ RuneBlog.create_new_blog
26
+ end
27
+
28
+ def initialize(cfg_file = ".blog")
29
+ # What views are there? Deployment, etc.
30
+ # Crude - FIXME later
31
+
32
+ lines = File.readlines(cfg_file).map {|x| x.chomp }
33
+ @root = lines[0]
34
+ @view = lines[1]
35
+ dirs = Dir.entries("#@root/views/") - %w[. ..]
36
+ dirs.reject! {|x| ! File.directory?("#@root/views/#{x}") }
37
+ @root = root
38
+ @views = dirs
39
+ @sequence = File.read(root + "/sequence").to_i
40
+ end
41
+
42
+ def next_sequence
43
+ @sequence += 1
44
+ File.open("#@root/sequence", "w") {|f| f.puts @sequence }
45
+ @sequence
46
+ end
47
+
48
+ def viewdir(v)
49
+ @root + "/views/#{v}/"
50
+ end
51
+
52
+ end
53
+
54
+ # Reopening...
55
+
56
+ class RuneBlog
57
+
58
+ def self.exist?
59
+ File.exist?(".blog")
60
+ end
61
+
62
+ def get_config
63
+ end
64
+
65
+ # def initialize
66
+ # # ?
67
+ # end
68
+
69
+ def self.create_new_blog
70
+ #-- what if data already exists?
71
+ result = system("cp -r #{RuneBlog::DefaultData} .")
72
+ raise "Error copying default data" unless result
73
+
74
+ File.open(".blog", "w") do |f|
75
+ f.puts "data"
76
+ f.puts "no_default"
77
+ end
78
+ File.open("data/VERSION", "a") {|f| f.puts "\nBlog created: " + Time.now.to_s }
79
+ end
80
+
81
+ # def self.open_blog
82
+ # end
83
+
84
+ # def self.create_new_post(title, date, view)
85
+ # @template = <<-EOS
86
+ # .mixin liveblog
87
+ #
88
+ # .title #{title}
89
+ # .pubdate #{date}
90
+ # .views #{view}
91
+ #
92
+ # .teaser
93
+ # Teaser goes here.
94
+ # .end
95
+ # Remainder of post goes here.
96
+ # EOS
97
+ #
98
+ # @slug = make_slug(title)
99
+ # @fname = @slug + ".lt3"
100
+ # File.open("#@root/src/#@fname", "w") {|f| f.puts @template }
101
+ # @fname
102
+ # rescue => err
103
+ # error(err, __LINE__, __FILE__)
104
+ # end
105
+
106
+ end
data/lib/oldrepl.rb ADDED
@@ -0,0 +1,628 @@
1
+ require 'runeblog'
2
+
3
+ require 'ostruct'
4
+
5
+ =begin
6
+ Instance vars in original code:
7
+ @bloghead
8
+ @blogtail
9
+ @config
10
+ @date
11
+ @deploy
12
+ @fname
13
+ @main
14
+ @meta
15
+ @root
16
+ @sequence
17
+ @slug
18
+ @template
19
+ @title
20
+ @today
21
+ @view
22
+ =end
23
+
24
+ module RuneBlog::REPL
25
+
26
+ ### error
27
+
28
+ def error(err, line, file)
29
+ str = "\n Error: #{red(err)}"
30
+ puts err.backtrace
31
+ end
32
+
33
+ ### ask
34
+
35
+ def ask(prompt, meth = :to_s)
36
+ print prompt
37
+ STDOUT.flush
38
+ STDIN.gets.chomp.send(meth)
39
+ end
40
+
41
+ def yesno(prompt, meth = :to_s)
42
+ print prompt
43
+ STDOUT.flush
44
+ STDIN.gets.chomp.upcase[0] == "Y"
45
+ end
46
+
47
+ ### quit
48
+
49
+ def cmd_quit(arg)
50
+ raise "Glitch: Got an argument" if arg != []
51
+ puts "\n "
52
+ exit
53
+ end
54
+
55
+ ### version
56
+
57
+ def cmd_version(arg)
58
+ raise "Glitch: Got an argument" if arg != []
59
+ puts "\n " + RuneBlog::VERSION
60
+ end
61
+
62
+ ### new_blog!
63
+
64
+ def cmd_new_blog!(arg)
65
+ raise "Glitch: Got an argument" if arg != []
66
+ return if RuneBlog.exist?
67
+ yn = yesno(red(" No .blog found. Create new blog? "))
68
+ RuneBlog.create_new_blog if yn
69
+ rescue => err
70
+ error(err)
71
+ end
72
+
73
+ ### make_slug
74
+
75
+ # What to do with this?
76
+
77
+ def make_slug(title, seq=nil)
78
+ num = '%04d' % (seq || @config.next_sequence) # FIXME can do better
79
+ slug = title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
80
+ "#{num}-#{slug}"
81
+ end
82
+
83
+ ### read_config
84
+
85
+ def read_config # Crude - FIXME later
86
+ cmd_new_blog!([]) unless RuneBlog.exist?
87
+ @config = RuneBlog::Config.new
88
+ @view = @config.view # current view
89
+ @sequence = @config.sequence
90
+ @root = @config.root
91
+ @config
92
+ rescue => err
93
+ error(err)
94
+ end
95
+
96
+ ### create_empty_post
97
+
98
+ def create_empty_post
99
+ @template = <<-EOS
100
+ .mixin liveblog
101
+
102
+ .title #@title
103
+ .pubdate #@date
104
+ .views #@view
105
+
106
+ .teaser
107
+ Teaser goes here.
108
+ .end
109
+ Remainder of post goes here.
110
+ EOS
111
+
112
+ @slug = make_slug(@title)
113
+ @fname = @slug + ".lt3"
114
+ File.open("#@root/src/#@fname", "w") {|f| f.puts @template }
115
+ @fname
116
+ rescue => err
117
+ error(err)
118
+ end
119
+
120
+ ### edit_initial_post
121
+
122
+ def edit_initial_post(file)
123
+ result = system("vi #@root/src/#{file} +8 ")
124
+ raise "Problem editing #@root/src/#{file}" unless result
125
+ rescue => err
126
+ error(err, __LINE__, __FILE__)
127
+ end
128
+
129
+ ### browse
130
+
131
+ def cmd_browse
132
+ raise "Glitch: Got an argument" if arg != []
133
+ @deploy ||= {}
134
+ return puts red("\n Deploy first.") unless @deploy[@view]
135
+
136
+ lines = @deploy[@view]
137
+ user, server, sroot, spath = *lines
138
+ result = system("open 'http://#{server}/#{spath}'")
139
+ raise "Problem opening http://#{server}/#{spath}" unless result
140
+ rescue => err
141
+ error(err)
142
+ end
143
+
144
+ ### open_local
145
+
146
+ def open_local
147
+ result = system("open #{@config.viewdir(@view)}/index.html")
148
+ raise "Problem opening #{@config.viewdir(@view)}/index.html" unless result
149
+ rescue => err
150
+ error(err)
151
+ end
152
+
153
+ def cmd_deploy(arg)
154
+ # TBD clunky FIXME
155
+ raise "Glitch: Got an argument" if arg != []
156
+ @deploy ||= {}
157
+ deployment = @config.viewdir(@view) + "deploy"
158
+ raise "File '#{deployment}' not found" unless File.exist?(deployment)
159
+
160
+ lines = File.readlines(deployment).map {|x| x.chomp }
161
+ @deploy[@view] = lines
162
+ user, server, sroot, spath = *lines
163
+ vdir = @config.viewdir(@view)
164
+ files = ["#{vdir}/index.html"]
165
+ files += Dir.entries(vdir).grep(/^\d\d\d\d/).map {|x| "#{vdir}/#{x}" }
166
+ files.reject! {|f| File.mtime(f) < File.mtime("#{vdir}/last_deployed") }
167
+ return puts red("\n No files to deploy") if files.empty?
168
+
169
+ puts "\n Files:"
170
+ files.each {|f| puts " " + f }
171
+ puts
172
+ dir = "#{sroot}/#{spath}"
173
+ # FIXME - may or may not already exist
174
+ result = system("ssh root@#{server} mkdir #{dir}")
175
+
176
+ cmd = "scp -r #{files.join(' ')} root@#{server}:#{dir} >/dev/null 2>&1"
177
+ print red("\n Deploying #{files.size} files... ")
178
+ result = system(cmd)
179
+ raise "Problem occurred in deployment" unless result
180
+
181
+ File.write("#{vdir}/last_deployed", files)
182
+ puts red("finished.")
183
+ rescue => err
184
+ error(err)
185
+ end
186
+
187
+ ### process_post
188
+
189
+ def process_post(file)
190
+ @main ||= Livetext.new
191
+ @main.main.output = File.new("/tmp/WHOA","w")
192
+ path = @root + "/src/#{file}"
193
+ @meta = @main.process_file(path, binding)
194
+ raise "process_file returned nil" if @meta.nil?
195
+
196
+ @meta.slug = make_slug(@meta.title, @config.sequence)
197
+ @meta.slug = file.sub(/.lt3$/, "")
198
+ @meta
199
+ rescue => err
200
+ error(err)
201
+ end
202
+
203
+ ### reload_post
204
+
205
+ def reload_post(file)
206
+ @main ||= Livetext.new
207
+ @main.main.output = File.new("/tmp/WHOA","w")
208
+ @meta = process_post(file)
209
+ @meta.slug = file.sub(/.lt3$/, "")
210
+ @meta
211
+ rescue => err
212
+ error(err)
213
+ end
214
+
215
+ ### posting
216
+
217
+ def posting(view, meta)
218
+ ref = "#{view}/#{meta.slug}/index.html"
219
+ <<-HTML
220
+ <br>
221
+ <font size=+1>#{meta.pubdate}&nbsp;&nbsp;</font>
222
+ <font size=+2 color=blue><a href=../#{ref} style="text-decoration: none">#{meta.title}</font></a>
223
+ <br>
224
+ #{meta.teaser}
225
+ <a href=../#{ref} style="text-decoration: none">Read more...</a>
226
+ <br><br>
227
+ <hr>
228
+ HTML
229
+ end
230
+
231
+ ### generate_index
232
+
233
+ def generate_index(view)
234
+ # Gather all posts, create list
235
+ vdir = "#@root/views/#{view}"
236
+ posts = Dir.entries(vdir).grep /^\d\d\d\d/
237
+ posts = posts.sort.reverse
238
+
239
+ # Add view header/trailer
240
+ head = File.read("#{vdir}/custom/blog_header.html") rescue RuneBlog::BlogHeader
241
+ tail = File.read("#{vdir}/custom/blog_trailer.html") rescue RuneBlog::BlogTrailer
242
+ @bloghead = interpolate(head)
243
+ @blogtail = interpolate(tail)
244
+
245
+ # Output view
246
+ posts.map! {|post| YAML.load(File.read("#{vdir}/#{post}/metadata.yaml")) }
247
+ File.open("#{vdir}/index.html", "w") do |f|
248
+ f.puts @bloghead
249
+ posts.each {|post| f.puts posting(view, post) }
250
+ f.puts @blogtail
251
+ end
252
+ rescue => err
253
+ error(err)
254
+ end
255
+
256
+ ### create_dir
257
+
258
+ def create_dir(dir)
259
+ cmd = "mkdir -p #{dir} >/dev/null 2>&1"
260
+ result = system(cmd)
261
+ raise "Can't create #{dir}" unless result
262
+ end
263
+
264
+ ### link_post_view
265
+
266
+ def link_post_view(view)
267
+ # Create dir using slug (index.html, metadata?)
268
+ vdir = @config.viewdir(view)
269
+ dir = vdir + @meta.slug + "/"
270
+ create_dir(dir + "assets")
271
+ File.write("#{dir}/metadata.yaml", @meta.to_yaml)
272
+ template = File.read(vdir + "custom/post_template.html")
273
+ post = interpolate(template)
274
+ File.write(dir + "index.html", post)
275
+ generate_index(view)
276
+ rescue => err
277
+ error(err)
278
+ end
279
+
280
+ ### find_asset
281
+
282
+ # def find_asset(asset) # , views)
283
+ # # STDERR.puts "repl find_asset: @meta = #{@meta.inspect}"
284
+ # views = @meta.views
285
+ # views.each do |view|
286
+ # vdir = @config.viewdir(view)
287
+ # post_dir = "#{vdir}#{@meta.slug}/assets/"
288
+ # path = post_dir + asset
289
+ # STDERR.puts " Seeking #{path}"
290
+ # return path if File.exist?(path)
291
+ # end
292
+ # views.each do |view|
293
+ # dir = @config.viewdir(view) + "/assets/"
294
+ # path = dir + asset
295
+ # STDERR.puts " Seeking #{path}"
296
+ # return path if File.exist?(path)
297
+ # end
298
+ # top = @root + "/assets/"
299
+ # path = top + asset
300
+ # STDERR.puts " Seeking #{path}"
301
+ # return path if File.exist?(path)
302
+ #
303
+ # return nil
304
+ # end
305
+ #
306
+ # ### find_all_assets
307
+ #
308
+ # def find_all_assets(list, views)
309
+ # # STDERR.puts "\n Called find_all_assets with #{list.inspect}"
310
+ # list ||= []
311
+ # list.each {|asset| puts "#{asset} => #{find_asset(asset, views)}" }
312
+ # end
313
+
314
+ ### publish_post
315
+
316
+ def publish_post(meta)
317
+ puts " #{colored_slug(meta.slug)}"
318
+ # First gather the views
319
+ views = meta.views
320
+ print " Views: "
321
+ views.each do |view|
322
+ print "#{view} "
323
+ link_post_view(view)
324
+ end
325
+ # assets = find_all_assets(@meta.assets, views)
326
+ puts
327
+ rescue => err
328
+ error(err)
329
+ end
330
+
331
+ ### rebuild_post
332
+
333
+ def rebuild_post(file)
334
+ reload_post(file)
335
+ publish_post(@meta) # FIXME ??
336
+ rescue => err
337
+ error(err)
338
+ end
339
+
340
+ ### rebuild
341
+
342
+ def cmd_rebuild(arg)
343
+ raise "Glitch: Got an argument" if arg != []
344
+ puts
345
+ files = Dir.entries("#@root/src/").grep /\d\d\d\d.*.lt3$/
346
+ files.map! {|f| File.basename(f) }
347
+ files = files.sort.reverse
348
+ files.each {|file| rebuild_post(file) }
349
+ rescue => err
350
+ error(err)
351
+ end
352
+
353
+ ### relink
354
+
355
+ def cmd_relink(arg)
356
+ raise "Glitch: Got an argument" if arg != []
357
+ @config.views.each {|view| generate_index(view) }
358
+ rescue => err
359
+ error(err)
360
+ end
361
+
362
+ # ### publish?
363
+ #
364
+ # def publish?
365
+ # yn = ask(red(" Publish? y/n "))
366
+ # yn.upcase == "Y"
367
+ # end
368
+
369
+ ### list_views
370
+
371
+ def cmd_list_views(arg)
372
+ abort "Config file not read" unless @config
373
+ raise "Glitch: Got an argument" if arg != []
374
+ puts
375
+ @config.views.each {|v| puts " #{v}" }
376
+ rescue => err
377
+ error(err)
378
+ end
379
+
380
+ ### change_view
381
+
382
+ def cmd_change_view(arg)
383
+ if arg.empty?
384
+ puts "\n #@view"
385
+ else
386
+ arg = arg.first
387
+ list = @config.views.grep /^#{arg}/
388
+ if list.size == 1
389
+ @view = @config.view = list.first
390
+ puts red("\n View: #{@view}") if arg != @view
391
+ else
392
+ puts "view #{arg.inspect} does not exist"
393
+ end
394
+ end
395
+ rescue => err
396
+ error(err)
397
+ end
398
+
399
+ ### new_view
400
+
401
+ def cmd_new_view(arg)
402
+ arg = arg.first
403
+ read_config unless @config
404
+ arg ||= ask("New view: ") # check validity later
405
+ raise "view #{arg} already exists" if @config.views.include?(arg)
406
+
407
+ dir = @root + "/views/" + arg + "/"
408
+ create_dir(dir + 'custom')
409
+ create_dir(dir + 'assets')
410
+
411
+ # Something more like this? RuneBlog.new_view(arg)
412
+ File.write(dir + "custom/blog_header.html", RuneBlog::BlogHeader)
413
+ File.write(dir + "custom/blog_trailer.html", RuneBlog::BlogTrailer)
414
+ File.write(dir + "last_deployed", "Initial creation")
415
+ @config.views << arg
416
+ rescue => err
417
+ error(err)
418
+ end
419
+
420
+ ### import
421
+
422
+ def import(arg = nil)
423
+ read_config unless @config
424
+ arg = nil if arg == ""
425
+ arg ||= ask("Filename: ") # check validity later
426
+ name = arg
427
+ grep = `grep ^.title #{name}`
428
+ @title = grep.sub(/^.title /, "")
429
+ @slug = make_slug(@title)
430
+ @fname = @slug + ".lt3"
431
+ result = system("cp #{name} #@root/src/#@fname")
432
+ raise "Could not copy #{name} to #@root/src/#@fname" unless result
433
+
434
+ edit_initial_post(@fname)
435
+ process_post(@fname)
436
+ publish_post(@meta) # if publish?
437
+ rescue => err
438
+ error(err)
439
+ end
440
+
441
+ ### new_post
442
+
443
+ def cmd_new_post(arg)
444
+ raise "Glitch: Got an argument" if arg != []
445
+ read_config unless @config
446
+ @title = ask("Title: ")
447
+ @today = Time.now.strftime("%Y%m%d")
448
+ @date = Time.now.strftime("%Y-%m-%d")
449
+
450
+ file = create_empty_post
451
+ edit_initial_post(file)
452
+ # file = @root + "/src/" + file
453
+ process_post(file) #- FIXME handle each view
454
+ publish_post(@meta) # if publish?
455
+ rescue => err
456
+ error(err)
457
+ end
458
+
459
+ ### remove_multiple_posts
460
+
461
+ def remove_multiple_posts(str)
462
+ args = str.split
463
+ args.each {|arg| remove_post(arg, false) }
464
+ end
465
+
466
+ ### remove_post
467
+
468
+ #-- FIXME affects linking, building, deployment...
469
+
470
+ def cmd_remove_post(arg, safe=true)
471
+ arg = arg.first
472
+ id = Integer(arg) rescue raise("'#{arg}' is not an integer")
473
+ tag = "#{'%04d' % id}"
474
+ files = Find.find(@root).to_a
475
+ files = files.grep(/#{tag}-/)
476
+ return puts red("\n No such post found (#{id})") if files.empty?
477
+
478
+ if safe
479
+ puts
480
+ files.each {|f| puts " #{f}" }
481
+ ques = files.size > 1 ? "\n Delete all these? " : "\n Delete? "
482
+ yn = ask red(ques)
483
+ if yn.downcase == "y"
484
+ result = system("rm -rf #{files.join(' ')}")
485
+ raise "Problem deleting file(s)" unless result
486
+ puts red("\n Deleted")
487
+ else
488
+ puts red("\n No action taken")
489
+ end
490
+ else
491
+ result = system("rm -rf #{files.join(' ')}")
492
+ puts red("\n Deleted:")
493
+ files.each {|f| puts " #{f}" }
494
+ raise "Problem mass-deleting file(s)" unless result
495
+ end
496
+ rescue => err
497
+ puts err
498
+ puts err.backtrace
499
+ puts
500
+ end
501
+
502
+ ### edit_post
503
+
504
+ #-- FIXME affects linking, building, deployment...
505
+
506
+ def cmd_edit_post(arg)
507
+ arg = arg.first
508
+ id = Integer(arg) rescue raise("'#{arg}' is not an integer")
509
+ tag = "#{'%04d' % id}"
510
+ files = Find.find(@root+"/src").to_a
511
+ files = files.grep(/#{tag}-/)
512
+ files = files.map {|f| File.basename(f) }
513
+ return puts red("Multiple files: #{files}") if files.size > 1
514
+ return puts red("\n No such post found (#{id})") if files.empty?
515
+
516
+ file = files.first
517
+ result = system("vi #@root/src/#{file}")
518
+ raise "Problem editing #{file}" unless result
519
+
520
+ rebuild_post(file)
521
+ rescue => err
522
+ puts err
523
+ puts err.backtrace
524
+ puts
525
+ end
526
+
527
+ ### list_posts
528
+
529
+ def cmd_list_posts(arg)
530
+ raise "Glitch: Got an argument" if arg != []
531
+ dir = @config.viewdir(@view)
532
+ Dir.chdir(dir) do
533
+ posts = Dir.entries(".").grep(/^0.*/)
534
+ if posts.empty?
535
+ puts "\n " + @view + ":" + red(" No posts")
536
+ else
537
+ puts "\n " + @view + ":\n "
538
+ posts.each {|post| puts " #{colored_slug(post)}" }
539
+ end
540
+ end
541
+ rescue
542
+ puts "Oops? cwd = #{Dir.pwd} dir = #{dir}"
543
+ puts err.backtrace
544
+ exit
545
+ end
546
+
547
+ ### list_drafts
548
+
549
+ def cmd_list_drafts(arg)
550
+ raise "Glitch: Got an argument" if arg != []
551
+ dir = "#@root/src"
552
+ Dir.chdir(dir) do
553
+ posts = Dir.entries(".").grep(/^0.*.lt3/)
554
+ puts
555
+ if posts.empty?
556
+ puts red(" No posts")
557
+ else
558
+ posts.each {|post| puts " #{colored_slug(post.sub(/.lt3$/, ""))}" }
559
+ end
560
+ end
561
+ rescue
562
+ puts "Oops? cwd = #{Dir.pwd} dir = #{dir}"
563
+ puts err.backtrace
564
+ exit
565
+ end
566
+
567
+ def cmd_INVALID(arg)
568
+ puts "\n Command '#{red(arg)}' was not understood."
569
+ end
570
+
571
+ def cmd_help(arg)
572
+ raise "Glitch: Got an argument" if arg != []
573
+ puts <<-EOS
574
+
575
+ Commands:
576
+
577
+ #{red('h, help ')} This message
578
+ #{red('q, quit ')} Exit the program
579
+ #{red('v, version ')} Print version information
580
+
581
+ #{red('change view VIEW ')} Change current view
582
+ #{red('cv VIEW ')} Change current view
583
+ #{red('new view ')} Create a new view
584
+ #{red('list views ')} List all views available
585
+ #{red('lsv ')} Same as: list views
586
+
587
+ #{red('p, post ')} Create a new post
588
+ #{red('new post ')} Same as post (create a post)
589
+ #{red('lsp, list posts ')} List posts in current view
590
+ #{red('lsd, list drafts ')} List all posts regardless of view
591
+
592
+ #{red('rm ID ')} Remove a post
593
+ #{red('edit ID ')} Edit a post
594
+
595
+ #{red('preview ')} Look at current (local) view in browser
596
+ #{red('browse ')} Look at current (deployed) view in browser
597
+ #{red('relink ')} Regenerate index for all views
598
+ #{red('rebuild ')} Regenerate all posts and relink
599
+ #{red('deploy ')} Deploy (current view)
600
+ EOS
601
+ end
602
+
603
+ def clear
604
+ puts "\e[H\e[2J" # clear screen
605
+ end
606
+
607
+ def red(text)
608
+ "\e[31m#{text}\e[0m"
609
+ end
610
+
611
+ def blue(text)
612
+ "\e[34m#{text}\e[0m"
613
+ end
614
+
615
+ def bold(str)
616
+ "\e[1m#{str}\e[22m"
617
+ end
618
+
619
+ def interpolate(str)
620
+ wrap = "<<-EOS\n#{str}\nEOS"
621
+ eval wrap
622
+ end
623
+
624
+ def colored_slug(slug)
625
+ red(slug[0..3])+blue(slug[4..-1])
626
+ end
627
+
628
+ end