scriptorium 0.0.3 → 0.7.2

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 (353) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +324 -0
  3. data/README.md +3155 -1
  4. data/assets/.DS_Store +0 -0
  5. data/assets/README.md +44 -0
  6. data/assets/icons/social/reddit.png +0 -0
  7. data/assets/icons/social/x-logo.png +0 -0
  8. data/assets/icons/ui/.DS_Store +0 -0
  9. data/assets/icons/ui/back.png +0 -0
  10. data/assets/icons/ui/copy.png +0 -0
  11. data/assets/icons/ui/down.png +0 -0
  12. data/assets/icons/ui/end.png +0 -0
  13. data/assets/icons/ui/exit.png +0 -0
  14. data/assets/icons/ui/foo +10 -0
  15. data/assets/icons/ui/home.png +0 -0
  16. data/assets/icons/ui/left.png +0 -0
  17. data/assets/icons/ui/next.png +0 -0
  18. data/assets/icons/ui/right.png +0 -0
  19. data/assets/icons/ui/start.png +0 -0
  20. data/assets/icons/ui/up.png +0 -0
  21. data/assets/imagenotfound.jpg +0 -0
  22. data/assets/samples/placeholder.svg +9 -0
  23. data/assets/themes/standard/favicon.svg +6 -0
  24. data/bin/sblog +84 -5
  25. data/bin/scriptorium +1 -0
  26. data/doc/README.txt +6 -0
  27. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +94 -0
  28. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +2 -0
  29. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +45 -0
  30. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
  31. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
  32. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
  33. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +35 -0
  34. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +27 -0
  35. data/doc/anti-amnesia/20250807-213025.md +116 -0
  36. data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
  37. data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
  38. data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
  39. data/doc/banner_svg_config.md +114 -0
  40. data/doc/contrib.lt3 +8 -0
  41. data/doc/dependencies.md +281 -0
  42. data/doc/hacker.lt3 +5 -0
  43. data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
  44. data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
  45. data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
  46. data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
  47. data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
  48. data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
  49. data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
  50. data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
  51. data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
  52. data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
  53. data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
  54. data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
  55. data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
  56. data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
  57. data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
  58. data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
  59. data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
  60. data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
  61. data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
  62. data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
  63. data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
  64. data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
  65. data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
  66. data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
  67. data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
  68. data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
  69. data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
  70. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
  71. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
  72. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
  73. data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
  74. data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
  75. data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
  76. data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
  77. data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
  78. data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
  79. data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
  80. data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
  81. data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
  82. data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
  83. data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
  84. data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
  85. data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
  86. data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
  87. data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
  88. data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
  89. data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
  90. data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
  91. data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
  92. data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
  93. data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
  94. data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
  95. data/doc/imported/0018-ruby-puns/post.html +46 -0
  96. data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
  97. data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
  98. data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
  99. data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
  100. data/doc/imported/0020-fffff/metadata.txt +7 -0
  101. data/doc/imported/0020-fffff/post.html +24 -0
  102. data/doc/imported/0020-fffff/source.lt3 +12 -0
  103. data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
  104. data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
  105. data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
  106. data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
  107. data/doc/imported/0023-doctor-sleep/post.html +63 -0
  108. data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
  109. data/doc/imported/0024-just-a-test/metadata.txt +7 -0
  110. data/doc/imported/0024-just-a-test/post.html +24 -0
  111. data/doc/imported/0024-just-a-test/source.lt3 +12 -0
  112. data/doc/imported/import_summary.txt +98 -0
  113. data/doc/livetext-informal-spec.txt +65 -0
  114. data/doc/myuserdoc/ch-0.lt3 +31 -0
  115. data/doc/myuserdoc/ch-1.lt3 +37 -0
  116. data/doc/myuserdoc/ch-10.lt3 +22 -0
  117. data/doc/myuserdoc/ch-2.lt3 +37 -0
  118. data/doc/myuserdoc/ch-3.lt3 +19 -0
  119. data/doc/myuserdoc/ch-4.lt3 +43 -0
  120. data/doc/myuserdoc/ch-5.lt3 +22 -0
  121. data/doc/myuserdoc/ch-6.lt3 +19 -0
  122. data/doc/myuserdoc/ch-7.lt3 +16 -0
  123. data/doc/myuserdoc/ch-8.lt3 +13 -0
  124. data/doc/myuserdoc/ch-9.lt3 +19 -0
  125. data/doc/myuserdoc/tweak.rb +18 -0
  126. data/doc/myuserdoc/userdoc-toc.txt +88 -0
  127. data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
  128. data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
  129. data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
  130. data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
  131. data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
  132. data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
  133. data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
  134. data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
  135. data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
  136. data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
  137. data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
  138. data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
  139. data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
  140. data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
  141. data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
  142. data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
  143. data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
  144. data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
  145. data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
  146. data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
  147. data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
  148. data/doc/old-posts/0024-just-a-test.lt3 +12 -0
  149. data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
  150. data/doc/old-repo +1 -0
  151. data/doc/reddit_credentials_template.json +8 -0
  152. data/doc/reddit_integration.md +207 -0
  153. data/doc/user.lt3 +35 -0
  154. data/doc/user_guide_section_1.md +137 -0
  155. data/doc/user_guide_section_10.md +515 -0
  156. data/doc/user_guide_section_11.md +708 -0
  157. data/doc/user_guide_section_2.md +233 -0
  158. data/doc/user_guide_section_3.md +5 -0
  159. data/doc/user_guide_section_4.md +221 -0
  160. data/doc/user_guide_section_5.md +243 -0
  161. data/doc/user_guide_section_6.md +147 -0
  162. data/doc/user_guide_section_7.md +311 -0
  163. data/doc/user_guide_section_8.md +224 -0
  164. data/doc/user_guide_section_9.md +375 -0
  165. data/lib/rouge/lexers/livetext.rb +74 -0
  166. data/lib/scriptorium/api.rb +2373 -0
  167. data/lib/scriptorium/banner_svg.rb +729 -0
  168. data/lib/scriptorium/contract.rb +34 -0
  169. data/lib/scriptorium/exceptions.rb +201 -1
  170. data/lib/scriptorium/helpers.rb +675 -0
  171. data/lib/scriptorium/post.rb +259 -0
  172. data/lib/scriptorium/reddit.rb +83 -0
  173. data/lib/scriptorium/repo.rb +938 -0
  174. data/lib/scriptorium/standard_files.rb +149 -0
  175. data/lib/scriptorium/support/bootstrap/css.txt +5 -0
  176. data/lib/scriptorium/support/bootstrap/js.txt +4 -0
  177. data/lib/scriptorium/support/common_js/clipboard.js +35 -0
  178. data/lib/scriptorium/support/common_js/content-loader.js +187 -0
  179. data/lib/scriptorium/support/common_js/navigation.js +52 -0
  180. data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
  181. data/lib/scriptorium/support/config/reddit.txt +10 -0
  182. data/lib/scriptorium/support/config/reddit_template.txt +17 -0
  183. data/lib/scriptorium/support/config/social.txt +8 -0
  184. data/lib/scriptorium/support/highlight/css.txt +2 -0
  185. data/lib/scriptorium/support/highlight/custom.css +119 -0
  186. data/lib/scriptorium/support/highlight/js.txt +1 -0
  187. data/lib/scriptorium/support/post_index/config.txt +15 -0
  188. data/lib/scriptorium/support/post_index/style.css +55 -0
  189. data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
  190. data/lib/scriptorium/support/templates/initial_post.lt3 +12 -0
  191. data/lib/scriptorium/support/templates/layout.txt +5 -0
  192. data/lib/scriptorium/support/templates/post.lt3 +104 -0
  193. data/lib/scriptorium/support/theme/footer.lt3 +2 -0
  194. data/lib/scriptorium/support/theme/header.lt3 +4 -0
  195. data/lib/scriptorium/support/theme/left.lt3 +3 -0
  196. data/lib/scriptorium/support/theme/main.lt3 +5 -0
  197. data/lib/scriptorium/support/theme/right.lt3 +3 -0
  198. data/lib/scriptorium/theme.rb +192 -0
  199. data/lib/scriptorium/version.rb +1 -1
  200. data/lib/scriptorium/view.rb +1021 -0
  201. data/lib/scriptorium/widgets/featured_posts.rb +149 -0
  202. data/lib/scriptorium/widgets/links.rb +112 -0
  203. data/lib/scriptorium/widgets/pages.rb +133 -0
  204. data/lib/scriptorium/widgets/widget.rb +133 -0
  205. data/lib/scriptorium.rb +38 -34
  206. data/lib/skeleton.rb +10 -1
  207. data/scriptorium.gemspec +17 -5
  208. data/test/README.md +69 -0
  209. data/test/WEB_INTEGRATION_README.md +196 -0
  210. data/test/all +83 -0
  211. data/test/api_demo.rb +99 -0
  212. data/test/assets/imagenotfound.jpg +0 -0
  213. data/test/assets/images/.DS_Store +0 -0
  214. data/test/assets/images/README.md +27 -0
  215. data/test/assets/images/odd_aspect.png +0 -0
  216. data/test/assets/images/perfect.png +0 -0
  217. data/test/assets/images/small.png +0 -0
  218. data/test/assets/images/tall.png +0 -0
  219. data/test/assets/images/very_tall.png +0 -0
  220. data/test/assets/images/very_wide.png +0 -0
  221. data/test/assets/images/wide.png +0 -0
  222. data/test/assets/testbanner.jpg +0 -0
  223. data/test/banner_svg/simple_helpers.rb +13 -0
  224. data/test/banner_svg/unit.rb +1000 -0
  225. data/test/config/deployment.txt +5 -0
  226. data/test/ed_test.rb +204 -0
  227. data/test/integration/cursor_banner_combinations.rb +193 -0
  228. data/test/integration/cursor_banner_features.rb +374 -0
  229. data/test/integration/integration_test.rb +326 -0
  230. data/test/integration/preview_flow_test.rb +94 -0
  231. data/test/livetext_plugin_test.rb +500 -0
  232. data/test/manual/asset_mgmt.rb +67 -0
  233. data/test/manual/banner-tests/index.html +45 -0
  234. data/test/manual/banner-tests/svg.txt +3 -0
  235. data/test/manual/banner-tests/test01.html +122 -0
  236. data/test/manual/banner-tests/test02.html +122 -0
  237. data/test/manual/banner-tests/test03.html +122 -0
  238. data/test/manual/banner-tests/test04.html +129 -0
  239. data/test/manual/banner-tests/test05.html +129 -0
  240. data/test/manual/banner-tests/test06.html +129 -0
  241. data/test/manual/banner-tests/test07.html +129 -0
  242. data/test/manual/banner-tests/test08.html +123 -0
  243. data/test/manual/banner-tests/test09.html +123 -0
  244. data/test/manual/banner-tests/test10.html +123 -0
  245. data/test/manual/banner-tests/test11.html +123 -0
  246. data/test/manual/banner-tests/test12.html +123 -0
  247. data/test/manual/banner-tests/test13.html +123 -0
  248. data/test/manual/banner-tests/test14.html +123 -0
  249. data/test/manual/banner-tests/test15.html +122 -0
  250. data/test/manual/banner-tests/test16.html +122 -0
  251. data/test/manual/banner-tests/test17.html +122 -0
  252. data/test/manual/banner-tests/test18.html +132 -0
  253. data/test/manual/banner-tests/test19.html +132 -0
  254. data/test/manual/banner-tests/test20.html +132 -0
  255. data/test/manual/banner-tests/test21.html +132 -0
  256. data/test/manual/banner-tests/test22.html +132 -0
  257. data/test/manual/banner-tests/test23.html +132 -0
  258. data/test/manual/banner-tests/test24.html +132 -0
  259. data/test/manual/banner-tests/test25.html +131 -0
  260. data/test/manual/banner_environment.rb +205 -0
  261. data/test/manual/codemirror_demo.html +773 -0
  262. data/test/manual/create_posts_for_web.rb +114 -0
  263. data/test/manual/environment.rb +67 -0
  264. data/test/manual/make_banner.rb +153 -0
  265. data/test/manual/preview_manual_test.rb +129 -0
  266. data/test/manual/sample_banner_config.txt +12 -0
  267. data/test/manual/test_advanced_widgets.rb +73 -0
  268. data/test/manual/test_banner_combinations.rb +120 -0
  269. data/test/manual/test_banner_features.rb +306 -0
  270. data/test/manual/test_banner_integration.rb +115 -0
  271. data/test/manual/test_banner_radial.rb +87 -0
  272. data/test/manual/test_basic_posts.rb +47 -0
  273. data/test/manual/test_layout_widgets.rb +40 -0
  274. data/test/manual/test_pagination.rb +24 -0
  275. data/test/manual/test_random_posts.rb +38 -0
  276. data/test/manual/test_syntax_highlighting.rb +167 -0
  277. data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
  278. data/test/rubytext/rubytext_demo_test.rb +42 -0
  279. data/test/rubytext/rubytext_testing_guide.md +277 -0
  280. data/test/run_automated_tests.rb +45 -0
  281. data/test/staging/.DS_Store +0 -0
  282. data/test/support/preview_utils.rb +88 -0
  283. data/test/syntax_highlighting_test.lt3 +124 -0
  284. data/test/test_gem_assets.rb +48 -0
  285. data/test/test_helpers.rb +240 -0
  286. data/test/tui_editor_integration_test.rb +296 -0
  287. data/test/tui_integration_test.rb +883 -0
  288. data/test/unit/api.rb +1776 -0
  289. data/test/unit/asset_management.rb +219 -0
  290. data/test/unit/backup_test.rb +451 -0
  291. data/test/unit/clipboard_test.rb +60 -0
  292. data/test/unit/contract_test.rb +69 -0
  293. data/test/unit/core.rb +1211 -0
  294. data/test/unit/deploy_config_test.rb +248 -0
  295. data/test/unit/deploy_test.rb +478 -0
  296. data/test/unit/edit_post_test.rb +168 -0
  297. data/test/unit/gem_asset_management.rb +183 -0
  298. data/test/unit/livetext_basic.rb +57 -0
  299. data/test/unit/livetext_compatibility.rb +82 -0
  300. data/test/unit/parse_cmd_test.rb +260 -0
  301. data/test/unit/permalink_copy_test.rb +211 -0
  302. data/test/unit/post.rb +309 -0
  303. data/test/unit/post_index_config_test.rb +258 -0
  304. data/test/unit/post_state_helpers_test.rb +137 -0
  305. data/test/unit/read_commented_file_test.rb +278 -0
  306. data/test/unit/reddit_test.rb +235 -0
  307. data/test/unit/repo.rb +569 -0
  308. data/test/unit/social_test.rb +366 -0
  309. data/test/unit/syntax_highlighting.rb +70 -0
  310. data/test/unit/theme_management_test.rb +91 -0
  311. data/test/unit/view.rb +498 -0
  312. data/test/unit/widgets.rb +669 -0
  313. data/test/web_integration_test.rb +231 -0
  314. data/test/web_test_helper.rb +218 -0
  315. data/test/web_workflow_test.rb +527 -0
  316. data/test/wizard_test.rb +123 -0
  317. data/ui/README.md +67 -0
  318. data/ui/common/lib/ui_common.rb +8 -0
  319. data/ui/rubytext/README.md +191 -0
  320. data/ui/rubytext/bin/scriptorium-rubytext +402 -0
  321. data/ui/rubytext/lib/rubytext_ui.rb +300 -0
  322. data/ui/tui/bin/scriptorium +1890 -0
  323. data/ui/tui/test/tui_test.rb +23 -0
  324. data/ui/web/app/app.rb +2600 -0
  325. data/ui/web/app/assets/livetext_mode.js +244 -0
  326. data/ui/web/app/error_helpers.rb +150 -0
  327. data/ui/web/app/views/advanced_config.erb +196 -0
  328. data/ui/web/app/views/asset_management.erb +645 -0
  329. data/ui/web/app/views/backup_management.erb +238 -0
  330. data/ui/web/app/views/banner_config.erb +200 -0
  331. data/ui/web/app/views/config_widget.erb +232 -0
  332. data/ui/web/app/views/configure_view.erb +401 -0
  333. data/ui/web/app/views/dashboard.erb +154 -0
  334. data/ui/web/app/views/deploy_config.erb +149 -0
  335. data/ui/web/app/views/edit_pages.erb +363 -0
  336. data/ui/web/app/views/edit_post.erb +175 -0
  337. data/ui/web/app/views/edit_theme.erb +73 -0
  338. data/ui/web/app/views/edit_theme_file.erb +74 -0
  339. data/ui/web/app/views/error_page.erb +29 -0
  340. data/ui/web/app/views/header_config.erb +155 -0
  341. data/ui/web/app/views/layout_config.erb +147 -0
  342. data/ui/web/app/views/navbar_config.erb +411 -0
  343. data/ui/web/app/views/theme_management.erb +130 -0
  344. data/ui/web/app/views/view_dashboard.erb +779 -0
  345. data/ui/web/app/views/widgets.erb +249 -0
  346. data/ui/web/bin/scriptorium-web +164 -0
  347. data/ui/web/test/web_basic_test.rb +38 -0
  348. data/ui/web/test_navbar.txt +7 -0
  349. data/ui/web/tmp/timing.log +17 -0
  350. data/ui/web/tmp/web_server.log +0 -0
  351. metadata +434 -8
  352. data/lib/scriptorium/engine.rb +0 -22
  353. data/test/engine/unit.rb +0 -44
@@ -0,0 +1,87 @@
1
+ .h1 Phoenix isn't Rails
2
+
3
+ .set post.num = 0007
4
+ .set post.slug = phoenix-isnt-rails
5
+ .set post.date = 2015-07-27
6
+ .set post.title = Phoenix isn't Rails
7
+ .set post.tags =
8
+ .set post.views = computing
9
+ .set post.published = yes
10
+ .set post.deployed = no
11
+
12
+ I don't know Elixir very well at all. But I've started to learn Phoenix now. The
13
+ first thing to know: Phoenix is not Ruby on Rails (nor is it "Elixir on Rails").
14
+ I began my learning experience by dutifully crunching through the tutorial and
15
+ making my share (at least) of newbie mistakes. (Disclaimer: I'm not a web guy. I
16
+ don't natively "think" in those terms and perhaps never will.)
17
+
18
+ At some point in the hello-world example, I stopped and did a count of the files
19
+ under my tree. It will become clear in a moment why this was a little naive and
20
+ careless.
21
+
22
+ At any rate, I think find . | wc -lreported 11,648 files to me. I found this
23
+ a bit confusing and puzzling, and I didn't think it through.
24
+
25
+ I chatted with Chris McCord and another guy I don't think I've met. This is a summary:
26
+
27
+ hal_9000: chrismccord: I have a question about the philosophy/design
28
+ of phoenix - if you have time/inclination and the answer is not too involved
29
+
30
+ chrismccord: hal_9000: shoot
31
+
32
+ hal_9000: first of all, i’m not a web guy - i’ve played with rails and several
33
+ other things - wrote a few small apps. One thing that appealed to me
34
+ about Sinatra was how “lightweight” it was compared to Rails — you can
35
+ write a primitive Sinatra app in a single file.
36
+ hal_9000: i “sort of” expected that Phoenix might be that way — but a find piped
37
+ to wc showed me that a hello-world app has more than 11,000 files in it.
38
+ why in general is that?
39
+
40
+ chrismccord: hal_9000: remove the node_modules folder and re-run ws
41
+ chrismccord: it's all nodejs for the asset building
42
+ chrismccord: hal_9000: we are lightweight. It's a misconception I have to keep correcting.
43
+ We are much closer to sinatra than rails
44
+
45
+ hal_9000: hmm, i don’t even know nodejs of course
46
+ hal_9000: chrismccord: thanks, i had a feeling i was missing something for sure
47
+
48
+ chrismccord: hal_9000: you could write an app in a single file, but no-one does that,
49
+ because we don't write production software in a single file
50
+ chrismccord: hal_9000: It is also worth mentioning there is also nothing global in
51
+ phoenix. We are not a monolith like rails
52
+
53
+ jeregrine: hal_9000: something to keep in mind here is that phoenix assumes you are
54
+ writing production software. Eventually you will need to touch every file, otherwise
55
+ it wouldn't generate the file
56
+
57
+ hal_9000: chrismccord: ok, thanks, i will look more closely. i’m impressed with what i see
58
+
59
+ jeregrine: hal_9000: if you are like me and have used sinatra for production software you
60
+ probably discovered you ended up writing a slightly smaller version of rails
61
+
62
+ hal_9000: jeregrine: that makes perfect sense
63
+
64
+ jeregrine: hal_9000: if you only need a single route/api call, and are certain it will never grow,
65
+ you could VERY easily get away with just plug and it's router
66
+ jeregrine: hal_9000: http://hexdocs.pm/plug/Plug.Router.html for reference.
67
+
68
+ hal_9000: chrismccord: i grasp it now, sorry for the noise
69
+
70
+ jeregrine: hal_9000: lemme know if you have any questions, this is something we need to be better at
71
+ communicating. We are not rails
72
+
73
+ chrismccord: hal_9000: no worries. Sorry if my response was rash too. I just have to fight a lot of
74
+ "phoenix is bloated" comments because people assume it is given my Rails background and
75
+ the comparisons with rails
76
+
77
+ hal_9000: chrismccord: no, your response was not rash at all
78
+
79
+ So first of all: I didn't pay attention to what I was doing when I did my file count.
80
+
81
+ But the real takeaway here is: Phoenix isn't bloated, and more importantly, Phoenix isn't Rails.
82
+ The philosophy seems to be more "minimalistic" as I had hoped.
83
+
84
+ And of course, we all know that Elixir isn't Ruby. I won't belabor that point.
85
+
86
+ On the other hand, I do find (so far) that Plug is a lot like Rack. That's a good thing, because I
87
+ always thought Rack was sheer genius. More on that as I learn.
@@ -0,0 +1,7 @@
1
+ num 0008
2
+ title Concerning the term "monkeypatching"
3
+ date 2015-08-10
4
+ pubdate 2015-08-10
5
+ views computing
6
+ tags
7
+ pinned
@@ -0,0 +1,129 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Concerning the term "monkeypatching"</title>
6
+ <meta name="generator" content="Scriptorium Import">
7
+ <meta property="og:title" content="Concerning the term "monkeypatching"">
8
+ <meta property="og:locale" content="en_US">
9
+ <meta property="og:type" content="article">
10
+ <meta property="article:published_time" content="2015-08-10">
11
+ </head>
12
+ <body>
13
+ <article>
14
+ <header>
15
+ <h1>Concerning the term "monkeypatching"</h1>
16
+ <time datetime="2015-08-10">August 10, 2015</time>
17
+ </header>
18
+
19
+ <div class="content">
20
+ <p>
21
+ There have been many "dark days" in the Ruby community, some much darker than others.
22
+ Guy Decoux died, _why the lucky stiff_ left us (without dying), Jim Weirich died. (Yes, I count
23
+ actual deaths as the darkest moments of all.)
24
+
25
+ <p>
26
+ But I count another dark moment that many of you will not. When I had been using Ruby a
27
+ little more than six years, in December 2005, the term "monkeypatching" was introduced
28
+ into our circle.
29
+
30
+ <p>
31
+ It was a post by Drew Mills, quoting a blog from a Python person who apparently hated Ruby.
32
+ I don't blame Drew. I don't suppose I "blame" anyone. But I regret that this slang has entered
33
+ our culture.
34
+
35
+ <p>
36
+ The post Drew quoted was this:
37
+
38
+ <p>
39
+ <blockquote>
40
+ It's the second generation that's going to be less enthused, that's going to stare in bafflement at these classes that mysteriously spawn methods, and trying to figure out what's going when there's an exception in dynamically generated code. You can monkeypatch code in Python pretty easily, but we look down on it enough that we call it "monkeypatching". In Ruby they call it "opening a class" and think it's a cool feature. I will assert: we are right, they are wrong.
41
+ </blockquote>
42
+ Before I go on to my main point, I'll make an observation that is arguably much more interesting.
43
+ If you read again, it sounds like the Python person (Ian Bicking) was talking about dynamic method
44
+ dispatch (the use or abuse of method_missing) rather than actual open classes.
45
+
46
+ <p>
47
+ Someone later in that thread decried the "ignorance" of Bicking with regard to this -- that he didn't
48
+ even know enough Ruby to know the difference between dynamic dispatch and open classes. I
49
+ wonder if the original pythonism meant something different? Since I never completed my Python
50
+ studies, I can't comment.
51
+
52
+ <p>
53
+ At any rate: Back to my story.
54
+
55
+ <p>
56
+ I still recall the revulsion I felt, almost physical nausea, when I read this the first time. That's probably
57
+ a somewhat extreme response on my part.
58
+
59
+ <p>
60
+ I regarded open classes as a programming technique that is potentially very powerful but easy to misuse.
61
+ This sounds like a "good and yet bad" argument. But let me rephrase that sentence.
62
+
63
+ <p>
64
+ Open classes are a technique that is potentially very powerful <i>(and</i> therefore) easy to misuse. That is
65
+ the point. Any tool that is powerful enough is prone to misuse by people who are unskilled.
66
+
67
+ <p>
68
+ The term "monkeypatching" is obviously a pejorative term. Upon seeing it, my first thought was, "I am
69
+ not a monkey, and I am not 'patching' anything."
70
+
71
+ <p>
72
+ After all, that is the implication. The term implies that the developer is a monkey, and that the work he is
73
+ doing is sloppy or shoddy. It is an insult both to the quality of the developer's work and to the developer
74
+ himself.
75
+
76
+ <p>
77
+ So it bothered me because it was a pejorative and it was insulting to us as programmers. It was also
78
+ (arguably) an insult to Ruby itself and therefore by extension an insult to Matz.
79
+
80
+ <p>
81
+ I dislike being clannish, though perhaps sometimes I am. After all, Ruby is not (supposed to be) anyone's
82
+ religion or cultural heritage. It's only a programming language, and I think it's very much like Python. But it
83
+ also bothered me that this neologism originated <i>outside</i> our community, in particular with the Python
84
+ community.
85
+
86
+ <p>
87
+ Generalizations are always wrong. (Yes, that's a joke.) And stereotypes as such are at least useless if not
88
+ actually hurtful. And yet I always heard about the arrogance and rudeness of Python programmers, and I
89
+ occasionally saw real evidence of it. And though I dislike the word "nice" in general, I always found it interesting
90
+ that Ruby coders were labeled as "nice" (as in the abbreviation MINASWAN, "Matz is nice, and so we are nice").
91
+
92
+ <p>
93
+ So when this usage was introduced, I felt rather as though someone had opened my front door and dumped a
94
+ large piece of dog manure onto my carpet. What is worse, it has wormed its way into common usage in our
95
+ community, even in documentation. A lot of this happened in the early days of Rails, when fate dumped a huge
96
+ influx of newbies onto the Ruby community. Not to disparage the Rails people in general, but at the time this
97
+ felt much the same as it did back when AOL (America Online) made its debut and dumped millions of (insert
98
+ noun here) into the Internet and Usenet communities.
99
+
100
+ <p>
101
+ It's impossible to stop this usage now (like so many other usages in the English language having nothing to do
102
+ with computing). But I still protest, and I still stand against it.
103
+
104
+ <p>
105
+ The term "monkeypatching" appears only once in more than 800 pages of <i>The Ruby Way</i>. It occurs when I
106
+ say I don't condone this term, and it won't be used further in the book.
107
+
108
+ <p>
109
+ As an aside: The "refinements" which exist in recent versions of Ruby make open classes stricter and safer. I'll blog
110
+ about that later. But this isn't much of a technical post. It's just a reminiscence and a rant.
111
+
112
+ <p>
113
+ So basically I hate the term "monkeypatching." I am polite to people who say it to me (e.g., in asking a question), but
114
+ secretly I want to just ignore them.
115
+
116
+ <p>
117
+ The last time I saw Jim Weirich, in New Orleans, he and I talked about this. He agreed it was a pejorative term,
118
+ and it was a shame it had entered the common dialect, though there was really nothing to do about it. But being
119
+ much more level-headed and good-natured than I am, he wasn't bothered much by it.
120
+
121
+ <p>
122
+ I really miss Jim, by the way. He was a truly brilliant developer and an amiable and wonderful person in general.
123
+ If it would bring him back, I would gladly change the book's name to <i>The Art of Monkeypatching</i>.
124
+
125
+ <p>
126
+ </div>
127
+ </article>
128
+ </body>
129
+ </html>
@@ -0,0 +1,92 @@
1
+ .h1 Concerning the term "monkeypatching"
2
+
3
+ .set post.num = 0008
4
+ .set post.slug = concerning-the-term-monkeypatching
5
+ .set post.date = 2015-08-10
6
+ .set post.title = Concerning the term "monkeypatching"
7
+ .set post.tags =
8
+ .set post.views = computing
9
+ .set post.published = yes
10
+ .set post.deployed = no
11
+
12
+ There have been many "dark days" in the Ruby community, some much darker than others.
13
+ Guy Decoux died, _why the lucky stiff_ left us (without dying), Jim Weirich died. (Yes, I count
14
+ actual deaths as the darkest moments of all.)
15
+
16
+ But I count another dark moment that many of you will not. When I had been using Ruby a
17
+ little more than six years, in December 2005, the term "monkeypatching" was introduced
18
+ into our circle.
19
+
20
+ It was a post by Drew Mills, quoting a blog from a Python person who apparently hated Ruby.
21
+ I don't blame Drew. I don't suppose I "blame" anyone. But I regret that this slang has entered
22
+ our culture.
23
+
24
+ The post Drew quoted was this:
25
+
26
+ It's the second generation that's going to be less enthused, that's going to stare in bafflement at these classes that mysteriously spawn methods, and trying to figure out what's going when there's an exception in dynamically generated code. You can monkeypatch code in Python pretty easily, but we look down on it enough that we call it "monkeypatching". In Ruby they call it "opening a class" and think it's a cool feature. I will assert: we are right, they are wrong.
27
+
28
+ Before I go on to my main point, I'll make an observation that is arguably much more interesting.
29
+ If you read again, it sounds like the Python person (Ian Bicking) was talking about dynamic method
30
+ dispatch (the use or abuse of method_missing) rather than actual open classes.
31
+
32
+ Someone later in that thread decried the "ignorance" of Bicking with regard to this -- that he didn't
33
+ even know enough Ruby to know the difference between dynamic dispatch and open classes. I
34
+ wonder if the original pythonism meant something different? Since I never completed my Python
35
+ studies, I can't comment.
36
+
37
+ At any rate: Back to my story.
38
+
39
+ I still recall the revulsion I felt, almost physical nausea, when I read this the first time. That's probably
40
+ a somewhat extreme response on my part.
41
+
42
+ I regarded open classes as a programming technique that is potentially very powerful but easy to misuse.
43
+ This sounds like a "good and yet bad" argument. But let me rephrase that sentence.
44
+
45
+ Open classes are a technique that is potentially very powerful (and therefore) easy to misuse. That is
46
+ the point. Any tool that is powerful enough is prone to misuse by people who are unskilled.
47
+
48
+ The term "monkeypatching" is obviously a pejorative term. Upon seeing it, my first thought was, "I am
49
+ not a monkey, and I am not 'patching' anything."
50
+
51
+ After all, that is the implication. The term implies that the developer is a monkey, and that the work he is
52
+ doing is sloppy or shoddy. It is an insult both to the quality of the developer's work and to the developer
53
+ himself.
54
+
55
+ So it bothered me because it was a pejorative and it was insulting to us as programmers. It was also
56
+ (arguably) an insult to Ruby itself and therefore by extension an insult to Matz.
57
+
58
+ I dislike being clannish, though perhaps sometimes I am. After all, Ruby is not (supposed to be) anyone's
59
+ religion or cultural heritage. It's only a programming language, and I think it's very much like Python. But it
60
+ also bothered me that this neologism originated outside our community, in particular with the Python
61
+ community.
62
+
63
+ Generalizations are always wrong. (Yes, that's a joke.) And stereotypes as such are at least useless if not
64
+ actually hurtful. And yet I always heard about the arrogance and rudeness of Python programmers, and I
65
+ occasionally saw real evidence of it. And though I dislike the word "nice" in general, I always found it interesting
66
+ that Ruby coders were labeled as "nice" (as in the abbreviation MINASWAN, "Matz is nice, and so we are nice").
67
+
68
+ So when this usage was introduced, I felt rather as though someone had opened my front door and dumped a
69
+ large piece of dog manure onto my carpet. What is worse, it has wormed its way into common usage in our
70
+ community, even in documentation. A lot of this happened in the early days of Rails, when fate dumped a huge
71
+ influx of newbies onto the Ruby community. Not to disparage the Rails people in general, but at the time this
72
+ felt much the same as it did back when AOL (America Online) made its debut and dumped millions of (insert
73
+ noun here) into the Internet and Usenet communities.
74
+
75
+ It's impossible to stop this usage now (like so many other usages in the English language having nothing to do
76
+ with computing). But I still protest, and I still stand against it.
77
+
78
+ The term "monkeypatching" appears only once in more than 800 pages of The Ruby Way. It occurs when I
79
+ say I don't condone this term, and it won't be used further in the book.
80
+
81
+ As an aside: The "refinements" which exist in recent versions of Ruby make open classes stricter and safer. I'll blog
82
+ about that later. But this isn't much of a technical post. It's just a reminiscence and a rant.
83
+
84
+ So basically I hate the term "monkeypatching." I am polite to people who say it to me (e.g., in asking a question), but
85
+ secretly I want to just ignore them.
86
+
87
+ The last time I saw Jim Weirich, in New Orleans, he and I talked about this. He agreed it was a pejorative term,
88
+ and it was a shame it had entered the common dialect, though there was really nothing to do about it. But being
89
+ much more level-headed and good-natured than I am, he wasn't bothered much by it.
90
+
91
+ I really miss Jim, by the way. He was a truly brilliant developer and an amiable and wonderful person in general.
92
+ If it would bring him back, I would gladly change the book's name to The Art of Monkeypatching.
@@ -0,0 +1,7 @@
1
+ num 0009
2
+ title Announcement coming soon...
3
+ date 2015-08-11
4
+ pubdate 2015-08-11
5
+ views computing
6
+ tags
7
+ pinned
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Announcement coming soon...</title>
6
+ <meta name="generator" content="Scriptorium Import">
7
+ <meta property="og:title" content="Announcement coming soon...">
8
+ <meta property="og:locale" content="en_US">
9
+ <meta property="og:type" content="article">
10
+ <meta property="article:published_time" content="2015-08-11">
11
+ </head>
12
+ <body>
13
+ <article>
14
+ <header>
15
+ <h1>Announcement coming soon...</h1>
16
+ <time datetime="2015-08-11">August 11, 2015</time>
17
+ </header>
18
+
19
+ <div class="content">
20
+ <p>
21
+ Maybe this will stir your curiosity a little. I hope it does.
22
+ I've started working on a project with someone else, and I
23
+ think it will be really worthwhile.
24
+ This will be launched within 48 hours and announced at the
25
+ Lone Star Ruby Conference in Austin, Texas (October 15).
26
+ Maybe it will be leaked a little before then, too.
27
+
28
+ <p>
29
+ Sit tight 48 hours or so...
30
+ </div>
31
+ </article>
32
+ </body>
33
+ </html>
@@ -0,0 +1,19 @@
1
+ .h1 Announcement coming soon...
2
+
3
+ .set post.num = 0009
4
+ .set post.slug = announcement-coming-soon
5
+ .set post.date = 2015-08-11
6
+ .set post.title = Announcement coming soon...
7
+ .set post.tags =
8
+ .set post.views = computing
9
+ .set post.published = yes
10
+ .set post.deployed = no
11
+
12
+ Maybe this will stir your curiosity a little. I hope it does.
13
+ I've started working on a project with someone else, and I
14
+ think it will be really worthwhile.
15
+ This will be launched within 48 hours and announced at the
16
+ Lone Star Ruby Conference in Austin, Texas (October 15).
17
+ Maybe it will be leaked a little before then, too.
18
+
19
+ Sit tight 48 hours or so...
@@ -0,0 +1,7 @@
1
+ num 0010
2
+ title Immutable data (ditching the wax tablet)
3
+ date 2015-08-25
4
+ pubdate 2015-08-25
5
+ views computing
6
+ tags
7
+ pinned
@@ -0,0 +1,175 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Immutable data (ditching the wax tablet)</title>
6
+ <meta name="generator" content="Scriptorium Import">
7
+ <meta property="og:title" content="Immutable data (ditching the wax tablet)">
8
+ <meta property="og:locale" content="en_US">
9
+ <meta property="og:type" content="article">
10
+ <meta property="article:published_time" content="2015-08-25">
11
+ </head>
12
+ <body>
13
+ <article>
14
+ <header>
15
+ <h1>Immutable data (ditching the wax tablet)</h1>
16
+ <time datetime="2015-08-25">August 25, 2015</time>
17
+ </header>
18
+
19
+ <div class="content">
20
+ <p>
21
+ A couple of weeks ago, I went to Phoenix training prior to the Lone Star Ruby
22
+ Conference in Austin. I was talking with Bruce Tate, and he shared with me
23
+ some thoughts about functional programming in general.
24
+ Obviously Bruce isn't responsible if I misquote him. My memory is faulty.
25
+
26
+ <p>
27
+ "Functional programming is the future," he told me, "and OOP is dying."
28
+ He pointed to the ever-increasing popularity of multi-core machines and the
29
+ increasing irrelevance of conserving memory.
30
+
31
+ <p>
32
+ He said that OOP was all about optimizing for memory usage, and that was
33
+ no longer such a big concern. I wasn't sure what he meant. I thought about it
34
+ later, and decided I was probably missing some profound points.
35
+
36
+ <p>
37
+ But at the same time, I thought I saw something with a clarity that I hadn't
38
+ before. I have wrestled with the concepts of FP over the last year or two; as
39
+ a procedural and OOP type, it hasn't always fit into my brain quickly or
40
+ easily.
41
+
42
+ <p>
43
+ At times it felt that I was taking a step backwards technologically, back into
44
+ procedural thinking. On the one hand, that isn't really true. On the other
45
+ hand, I think we all know what backtracking is for. If you've ever gotten lost
46
+ in a strange town, you know that sometimes you have to back up to a known
47
+ point and try going off in a different direction.
48
+
49
+ <p>
50
+ If you're interested, you could make some fine analogies here between human
51
+ technological advances and things like game theory and machine learning. It's
52
+ hard to imagine navigating a maze or implementing a chess-playing program
53
+ without the concept of backtracking. But that's not my point here.
54
+
55
+ <p>
56
+ One of the key concepts in functional programming, as I understand it, is that
57
+ of immutable data. I have spent hours puzzling over this, because it hasn't
58
+ been immediately intuitive to me.
59
+
60
+ <p>
61
+ There was a quote I read once that the GOTO statement caused difficulties
62
+ because it left us with the question, "How did I get here?" And mutable data
63
+ leaves us with the question, "How did I get to this state?" That made sense
64
+ to me, at least a little.
65
+
66
+ <p>
67
+ It got me to thinking about a more remote time, when I taught programming
68
+ concepts to beginners (using BASIC). In an effort to explain how a program
69
+ worked, I would run through an exercise on the whiteboard which I called
70
+ "playing computer." Variables were represented by little boxes which more or
71
+ less corresponded to memory locations. As I manually stepped through the execution
72
+ of some simple program, I would erase and update the contents of these boxes.
73
+
74
+ <p>
75
+ It was nice and effective, but I sometimes did it another way. I expressed the
76
+ same information in the form of a table, with variable names across the
77
+ columns and time increasing down the rows. This made it clear not just what
78
+ values the variables had, but what values they used to have (and how/when they
79
+ changed).
80
+
81
+ <p>
82
+ As an aside, I'm one of those people who believes that an education should not
83
+ be merely deep but also broad. I believe a good vocabulary, like a good
84
+ education in general, enhances our experience of life.
85
+
86
+ <p>
87
+ And as I thought about my old whiteboard shenanigans, the word that came to me
88
+ was <i>palimpsest</i> -- a beautiful, useful, poetic word that we rarely see nowadays.
89
+ It's sometimes used figuratively; but the literal definition is <i>(a</i> document on )
90
+ <i>(which</i> the original writing has been erased and replaced with new writing).
91
+
92
+ <p>
93
+ I thought about the many older modes of writing, such as clay and wax tablets
94
+ and papyrus. Some materials such as papyrus and parchment (vellum) were rather
95
+ limited in availability or moderately labor-intensive to produce; people wanted
96
+ to re-use them. It was natural to wipe (or scrape or clean) such a material
97
+ once the writing on it was no longer relevant. The term "blank slate" <i>((tabula</i> rasa))
98
+ was once very literal; the stuff we wrote on was the same as the building material.
99
+
100
+ <p>
101
+ By the way, what is deemed relevant may change over the course of 1,000 or 2,000
102
+ years. Many an archaeologist or linguist has spent countless frustrating hours
103
+ trying to decipher the original writing under some later inscription. In a
104
+ similar way, art experts have gone to enormous lengths to uncover artworks
105
+ which someone painted over rather than start a new canvas.
106
+
107
+ <p>
108
+ But what if writing materials were cheap? Today we are much more likely to
109
+ have notepads on our desks than little erasable slates or wax tablets.
110
+
111
+ <p>
112
+ Let's extend the analogy to computer memory. There was a time, perhaps four
113
+ decades ago, when it was expensive and limited in availabilty. I recall seeing
114
+ an information sheet about a mainframe ("What's a mainframe?" asks everyone
115
+ under 40) that listed its specs, almost bragging about its memory, which was
116
+ 448K. Yes, that is less than half a meg. That computer ran a medium-sized
117
+ university. Within seven years, of course, people were carrying around floppy
118
+ disks that held three times that much. ("What's a floppy disk?" asks everyone
119
+ under 30.)
120
+
121
+ <p>
122
+ It was only ten years or so prior to that time that the world saw the creation
123
+ of this curious thing called UNIX (a play on the name MULTICS). Some of you
124
+ reading this may have wondered (or not) why UNIX and its offspring stored a
125
+ conceptual newline as a single linefeed character (rather than the somewhat
126
+ more sensible "carriage return + linefeed" combination. The answer is that
127
+ the designers wanted to save RAM and disk space. For every line of text, they
128
+ saved an entire byte in this way. When a linefeed was sent to a device such
129
+ as a terminal or printer, the OS typically converted it to a "real" CRLF pair.
130
+ This all happened because memory was scarce and expensive.
131
+
132
+ <p>
133
+ It isn't true anymore. In some cases, we may have learned bad habits and
134
+ forgotten how to conserve memory. But in general, we have more imortant things
135
+ to worry about now.
136
+
137
+ <p>
138
+ But let's think a minute. If memory is cheap and available, why are we
139
+ turning it into a palimpsest? Isn't there something to be said for the idea of
140
+ leaving data alone, never overwriting information, always writing new data
141
+ somewhere else?
142
+
143
+ <p>
144
+ If we do that, we have a "history" of what has happened in program execution,
145
+ like a trail of breadcrumbs. More importantly, pieces of code that run
146
+ concurrently need not worry about stepping on each other's data. One process
147
+ (or thread or fiber) will never write over an item that another process is
148
+ reading. If this doesn't eliminate synchronization issues, it at least
149
+ mitigates them greatly.
150
+
151
+ <p>
152
+ So I'm starting to see where immutable data could be a good thing. And I'm
153
+ starting to see how it's good for concurrency. And concurrency really matters,
154
+ because it is the limiting factor of this generation of computing just as
155
+ memory scarcity was a limiting factor one or two generations ago.
156
+
157
+ <p>
158
+ In fact, I'll speculate a little about memory in general. Let's look 10, 20,
159
+ or even 50 years into the future. (My crystal ball, like everyone else's, is
160
+ very cloudy.)
161
+
162
+ <p>
163
+ I can imagine a time when memory is simply never erased at all. We're seeing
164
+ the crude beginnings of this already. Source control systems and databases
165
+ preserve far more history than they used to. My laptop's OS encourages me to
166
+ think of my backed-up data as a sort of limitless archive of past versions of
167
+ files. It's mostly an illusion, but it needn't always be. Why should any
168
+ document, any image, any video ever be erased?
169
+
170
+ <p>
171
+ Food for thought. Chow down, friends.
172
+ </div>
173
+ </article>
174
+ </body>
175
+ </html>