runeblog 0.3.02

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.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/README.lt3 +279 -0
  3. data/README.md +312 -0
  4. data/bin/blog +200 -0
  5. data/bin/mkwidget +164 -0
  6. data/data/EDITOR +1 -0
  7. data/data/ROOT +1 -0
  8. data/data/VIEW +1 -0
  9. data/data/features.txt +18 -0
  10. data/data/global.lt3 +20 -0
  11. data/data/universal.lt3 +18 -0
  12. data/empty_view/assets/austin-pano.jpg +0 -0
  13. data/empty_view/assets/sky2.jpg +0 -0
  14. data/empty_view/config/exper/2svg.lt3 +38 -0
  15. data/empty_view/config/exper/gen_svg.rb +60 -0
  16. data/empty_view/config/exper/meta.html +10 -0
  17. data/empty_view/config/exper/s2.html +25 -0
  18. data/empty_view/config/exper/varmint.rb +50 -0
  19. data/empty_view/config/facebook/credentials.txt +7 -0
  20. data/empty_view/config/facebook/facebook.rb +42 -0
  21. data/empty_view/config/facebook/fb.html +10 -0
  22. data/empty_view/config/facebook/fb.js.lt3 +15 -0
  23. data/empty_view/config/reddit/credentials.txt +6 -0
  24. data/empty_view/config/reddit/notes.txt +4 -0
  25. data/empty_view/config/reddit/reddit_post_url.py +34 -0
  26. data/empty_view/config/reddit/redpost.rb +43 -0
  27. data/empty_view/config/reddit/the-graffiti-wall.html +91 -0
  28. data/empty_view/config/twitter/credentials.txt +3 -0
  29. data/empty_view/config/twitter/tw.html +12 -0
  30. data/empty_view/config/twitter/tw.js +5 -0
  31. data/empty_view/config/twitter/twitter.rb +35 -0
  32. data/empty_view/posts/GIT_IS_DUMB +1 -0
  33. data/empty_view/remote/assets/GIT_IS_DUMB +1 -0
  34. data/empty_view/remote/banner/navbar/GIT_IS_DUMB +0 -0
  35. data/empty_view/remote/etc/GIT_IS_DUMB +1 -0
  36. data/empty_view/remote/permalink/GIT_IS_DUMB +1 -0
  37. data/empty_view/remote/widgets/ad/GIT_IS_DUMB +2 -0
  38. data/empty_view/remote/widgets/links/GIT_IS_DUMB +2 -0
  39. data/empty_view/remote/widgets/news/GIT_IS_DUMB +2 -0
  40. data/empty_view/remote/widgets/pages/GIT_IS_DUMB +2 -0
  41. data/empty_view/remote/widgets/pinned/GIT_IS_DUMB +2 -0
  42. data/empty_view/settings/features.txt +18 -0
  43. data/empty_view/settings/publish.txt +5 -0
  44. data/empty_view/settings/recent.txt +6 -0
  45. data/empty_view/settings/view.txt +4 -0
  46. data/empty_view/themes/standard/README +59 -0
  47. data/empty_view/themes/standard/banner/banner.lt3 +5 -0
  48. data/empty_view/themes/standard/banner/navbar/about.lt3 +18 -0
  49. data/empty_view/themes/standard/banner/navbar/contact.lt3 +18 -0
  50. data/empty_view/themes/standard/banner/navbar/faq.lt3 +1 -0
  51. data/empty_view/themes/standard/banner/navbar/list.data +3 -0
  52. data/empty_view/themes/standard/banner/top.lt3 +20 -0
  53. data/empty_view/themes/standard/blog/generate.lt3 +21 -0
  54. data/empty_view/themes/standard/blog/head.lt3 +16 -0
  55. data/empty_view/themes/standard/blog/index.lt3 +17 -0
  56. data/empty_view/themes/standard/blog/post_entry.lt3 +21 -0
  57. data/empty_view/themes/standard/etc/blog.css.lt3 +62 -0
  58. data/empty_view/themes/standard/etc/externals.lt3 +24 -0
  59. data/empty_view/themes/standard/etc/favicon.ico +0 -0
  60. data/empty_view/themes/standard/etc/misc.js +20 -0
  61. data/empty_view/themes/standard/post/generate.lt3 +38 -0
  62. data/empty_view/themes/standard/post/head.lt3 +7 -0
  63. data/empty_view/themes/standard/post/index.lt3 +24 -0
  64. data/empty_view/themes/standard/post/permalink.lt3 +32 -0
  65. data/empty_view/themes/standard/widgets/README +4 -0
  66. data/empty_view/themes/standard/widgets/ad/ad.lt3 +22 -0
  67. data/empty_view/themes/standard/widgets/ad/ad1.png +0 -0
  68. data/empty_view/themes/standard/widgets/ad/ad2.png +0 -0
  69. data/empty_view/themes/standard/widgets/ad/ad3.png +0 -0
  70. data/empty_view/themes/standard/widgets/ad/ad4.png +0 -0
  71. data/empty_view/themes/standard/widgets/bydates/README +2 -0
  72. data/empty_view/themes/standard/widgets/bydates/bydates.rb +18 -0
  73. data/empty_view/themes/standard/widgets/bydates/card.css +1 -0
  74. data/empty_view/themes/standard/widgets/bydates/custom.rb +1 -0
  75. data/empty_view/themes/standard/widgets/bydates/main.css +2 -0
  76. data/empty_view/themes/standard/widgets/links/README +2 -0
  77. data/empty_view/themes/standard/widgets/links/card.css +1 -0
  78. data/empty_view/themes/standard/widgets/links/custom.rb +1 -0
  79. data/empty_view/themes/standard/widgets/links/links.rb +90 -0
  80. data/empty_view/themes/standard/widgets/links/list.data +3 -0
  81. data/empty_view/themes/standard/widgets/links/main.css +2 -0
  82. data/empty_view/themes/standard/widgets/news/README +2 -0
  83. data/empty_view/themes/standard/widgets/news/card.css +1 -0
  84. data/empty_view/themes/standard/widgets/news/custom.rb +1 -0
  85. data/empty_view/themes/standard/widgets/news/list.data +4 -0
  86. data/empty_view/themes/standard/widgets/news/main.css +2 -0
  87. data/empty_view/themes/standard/widgets/news/news.rb +88 -0
  88. data/empty_view/themes/standard/widgets/pages/README +2 -0
  89. data/empty_view/themes/standard/widgets/pages/card.css +1 -0
  90. data/empty_view/themes/standard/widgets/pages/custom.rb +1 -0
  91. data/empty_view/themes/standard/widgets/pages/disclaim.lt3 +10 -0
  92. data/empty_view/themes/standard/widgets/pages/faq.lt3 +40 -0
  93. data/empty_view/themes/standard/widgets/pages/like-dislike.lt3 +11 -0
  94. data/empty_view/themes/standard/widgets/pages/list.data +4 -0
  95. data/empty_view/themes/standard/widgets/pages/local.rb +0 -0
  96. data/empty_view/themes/standard/widgets/pages/main.css +2 -0
  97. data/empty_view/themes/standard/widgets/pages/other-stuff.lt3 +10 -0
  98. data/empty_view/themes/standard/widgets/pages/pages.rb +95 -0
  99. data/empty_view/themes/standard/widgets/pinned/README +2 -0
  100. data/empty_view/themes/standard/widgets/pinned/card.css +1 -0
  101. data/empty_view/themes/standard/widgets/pinned/custom.rb +1 -0
  102. data/empty_view/themes/standard/widgets/pinned/main.css +2 -0
  103. data/empty_view/themes/standard/widgets/pinned/pinned.rb +99 -0
  104. data/empty_view/themes/standard/widgets/search/README +2 -0
  105. data/empty_view/themes/standard/widgets/search/card.css +1 -0
  106. data/empty_view/themes/standard/widgets/search/custom.rb +1 -0
  107. data/empty_view/themes/standard/widgets/search/main.css +2 -0
  108. data/empty_view/themes/standard/widgets/search/search.rb +18 -0
  109. data/empty_view/themes/standard/widgets/sitemap/README +2 -0
  110. data/empty_view/themes/standard/widgets/sitemap/card.css +1 -0
  111. data/empty_view/themes/standard/widgets/sitemap/custom.rb +1 -0
  112. data/empty_view/themes/standard/widgets/sitemap/main.css +2 -0
  113. data/empty_view/themes/standard/widgets/sitemap/sitemap.rb +18 -0
  114. data/empty_view/themes/standard/widgets/tag-cloud/OLD-example.lt3 +12 -0
  115. data/empty_view/themes/standard/widgets/tag-cloud/README +2 -0
  116. data/empty_view/themes/standard/widgets/tag-cloud/card.css +1 -0
  117. data/empty_view/themes/standard/widgets/tag-cloud/custom.rb +1 -0
  118. data/empty_view/themes/standard/widgets/tag-cloud/main.css +2 -0
  119. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.lt3 +3 -0
  120. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.rb +18 -0
  121. data/lib/Javascript.stuff +69 -0
  122. data/lib/helpers-blog.rb +155 -0
  123. data/lib/helpers-repl.rb +201 -0
  124. data/lib/liveblog.rb +825 -0
  125. data/lib/logging.rb +44 -0
  126. data/lib/lowlevel.rb +73 -0
  127. data/lib/pathmagic.rb +14 -0
  128. data/lib/post.rb +211 -0
  129. data/lib/processing.rb +60 -0
  130. data/lib/publish.rb +73 -0
  131. data/lib/repl.rb +597 -0
  132. data/lib/runeblog.rb +773 -0
  133. data/lib/runeblog_version.rb +50 -0
  134. data/lib/view.rb +69 -0
  135. data/runeblog.gemspec +42 -0
  136. data/test/austin.rb +158 -0
  137. data/test/fakeimage.jpg +0 -0
  138. data/test/general_test.rb +304 -0
  139. data/test/make_blog.rb +196 -0
  140. data/test/test +3 -0
  141. metadata +242 -0
@@ -0,0 +1,597 @@
1
+ require 'runeblog'
2
+ require 'ostruct'
3
+ require 'helpers-repl' # FIXME structure
4
+ require 'pathmagic'
5
+
6
+ make_exception(:PublishError, "Error during publishing")
7
+ make_exception(:EditorProblem, "Could not edit $1")
8
+
9
+ module RuneBlog::REPL
10
+ def edit_file(file, vim: "")
11
+ STDSCR.saveback
12
+ ed = @blog.editor
13
+ params = vim if ed =~ /vim$/
14
+ result = system!("#{@blog.editor} #{file} #{params}")
15
+ raise EditorProblem(file) unless result
16
+ STDSCR.restback
17
+ # cmd_clear(nil)
18
+ end
19
+
20
+ def cmd_quit(arg, testing = false)
21
+ cmd_clear(nil)
22
+ RubyText.stop
23
+ sleep 0.1
24
+
25
+ sleep 0.1
26
+ exit
27
+ end
28
+
29
+ def cmd_clear(arg, testing = false)
30
+ # STDSCR.rows.times { puts " "*(STDSCR.cols-1) }
31
+ STDSCR.clear
32
+ end
33
+
34
+ def cmd_version(arg, testing = false)
35
+ reset_output
36
+ output RuneBlog::VERSION
37
+ puts fx("\n RuneBlog", :bold), fx(" v #{RuneBlog::VERSION}\n", Red) unless testing
38
+ @out
39
+ end
40
+
41
+ def OLD_cmd_config(arg, testing = false)
42
+ hash = {"global.lt3 Global configuration" => "global.lt3",
43
+ "banner/top.lt3 Text portion of banner" => "banner/top.lt3",
44
+ "blog/generate.lt3 Generator for view (usu not edited)" => "blog/generate.lt3",
45
+ ".... head.lt3 HEAD info for view" => "blog/head.lt3",
46
+ ".... banner.lt3 banner description" => "blog/banner.lt3",
47
+ ".... index.lt3 User-edited detail for view" => "blog/index.lt3",
48
+ ".... post_entry.lt3 Generator for post entry in recent-posts" => "blog/post_entry.lt3",
49
+ "etc/blog.css.lt3 Global CSS" => "etc/blog.css.lt3",
50
+ "... externals.lt3 External JS/CSS (Bootstrap, etc.)" => "/etc/externals.lt3",
51
+ "post/generate.lt3 Generator for a post" => "post/generate.lt3",
52
+ ".... head.lt3 HEAD info for post" => "post/head.lt3",
53
+ ".... index.lt3 Content for post" => "post/index.lt3",
54
+ ".... permalink.lt3 Generator for permalink" => "post/permalink.lt3",
55
+ }
56
+
57
+ dir = @blog.view.dir/"themes/standard/"
58
+ num, target = STDSCR.menu(title: "Edit file:", items: hash)
59
+ edit_file(dir/target)
60
+ end
61
+
62
+ def cmd_config(arg, testing = false)
63
+ hash = {"Global configuration" => "global.lt3",
64
+ " View-specific variables" => "../../settings/view.txt",
65
+ " Recent posts" => "../../settings/recent.txt",
66
+ " Publishing vars" => "../../settings/publish.txt",
67
+ "Banner description" => "blog/banner.lt3",
68
+ " Text portion of banner" => "banner/top.lt3",
69
+ "Generator for view (usu not edited)" => "blog/generate.lt3",
70
+ " HEAD info for view" => "blog/head.lt3",
71
+ " User-edited detail for view" => "blog/index.lt3",
72
+ "Generator for post entry in recent-posts" => "blog/post_entry.lt3",
73
+ "Global CSS" => "etc/blog.css.lt3",
74
+ "External JS/CSS (Bootstrap, etc.)" => "/etc/externals.lt3",
75
+ "Generator for a post" => "post/generate.lt3",
76
+ " HEAD info for post" => "post/head.lt3",
77
+ " Content for post" => "post/index.lt3",
78
+ "Generator for permalink" => "post/permalink.lt3",
79
+ }
80
+
81
+ dir = @blog.view.dir/"themes/standard/"
82
+ num, target = STDSCR.menu(title: "Edit file:", items: hash)
83
+ edit_file(dir/target)
84
+ end
85
+
86
+
87
+
88
+ def cmd_manage(arg, testing = false)
89
+ case arg
90
+ when "pages"; _manage_pages(nil, testing = false)
91
+ when "links"; _manage_links(nil, testing = false)
92
+ when "navbar"; _manage_navbar(nil, testing = false)
93
+ # when "pinned"; _manage_pinned(nil, testing = false) # ditch this??
94
+ else
95
+ puts "#{arg} is unknown"
96
+ end
97
+ end
98
+
99
+ def _manage_pinned(arg, testing = false) # cloned from manage_links
100
+ dir = @blog.view.dir/"themes/standard/widgets/pinned"
101
+ data = dir/"list.data"
102
+ edit_file(data)
103
+ end
104
+
105
+ def _manage_navbar(arg, testing = false) # cloned from manage_pages
106
+ dir = @blog.view.dir/"themes/standard/banner/navbar"
107
+ files = Dir.entries(dir) - %w[. .. navbar.lt3]
108
+ main_file = "[ navbar.lt3 ]"
109
+ new_item = " [New item] "
110
+ files = [main_file] + files + [new_item]
111
+ num, fname = STDSCR.menu(title: "Edit navbar:", items: files)
112
+ return if fname.nil?
113
+ case fname
114
+ when new_item
115
+ print "Page title: "
116
+ title = RubyText.gets
117
+ title.chomp!
118
+ print "File name (.lt3): "
119
+ fname = RubyText.gets
120
+ fname << ".lt3" unless fname.end_with?(".lt3")
121
+ new_file = dir/fname
122
+ File.open(new_file, "w") do |f|
123
+ f.puts "<h1>#{title}</h1>\n\n\n "
124
+ f.puts ".backlink"
125
+ end
126
+ edit_file(new_file)
127
+ when main_file
128
+ edit_file(main_file[2..-3])
129
+ else
130
+ edit_file(dir/fname)
131
+ end
132
+ end
133
+
134
+ def _manage_links(arg, testing = false)
135
+ dir = @blog.view.dir/"themes/standard/widgets/links"
136
+ data = dir/"list.data"
137
+ edit_file(data)
138
+ end
139
+
140
+ def _manage_pages(arg, testing = false)
141
+ dir = @blog.view.dir/"themes/standard/widgets/pages"
142
+ # Assume child files already generated (and list.data??)
143
+ data = dir/"list.data"
144
+ lines = _get_data?(data)
145
+ hash = {}
146
+ lines.each do |line|
147
+ url, name = line.chomp.split(",")
148
+ source = url.sub(/.html$/, ".lt3")
149
+ hash[name] = source
150
+ end
151
+ new_item = "[New page]"
152
+ num, fname = STDSCR.menu(title: "Edit page:", items: hash.keys + [new_item])
153
+ return if fname.nil?
154
+ if fname == new_item
155
+ print "Page title: "
156
+ title = RubyText.gets
157
+ title.chomp!
158
+ print "File name (.lt3): "
159
+ fname = RubyText.gets
160
+ fname << ".lt3" unless fname.end_with?(".lt3")
161
+ fhtml = fname.sub(/.lt3$/, ".html")
162
+ File.open(data, "a") {|f| f.puts "#{fhtml},#{title}" }
163
+ new_file = dir/fname
164
+ File.open(new_file, "w") do |f|
165
+ f.puts "<h1>#{title}</h1>\n\n\n "
166
+ f.puts ".backlink"
167
+ end
168
+ edit_file(new_file)
169
+ else
170
+ target = hash[fname]
171
+ edit_file(dir/target)
172
+ end
173
+ end
174
+
175
+ def cmd_import(arg, testing = false)
176
+ files = ask("\n File(s) = ")
177
+ system!("cp #{files} #{@blog.root}/views/#{@blog.view.name}/assets/")
178
+ end
179
+
180
+ def cmd_browse(arg, testing = false)
181
+ reset_output
182
+ url = @blog.view.publisher.url
183
+ if url.nil?
184
+ output! "Publish first."
185
+ puts "\n Publish first."
186
+ return @out
187
+ end
188
+ result = system!("open '#{url}'")
189
+ raise CantOpen(url) unless result
190
+ return @out
191
+ end
192
+
193
+ def cmd_preview(arg, testing = false)
194
+ reset_output
195
+ local = @blog.view.local_index
196
+ unless File.exist?(local)
197
+ puts "\n No index. Rebuilding..."
198
+ cmd_rebuild(nil)
199
+ end
200
+ result = system!("open #{local}")
201
+ raise CantOpen(local) unless result
202
+ @out
203
+ rescue => err
204
+ out = "/tmp/blog#{rand(100)}.txt"
205
+ File.open(out, "w") do |f|
206
+ f.puts err
207
+ f.puts err.backtrace.join("\n")
208
+ end
209
+ puts "Error: See #{out}"
210
+ end
211
+
212
+ def cmd_publish(arg, testing = false)
213
+ # Future Hal says please refactor this
214
+ puts unless testing
215
+ reset_output
216
+ unless @blog.view.can_publish?
217
+ msg = "Can't publish... see global.lt3"
218
+ puts msg unless testing
219
+ output! msg
220
+ return @out
221
+ end
222
+
223
+ ret = RubyText.spinner(label: " Publishing... ") do
224
+ @blog.view.publisher.publish
225
+ end
226
+ return @out unless ret
227
+
228
+ vdir = @blog.view.dir
229
+ dump("fix this later", "#{vdir}/last_published")
230
+ if ! testing || ! ret
231
+ puts " ...finished.\n "
232
+ output! "...finished.\n"
233
+ end
234
+ return @out
235
+ rescue => err
236
+ out = "/tmp/blog#{rand(100)}.txt"
237
+ File.open(out, "w") do |f|
238
+ f.puts err
239
+ f.puts err.backtrace.join("\n")
240
+ end
241
+ puts "Error: See #{out}"
242
+ end
243
+
244
+ def fresh?(src, dst)
245
+ return false unless File.exist?(dst)
246
+ File.mtime(src) <= File.mtime(dst)
247
+ end
248
+
249
+ def regen_posts
250
+ drafts = @blog.drafts # current view
251
+ drafts.each do |draft|
252
+ orig = @blog.root/:drafts/draft
253
+ html = @blog.root/:posts/draft
254
+ html.sub!(/.lt3$/, "/guts.html")
255
+ next if fresh?(orig, html)
256
+ puts " Regenerating #{draft}"
257
+ @blog.generate_post(orig) # rebuild post
258
+ end
259
+ puts
260
+ end
261
+
262
+ def cmd_rebuild(arg, testing = false)
263
+ debug "Starting cmd_rebuild..."
264
+ reset_output
265
+ puts unless testing
266
+ @blog.generate_view(@blog.view)
267
+ @blog.generate_index(@blog.view)
268
+ regen_posts
269
+ @out
270
+ rescue => err
271
+ out = "/tmp/blog#{rand(100)}.txt"
272
+ File.open(out, "w") do |f|
273
+ f.puts err
274
+ f.puts err.backtrace.join("\n")
275
+ end
276
+ puts "Error: See #{out}"
277
+ end
278
+
279
+ def cmd_change_view(arg, testing = false)
280
+ reset_output
281
+ # Simplify this
282
+ if arg.nil?
283
+ viewnames = @blog.views.map {|x| x.name }
284
+ n = viewnames.find_index(@blog.view.name)
285
+ name = @blog.view.name
286
+ # TODO: Add view description
287
+ k, name = STDSCR.menu(title: "Views", items: viewnames, curr: n) unless testing
288
+ return if name.nil?
289
+ @blog.view = name
290
+ output name + "\n"
291
+ puts "\n ", fx(name, :bold), "\n" unless testing
292
+ return @out
293
+ else
294
+ if @blog.view?(arg)
295
+ @blog.view = arg
296
+ output "View: " + @blog.view.name.to_s
297
+ puts "\n ", fx(arg, :bold), "\n" unless testing
298
+ end
299
+ end
300
+ return @out
301
+ end
302
+
303
+ def cmd_new_view(arg, testing = false)
304
+ reset_output
305
+ if arg.nil?
306
+ arg = ask(fx("\nFilename: ", :bold))
307
+ puts
308
+ end
309
+ @blog.create_view(arg)
310
+ text = File.read("#{@blog.root}/data/global.lt3")
311
+ File.write("#{@blog.root}/views/#{@blog.view}/themes/standard/global.lt3",
312
+ text.gsub(/VIEW_NAME/, @blog.view.to_s))
313
+ vim_params = '-c ":set hlsearch" -c ":hi Search ctermfg=2 ctermbg=6" +/"\(VIEW_.*\|SITE.*\)"'
314
+ edit_file(@blog.view.dir/"themes/standard/global.lt3", vim: vim_params)
315
+ @blog.change_view(arg)
316
+ @out
317
+ rescue ViewAlreadyExists
318
+ puts 'Blog already exists'
319
+ rescue => err
320
+ out = "/tmp/blog#{rand(100)}.txt"
321
+ File.open(out, "w") do |f|
322
+ f.puts err
323
+ f.puts err.backtrace.join("\n")
324
+ end
325
+ puts "Error: See #{out}"
326
+ end
327
+
328
+ def cmd_new_post(arg, testing = false)
329
+ reset_output
330
+ if @blog.views.empty?
331
+ puts "\n Create a view before creating the first post!\n "
332
+ return
333
+ end
334
+ title = ask("\nTitle: ")
335
+ puts
336
+ @blog.create_new_post(title)
337
+ # STDSCR.clear
338
+ @out
339
+ rescue => err
340
+ out = "/tmp/blog#{rand(100)}.txt"
341
+ File.open(out, "w") do |f|
342
+ f.puts err
343
+ f.puts err.backtrace.join("\n")
344
+ end
345
+ puts "Error: See #{out}"
346
+ end
347
+
348
+ def _remove_post(arg, testing=false)
349
+ id = get_integer(arg)
350
+ result = @blog.remove_post(id)
351
+ puts "Post #{id} not found" if result.nil?
352
+ end
353
+
354
+ def cmd_remove_post(arg, testing = false)
355
+ reset_output
356
+ args = arg.split
357
+ args.each do |x|
358
+ # FIXME
359
+ ret = _remove_post(x.to_i, false)
360
+ puts ret
361
+ output ret
362
+ end
363
+ @out
364
+ end
365
+
366
+ def cmd_edit_post(arg, testing = false)
367
+ reset_output
368
+ id = get_integer(arg)
369
+ # Simplify this
370
+ tag = "#{'%04d' % id}"
371
+ files = ::Find.find(@blog.root/:drafts).to_a
372
+ files = files.grep(/#{tag}-.*lt3/)
373
+ files = files.map {|f| File.basename(f) }
374
+ if files.size > 1
375
+ msg = "Multiple files: #{files}"
376
+ output msg
377
+ puts msg unless testing
378
+ return [false, msg]
379
+ end
380
+ if files.empty?
381
+ msg = "\n Can't edit post #{id}"
382
+ output msg
383
+ puts msg unless testing
384
+ return [false, msg]
385
+ end
386
+
387
+ file = files.first
388
+ draft = @blog.root/:drafts/file
389
+ vim_params = '-c G'
390
+ result = edit_file(draft)
391
+ @blog.generate_post(draft)
392
+ rescue => err
393
+ out = "/tmp/blog#{rand(100)}.txt"
394
+ File.open(out, "w") do |f|
395
+ f.puts err
396
+ f.puts err.backtrace.join("\n")
397
+ end
398
+ puts "Error: See #{out}"
399
+ end
400
+
401
+ def cmd_list_views(arg, testing = false)
402
+ reset_output("\n")
403
+ puts unless testing
404
+ @blog.views.each do |v|
405
+ v = v.to_s
406
+ v = fx(v, :bold) if v == @blog.view.name
407
+ output v + "\n"
408
+ # FIXME: next 3 lines are crufty as hell
409
+ lines = File.readlines(@blog.root/"views/#{v}/themes/standard/global.lt3")
410
+ lines = lines.select {|x| x =~ /^blog / && x !~ /VIEW_/ }
411
+ title = lines.first.split(" ", 2)[1]
412
+ print " ", ('%15s' % v) unless testing
413
+ puts " ", fx(title, :black) unless testing
414
+ end
415
+ puts unless testing
416
+ # @out
417
+ end
418
+
419
+ def cmd_list_posts(arg, testing = false)
420
+ reset_output
421
+ posts = @blog.posts # current view
422
+ str = @blog.view.name + ":\n"
423
+ output str
424
+ puts unless testing
425
+ puts " ", fx(str, :bold) unless testing
426
+ if posts.empty?
427
+ output! "No posts"
428
+ puts " No posts" unless testing
429
+ else
430
+ posts.each do |post|
431
+ outstr " #{colored_slug(post)}\n"
432
+ base = post.sub(/.lt3$/, "")
433
+ num, rest = base[0..3], base[4..-1]
434
+ puts " ", fx(num, Red), fx(rest, Blue) unless testing
435
+ draft = @blog.root/:drafts/post + ".lt3"
436
+ other = @blog._get_views(draft) - [@blog.view.to_s]
437
+ unless other.empty?
438
+ print fx(" "*7 + "also in: ", :bold)
439
+ puts other.join(", ")
440
+ end
441
+ end
442
+ end
443
+ puts unless testing
444
+ @out
445
+ end
446
+
447
+ def cmd_list_drafts(arg, testing = false)
448
+ reset_output
449
+ drafts = @blog.drafts # current view
450
+ if drafts.empty?
451
+ output! "No drafts"
452
+ puts "\n No drafts\n " unless testing
453
+ return @out
454
+ else
455
+ puts unless testing
456
+ drafts.each do |draft|
457
+ outstr " #{colored_slug(draft.sub(/.lt3$/, ""))}\n"
458
+ base = draft.sub(/.lt3$/, "")
459
+ num, rest = base[0..3], base[4..-1]
460
+ puts " ", fx(num, Red), fx(rest, Blue) unless testing
461
+ other = @blog._get_views(@blog.root/:drafts/draft) - [@blog.view.to_s]
462
+ unless other.empty?
463
+ print fx(" "*7 + "also in: ", :bold)
464
+ puts other.join(", ")
465
+ end
466
+ end
467
+ end
468
+ puts unless testing
469
+ @out
470
+ end
471
+
472
+ def cmd_list_assets(arg, testing = false)
473
+ reset_output
474
+ dir = @blog.view.dir + "/assets"
475
+ assets = Dir[dir + "/*"]
476
+ if assets.empty?
477
+ output! "No assets"
478
+ puts " No assets" unless testing
479
+ return @out
480
+ else
481
+ puts unless testing
482
+ assets.each do |name|
483
+ asset = File.basename(name)
484
+ outstr asset
485
+ puts " ", fx(asset, Blue) unless testing
486
+ end
487
+ end
488
+ puts unless testing
489
+ @out
490
+ end
491
+
492
+ def cmd_ssh(arg, testing = false)
493
+ pub = @blog.view.publisher
494
+ puts
495
+ system!("tputs clear; ssh #{pub.user}@#{pub.server}")
496
+ sleep 0.1
497
+ cmd_clear(nil)
498
+ end
499
+
500
+ def cmd_INVALID(arg, testing = false)
501
+ reset_output "\n Command '#{arg}' was not understood."
502
+ print fx("\n Command ", :bold)
503
+ print fx(arg, Red, :bold)
504
+ puts fx(" was not understood.\n ", :bold)
505
+ @out
506
+ end
507
+
508
+ def cmd_legacy(arg = nil)
509
+ # dir = ask("Dir = ")
510
+ dir = "sources/computing"
511
+ puts "Importing from: #{dir}"
512
+ files = Dir[dir/"**"]
513
+ files.each do |fname|
514
+ name = fname
515
+ cmd = "grep ^.title #{name}"
516
+ grep = `#{cmd}` # find .title
517
+ @title = grep.sub(/^.title /, "")
518
+ num = `grep ^.post #{name}`.sub(/^.post /, "").to_i
519
+ seq = @blog.get_sequence
520
+ tnum = File.basename(fname).to_i
521
+
522
+ raise "num != seq + 1" if num != seq + 1
523
+ raise "num != tnum" if num != tnum
524
+ seq = @blog.next_sequence
525
+ raise "num != seq" if num != seq
526
+
527
+ label = '%04d' % num
528
+ slug0 = @title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
529
+ @slug = "#{label}-#{slug0}"
530
+ @fname = @slug + ".lt3"
531
+ cmd = "cp #{name} #{@blog.root}/drafts/#@fname"
532
+ result = system!(cmd)
533
+ raise CantCopy(name, "#{@blog.root}/drafts/#@fname") unless result
534
+ # post = Post.load(@slug)
535
+ draft = "#{@blog.root}/drafts/#@fname"
536
+ @meta = @blog.generate_post(draft)
537
+ puts
538
+ sleep 2
539
+ end
540
+ rescue => err
541
+ error(err)
542
+ end
543
+
544
+ Help = <<-EOS
545
+
546
+ {Basics:} {Views:}
547
+ ------------------------------------------- -------------------------------------------
548
+ {h, help} This message {change view VIEW} Change current view
549
+ {q, quit} Exit the program {cv VIEW} Change current view
550
+ {v, version} Print version information {new view} Create a new view
551
+ {clear} Clear screen {list views} List all views available
552
+ {lsv} Same as: list views
553
+
554
+
555
+ {Posts:} {Advanced:}
556
+ ------------------------------------------- -------------------------------------------
557
+ {p, post} Create a new post {config} Edit various system files
558
+ {new post} Same as p, post {customize} (BUGGY) Change set of tags, extra views
559
+ {lsp, list posts} List posts in current view {preview} Look at current (local) view in browser
560
+ {lsd, list drafts} List all drafts (all views) {browse} Look at current (published) view in browser
561
+ {delete ID [ID...]} Remove multiple posts {rebuild} Regenerate all posts and relink
562
+ {undelete ID} Undelete a post {publish} Publish (current view)
563
+ {edit ID} Edit a post {ssh} Login to remote server
564
+ {import ASSETS} Import assets (images, etc.) {manage WIDGET} Manage content/layout of a widget
565
+ EOS
566
+
567
+ def cmd_help(arg, testing = false)
568
+ reset_output
569
+ msg = Help
570
+ output msg
571
+ msg.each_line do |line|
572
+ e = line.each_char
573
+ first = true
574
+ loop do
575
+ s1 = ""
576
+ c = e.next
577
+ if c == "{"
578
+ s2 = first ? "" : " "
579
+ first = false
580
+ loop do
581
+ c = e.next
582
+ break if c == "}"
583
+ s2 << c
584
+ end
585
+ print fx(s2, :bold)
586
+ s2 = ""
587
+ else
588
+ s1 << c
589
+ end
590
+ print s1
591
+ end
592
+ end
593
+ puts unless testing
594
+ @out
595
+ end
596
+ end
597
+