runeblog 0.0.45 → 0.0.48

Sign up to get free protection for your applications and to get access to all the features.
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